From 057a4c536f4b6e461d859a16e37759ce3527c9bc Mon Sep 17 00:00:00 2001 From: Skye <me@skye.vg> Date: Tue, 12 Nov 2024 17:02:36 +0900 Subject: [PATCH] format everything --- .../hexcasting/annotations/SoftImplement.java | 24 +- .../java/at/petrak/hexcasting/api/HexAPI.java | 400 +++-- .../hexcasting/api/addldata/ADHexHolder.java | 16 +- .../hexcasting/api/addldata/ADIotaHolder.java | 43 +- .../api/addldata/ADMediaHolder.java | 181 +-- .../hexcasting/api/addldata/ADPigment.java | 57 +- .../api/addldata/ADVariantItem.java | 6 +- .../ItemDelegatingEntityIotaHolder.java | 129 +- .../hexcasting/api/addldata/package-info.java | 11 +- .../FailToCastGreatSpellTrigger.java | 65 +- .../advancements/HexAdvancementTriggers.java | 17 +- .../api/advancements/MinMaxLongs.java | 123 +- .../api/advancements/OvercastTrigger.java | 134 +- .../api/advancements/SpendMediaTrigger.java | 109 +- .../hexcasting/api/block/HexBlockEntity.java | 71 +- .../block/circle/BlockAbstractImpetus.java | 133 +- .../block/circle/BlockCircleComponent.java | 156 +- .../api/casting/ActionRegistryEntry.java | 11 +- .../hexcasting/api/casting/ActionUtils.kt | 446 ++--- .../hexcasting/api/casting/ParticleSpray.kt | 39 +- .../api/casting/PatternShapeMatch.java | 91 +- .../hexcasting/api/casting/RenderedSpell.kt | 10 +- .../hexcasting/api/casting/SpellList.kt | 145 +- .../api/casting/arithmetic/Arithmetic.java | 5 +- .../api/casting/arithmetic/IterPair.java | 8 +- .../casting/arithmetic/TripleIterable.java | 76 +- .../arithmetic/engine/ArithmeticEngine.java | 193 ++- .../casting/arithmetic/engine/HashCons.java | 1 - .../engine/InvalidOperatorException.java | 21 +- .../engine/NoOperatorCandidatesException.java | 63 +- .../casting/arithmetic/operator/Operator.kt | 51 +- .../arithmetic/operator/OperatorBasic.kt | 50 +- .../arithmetic/operator/OperatorBinary.java | 11 +- .../arithmetic/operator/OperatorUnary.java | 11 +- .../predicates/IotaMultiPredicate.java | 42 +- .../arithmetic/predicates/IotaPredicate.java | 20 +- .../api/casting/castables/Action.kt | 87 +- .../api/casting/castables/ConstMediaAction.kt | 67 +- .../api/casting/castables/OperationAction.kt | 25 +- .../api/casting/castables/SpecialHandler.java | 52 +- .../api/casting/castables/SpellAction.kt | 117 +- .../circles/BlockEntityAbstractImpetus.java | 841 +++++----- .../casting/circles/CircleExecutionState.java | 601 +++---- .../api/casting/circles/ICircleComponent.java | 298 ++-- .../hexcasting/api/casting/eval/CastResult.kt | 18 +- .../api/casting/eval/CastingEnvironment.java | 1100 ++++++------- .../eval/CastingEnvironmentComponent.java | 98 +- .../api/casting/eval/ExecutionClientView.kt | 17 +- .../api/casting/eval/MishapEnvironment.java | 57 +- .../api/casting/eval/OperationResult.kt | 12 +- .../api/casting/eval/ResolvedPattern.kt | 39 +- .../api/casting/eval/ResolvedPatternType.kt | 24 +- .../api/casting/eval/SpecialPatterns.java | 8 +- .../api/casting/eval/SpellCircleContext.kt | 102 +- .../api/casting/eval/env/CircleCastEnv.java | 379 +++-- .../api/casting/eval/env/CircleMishapEnv.java | 46 +- .../casting/eval/env/PackagedItemCastEnv.java | 135 +- .../casting/eval/env/PlayerBasedCastEnv.java | 332 ++-- .../eval/env/PlayerBasedMishapEnv.java | 91 +- .../api/casting/eval/env/StaffCastEnv.java | 254 ++- .../api/casting/eval/env/package-info.java | 2 +- .../casting/eval/sideeffects/EvalSound.java | 13 +- .../eval/sideeffects/OperatorSideEffect.kt | 98 +- .../api/casting/eval/vm/CastingImage.kt | 241 ++- .../api/casting/eval/vm/CastingVM.kt | 524 +++--- .../api/casting/eval/vm/ContinuationFrame.kt | 153 +- .../api/casting/eval/vm/FrameEvaluate.kt | 101 +- .../api/casting/eval/vm/FrameFinishEval.kt | 54 +- .../api/casting/eval/vm/FrameForEach.kt | 172 +- .../api/casting/eval/vm/FunctionalData.kt | 15 +- .../api/casting/eval/vm/SpellContinuation.kt | 70 +- .../api/casting/iota/BooleanIota.java | 89 +- .../api/casting/iota/ContinuationIota.java | 126 +- .../api/casting/iota/DoubleIota.java | 92 +- .../api/casting/iota/EntityIota.java | 154 +- .../api/casting/iota/GarbageIota.java | 97 +- .../hexcasting/api/casting/iota/Iota.java | 196 ++- .../hexcasting/api/casting/iota/IotaType.java | 368 ++--- .../hexcasting/api/casting/iota/ListIota.java | 219 +-- .../hexcasting/api/casting/iota/NullIota.java | 90 +- .../api/casting/iota/PatternIota.java | 307 ++-- .../hexcasting/api/casting/iota/Vec3Iota.java | 110 +- .../api/casting/math/EulerPathFinder.kt | 147 +- .../hexcasting/api/casting/math/HexAngle.kt | 12 +- .../hexcasting/api/casting/math/HexCoord.kt | 107 +- .../hexcasting/api/casting/math/HexDir.kt | 67 +- .../hexcasting/api/casting/math/HexPattern.kt | 325 ++-- .../hexcasting/api/casting/mishaps/Mishap.kt | 190 +-- .../mishaps/MishapAlreadyBrainswept.kt | 18 +- .../api/casting/mishaps/MishapBadBlock.kt | 38 +- .../casting/mishaps/MishapBadBrainsweep.kt | 20 +- .../api/casting/mishaps/MishapBadCaster.kt | 14 +- .../api/casting/mishaps/MishapBadEntity.kt | 31 +- .../api/casting/mishaps/MishapBadItem.kt | 30 +- .../api/casting/mishaps/MishapBadLocation.kt | 14 +- .../casting/mishaps/MishapBadOffhandItem.kt | 33 +- .../casting/mishaps/MishapDisallowedSpell.kt | 15 +- .../api/casting/mishaps/MishapDivideByZero.kt | 165 +- .../casting/mishaps/MishapEntityTooFarAway.kt | 14 +- .../api/casting/mishaps/MishapEvalTooMuch.kt | 13 +- .../api/casting/mishaps/MishapImmuneEntity.kt | 14 +- .../mishaps/MishapInternalException.kt | 14 +- .../api/casting/mishaps/MishapInvalidIota.kt | 55 +- .../mishaps/MishapInvalidOperatorArgs.kt | 48 +- .../casting/mishaps/MishapInvalidPattern.kt | 15 +- .../mishaps/MishapInvalidSpellDatumType.kt | 22 +- .../mishaps/MishapLocationInWrongDimension.kt | 21 +- .../casting/mishaps/MishapNoAkashicRecord.kt | 14 +- .../casting/mishaps/MishapNotEnoughArgs.kt | 17 +- .../casting/mishaps/MishapNotEnoughMedia.kt | 17 +- .../api/casting/mishaps/MishapOthersName.kt | 90 +- .../api/casting/mishaps/MishapStackSize.kt | 18 +- .../mishaps/MishapTooManyCloseParens.kt | 17 +- .../casting/mishaps/MishapUnenlightened.kt | 41 +- .../casting/mishaps/MishapUnescapedValue.kt | 46 +- .../circle/MishapBoolDirectrixEmptyStack.kt | 18 +- .../circle/MishapBoolDirectrixNotBool.kt | 20 +- .../mishaps/circle/MishapNoSpellCircle.kt | 51 +- .../api/client/ClientCastingStack.kt | 113 +- .../api/client/ClientRenderHelper.kt | 154 +- .../api/client/HexPatternRenderHolder.kt | 24 +- .../client/ScryingLensOverlayRegistry.java | 152 +- .../hexcasting/api/item/HexHolderItem.java | 22 +- .../hexcasting/api/item/IotaHolderItem.java | 183 +-- .../hexcasting/api/item/MediaHolderItem.java | 90 +- .../hexcasting/api/item/PigmentItem.java | 11 +- .../hexcasting/api/item/VariantItem.java | 37 +- .../api/misc/DiscoveryHandlers.java | 32 +- .../hexcasting/api/misc/MediaConstants.java | 10 +- .../at/petrak/hexcasting/api/misc/Result.java | 128 +- .../hexcasting/api/misc/TriPredicate.java | 6 +- .../hexcasting/api/mod/HexApiMessages.java | 66 +- .../petrak/hexcasting/api/mod/HexConfig.java | 244 +-- .../hexcasting/api/mod/HexStatistics.java | 42 +- .../at/petrak/hexcasting/api/mod/HexTags.java | 146 +- .../hexcasting/api/pigment/ColorProvider.java | 85 +- .../hexcasting/api/pigment/FrozenPigment.java | 71 +- .../hexcasting/api/player/AltioraAbility.java | 10 +- .../hexcasting/api/player/FlightAbility.java | 6 +- .../hexcasting/api/player/Sentinel.java | 7 +- .../petrak/hexcasting/api/utils/HexUtils.kt | 423 ++--- .../petrak/hexcasting/api/utils/MathUtils.kt | 54 +- .../hexcasting/api/utils/MediaHelper.kt | 118 +- .../at/petrak/hexcasting/api/utils/NBTDsl.kt | 468 +++--- .../petrak/hexcasting/api/utils/NBTHelper.kt | 274 +++- .../hexcasting/client/ClientTickCounter.java | 30 +- .../client/PatternShapeMatcher.java | 3 +- .../client/RegisterClientStuff.java | 511 +++--- .../client/ShiftScrollListener.java | 97 +- .../client/entity/WallScrollRenderer.java | 261 +-- .../hexcasting/client/gui/GuiSpellcasting.kt | 995 +++++------ .../client/gui/PatternTooltipComponent.java | 143 +- .../client/ktxt/ClientAccessorWrappers.kt | 5 +- .../hexcasting/client/model/AltioraLayer.java | 74 +- .../client/model/HexModelLayers.java | 49 +- .../client/model/HexRobesModels.java | 130 +- ...yOwnArmorModelWithBlackjackAndHookers.java | 146 +- .../client/particles/ConjureParticle.java | 216 +-- .../client/render/GaslightingTracker.java | 34 +- .../client/render/HexAdditionalRenderers.java | 379 +++-- .../client/render/HexPatternLike.java | 95 +- .../client/render/HexPatternPoints.java | 270 +-- .../client/render/PatternColors.java | 120 +- .../client/render/PatternRenderer.java | 346 ++-- .../client/render/PatternSettings.java | 351 ++-- .../client/render/PatternTextureManager.java | 286 ++-- .../hexcasting/client/render/RenderLib.kt | 763 ++++----- .../client/render/ScryingLensOverlays.java | 442 ++--- .../hexcasting/client/render/VCDrawHelper.kt | 269 +-- .../render/WorldlyPatternRenderHelpers.java | 322 ++-- .../BlockEntityAkashicBookshelfRenderer.java | 35 +- .../be/BlockEntityQuenchedAllayRenderer.java | 92 +- .../render/be/BlockEntitySlateRenderer.java | 28 +- .../render/shader/FakeBufferSource.java | 39 +- .../client/render/shader/HexRenderTypes.java | 75 +- .../client/render/shader/HexShaders.java | 31 +- .../client/sound/GridSoundInstance.kt | 96 +- .../common/blocks/BlockConjured.java | 212 +-- .../common/blocks/BlockConjuredLight.java | 116 +- .../common/blocks/BlockFlammable.java | 43 +- .../common/blocks/BlockQuenchedAllay.java | 67 +- .../blocks/akashic/AkashicFloodfiller.java | 101 +- .../blocks/akashic/BlockAkashicBookshelf.java | 138 +- .../blocks/akashic/BlockAkashicLigature.java | 6 +- .../blocks/akashic/BlockAkashicRecord.java | 97 +- .../akashic/BlockEntityAkashicBookshelf.java | 131 +- .../common/blocks/behavior/HexComposting.java | 22 +- .../blocks/behavior/HexStrippables.java | 21 +- .../blocks/circles/BlockEmptyImpetus.java | 101 +- .../blocks/circles/BlockEntitySlate.java | 54 +- .../common/blocks/circles/BlockSlate.java | 423 ++--- .../directrix/BlockBooleanDirectrix.java | 226 +-- .../directrix/BlockEmptyDirectrix.java | 109 +- .../directrix/BlockRedstoneDirectrix.java | 210 +-- .../impetuses/BlockEntityLookingImpetus.java | 135 +- .../impetuses/BlockEntityRedstoneImpetus.java | 246 +-- .../BlockEntityRightClickImpetus.java | 6 +- .../impetuses/BlockLookingImpetus.java | 52 +- .../impetuses/BlockRedstoneImpetus.java | 139 +- .../impetuses/BlockRightClickImpetus.java | 50 +- .../blocks/decoration/BlockAkashicLeaves.java | 33 +- .../blocks/decoration/BlockAkashicLog.java | 34 +- .../decoration/BlockAmethystDirectional.java | 48 +- .../common/blocks/decoration/BlockAxis.java | 6 +- .../blocks/decoration/BlockHexDoor.java | 35 +- .../blocks/decoration/BlockHexFence.java | 33 +- .../blocks/decoration/BlockHexFenceGate.java | 34 +- .../decoration/BlockHexPressurePlate.java | 34 +- .../blocks/decoration/BlockHexSlab.java | 34 +- .../blocks/decoration/BlockHexStairs.java | 33 +- .../blocks/decoration/BlockHexTrapdoor.java | 33 +- .../blocks/decoration/BlockHexWoodButton.java | 34 +- .../common/blocks/decoration/BlockSconce.java | 196 ++- .../blocks/entity/BlockEntityConjured.java | 188 ++- .../entity/BlockEntityQuenchedAllay.java | 32 +- .../casting/PatternRegistryManifest.java | 226 +-- .../common/casting/actions/OpEntityHeight.kt | 12 +- .../common/casting/actions/OpEntityLook.kt | 12 +- .../common/casting/actions/OpEntityPos.kt | 12 +- .../casting/actions/OpEntityVelocity.kt | 14 +- .../casting/actions/akashic/OpAkashicRead.kt | 24 +- .../casting/actions/akashic/OpAkashicWrite.kt | 90 +- .../casting/actions/circles/OpCircleBounds.kt | 21 +- .../casting/actions/circles/OpImpetusDir.kt | 17 +- .../casting/actions/circles/OpImpetusPos.kt | 11 +- .../common/casting/actions/eval/OpEval.kt | 51 +- .../casting/actions/eval/OpEvalBreakable.kt | 18 +- .../common/casting/actions/eval/OpForEach.kt | 27 +- .../common/casting/actions/eval/OpHalt.kt | 43 +- .../common/casting/actions/eval/OpThanos.kt | 21 +- .../common/casting/actions/lists/OpAppend.kt | 15 +- .../common/casting/actions/lists/OpConcat.kt | 15 +- .../common/casting/actions/lists/OpCons.kt | 13 +- .../casting/actions/lists/OpEmptyList.kt | 9 +- .../common/casting/actions/lists/OpIndex.kt | 15 +- .../common/casting/actions/lists/OpIndexOf.kt | 14 +- .../casting/actions/lists/OpLastNToList.kt | 33 +- .../casting/actions/lists/OpListSize.kt | 9 +- .../casting/actions/lists/OpModifyInPlace.kt | 15 +- .../common/casting/actions/lists/OpRemove.kt | 19 +- .../casting/actions/lists/OpReverski.kt | 13 +- .../casting/actions/lists/OpSingleton.kt | 9 +- .../common/casting/actions/lists/OpSlice.kt | 18 +- .../common/casting/actions/lists/OpSplat.kt | 8 +- .../common/casting/actions/lists/OpUnCons.kt | 17 +- .../casting/actions/local/OpPeekLocal.kt | 29 +- .../casting/actions/local/OpPushLocal.kt | 25 +- .../common/casting/actions/math/OpAbsLen.kt | 12 +- .../common/casting/actions/math/OpAdd.kt | 38 +- .../common/casting/actions/math/OpCeil.kt | 14 +- .../casting/actions/math/OpCoerceToAxial.kt | 27 +- .../casting/actions/math/OpConstructVec.kt | 15 +- .../casting/actions/math/OpDeconstructVec.kt | 11 +- .../common/casting/actions/math/OpDivCross.kt | 58 +- .../common/casting/actions/math/OpFloor.kt | 12 +- .../common/casting/actions/math/OpLog.kt | 18 +- .../common/casting/actions/math/OpModulo.kt | 19 +- .../common/casting/actions/math/OpMulDot.kt | 37 +- .../common/casting/actions/math/OpPowProj.kt | 69 +- .../common/casting/actions/math/OpRandom.kt | 10 +- .../common/casting/actions/math/OpSub.kt | 37 +- .../math/SpecialHandlerNumberLiteral.kt | 114 +- .../common/casting/actions/math/bit/OpAnd.kt | 28 +- .../common/casting/actions/math/bit/OpNot.kt | 10 +- .../common/casting/actions/math/bit/OpOr.kt | 28 +- .../casting/actions/math/bit/OpToSet.kt | 22 +- .../common/casting/actions/math/bit/OpXor.kt | 40 +- .../casting/actions/math/logic/OpBoolAnd.kt | 12 +- .../casting/actions/math/logic/OpBoolIf.kt | 14 +- .../casting/actions/math/logic/OpBoolNot.kt | 10 +- .../casting/actions/math/logic/OpBoolOr.kt | 12 +- .../actions/math/logic/OpBoolToNumber.kt | 10 +- .../casting/actions/math/logic/OpBoolXor.kt | 12 +- .../actions/math/logic/OpCoerceToBool.kt | 8 +- .../casting/actions/math/logic/OpCompare.kt | 18 +- .../casting/actions/math/logic/OpEquality.kt | 12 +- .../casting/actions/math/trig/OpArcCos.kt | 12 +- .../casting/actions/math/trig/OpArcSin.kt | 12 +- .../casting/actions/math/trig/OpArcTan.kt | 12 +- .../casting/actions/math/trig/OpArcTan2.kt | 14 +- .../common/casting/actions/math/trig/OpCos.kt | 12 +- .../common/casting/actions/math/trig/OpSin.kt | 12 +- .../common/casting/actions/math/trig/OpTan.kt | 15 +- .../actions/raycast/OpBlockAxisRaycast.kt | 48 +- .../casting/actions/raycast/OpBlockRaycast.kt | 58 +- .../actions/raycast/OpEntityRaycast.kt | 130 +- .../common/casting/actions/rw/OpRead.kt | 43 +- .../common/casting/actions/rw/OpReadable.kt | 23 +- .../casting/actions/rw/OpTheCoolerRead.kt | 27 +- .../casting/actions/rw/OpTheCoolerReadable.kt | 23 +- .../casting/actions/rw/OpTheCoolerWritable.kt | 21 +- .../casting/actions/rw/OpTheCoolerWrite.kt | 79 +- .../common/casting/actions/rw/OpWritable.kt | 22 +- .../common/casting/actions/rw/OpWrite.kt | 78 +- .../casting/actions/selectors/OpGetCaster.kt | 13 +- .../actions/selectors/OpGetEntitiesBy.kt | 69 +- .../actions/selectors/OpGetEntityAt.kt | 28 +- .../casting/actions/spells/OpAddMotion.kt | 92 +- .../common/casting/actions/spells/OpBeep.kt | 48 +- .../common/casting/actions/spells/OpBlink.kt | 88 +- .../casting/actions/spells/OpBreakBlock.kt | 68 +- .../casting/actions/spells/OpColorize.kt | 43 +- .../casting/actions/spells/OpConjureBlock.kt | 85 +- .../casting/actions/spells/OpCreateFluid.kt | 79 +- .../casting/actions/spells/OpCycleVariant.kt | 35 +- .../casting/actions/spells/OpDestroyFluid.kt | 207 ++- .../casting/actions/spells/OpEdifySapling.kt | 77 +- .../common/casting/actions/spells/OpErase.kt | 73 +- .../casting/actions/spells/OpExplode.kt | 83 +- .../casting/actions/spells/OpExtinguish.kt | 204 +-- .../common/casting/actions/spells/OpFlight.kt | 384 +++-- .../common/casting/actions/spells/OpIgnite.kt | 111 +- .../casting/actions/spells/OpMakeBattery.kt | 101 +- .../actions/spells/OpMakePackagedSpell.kt | 107 +- .../casting/actions/spells/OpPlaceBlock.kt | 159 +- .../casting/actions/spells/OpPotionEffect.kt | 75 +- .../common/casting/actions/spells/OpPrint.kt | 46 +- .../casting/actions/spells/OpRecharge.kt | 115 +- .../OpTheOnlyReasonAnyoneDownloadedPsi.kt | 48 +- .../casting/actions/spells/great/OpAltiora.kt | 119 +- .../actions/spells/great/OpBrainsweep.kt | 100 +- .../actions/spells/great/OpLightning.kt | 43 +- .../actions/spells/great/OpTeleport.kt | 233 +-- .../casting/actions/spells/great/OpWeather.kt | 49 +- .../spells/sentinel/OpCreateSentinel.kt | 46 +- .../spells/sentinel/OpDestroySentinel.kt | 42 +- .../spells/sentinel/OpGetSentinelPos.kt | 22 +- .../spells/sentinel/OpGetSentinelWayfind.kt | 24 +- .../OpAlwinfyHasAscendedToABeingOfPureMath.kt | 92 +- .../casting/actions/stack/OpDuplicateN.kt | 24 +- .../casting/actions/stack/OpFisherman.kt | 57 +- .../actions/stack/OpFishermanButItCopies.kt | 35 +- .../common/casting/actions/stack/OpMask.kt | 19 +- .../casting/actions/stack/OpStackSize.kt | 16 +- .../casting/actions/stack/OpTwiddling.kt | 10 +- .../actions/stack/SpecialHandlerMask.kt | 123 +- .../arithmetic/BitwiseSetArithmetic.kt | 52 +- .../casting/arithmetic/BoolArithmetic.kt | 87 +- .../casting/arithmetic/DoubleArithmetic.kt | 125 +- .../casting/arithmetic/ListArithmetic.kt | 72 +- .../casting/arithmetic/ListSetArithmetic.kt | 43 +- .../casting/arithmetic/Vec3Arithmetic.java | 43 +- .../arithmetic/operator/OperatorLog.kt | 19 +- .../arithmetic/operator/OperatorUtils.kt | 92 +- .../operator/list/OperatorAppend.kt | 18 +- .../arithmetic/operator/list/OperatorIndex.kt | 23 +- .../operator/list/OperatorIndexOf.kt | 18 +- .../operator/list/OperatorRemove.kt | 26 +- .../operator/list/OperatorReplace.kt | 27 +- .../arithmetic/operator/list/OperatorSlice.kt | 32 +- .../operator/list/OperatorUnCons.kt | 16 +- .../operator/list/OperatorUnappend.kt | 15 +- .../operator/list/OperatorUnique.kt | 27 +- .../arithmetic/operator/vec/OperatorPack.java | 19 +- .../operator/vec/OperatorUnpack.java | 10 +- .../operator/vec/OperatorVec3Delegating.java | 44 +- .../common/command/BrainsweepCommand.java | 60 +- .../command/ListPerWorldPatternsCommand.java | 309 ++-- .../common/command/PatternResLocArgument.java | 66 +- .../command/PatternTexturesCommand.java | 52 +- .../common/command/RecalcPatternsCommand.java | 29 +- .../common/entities/EntityWallScroll.java | 343 ++-- .../common/entities/HexEntities.java | 49 +- .../hexcasting/common/impl/HexAPIImpl.java | 246 ++- .../common/items/HexBaubleItem.java | 2 +- .../common/items/ItemJewelerHammer.java | 15 +- .../hexcasting/common/items/ItemLens.java | 102 +- .../common/items/ItemLoreFragment.java | 120 +- .../hexcasting/common/items/ItemStaff.java | 73 +- .../common/items/armor/ItemRobes.java | 17 +- .../items/magic/DebugUnlockerHolder.java | 98 +- .../common/items/magic/ItemArtifact.java | 42 +- .../items/magic/ItemCreativeUnlocker.java | 503 +++--- .../common/items/magic/ItemCypher.java | 42 +- .../common/items/magic/ItemMediaBattery.java | 34 +- .../common/items/magic/ItemMediaHolder.java | 207 +-- .../common/items/magic/ItemPackagedHex.java | 295 ++-- .../common/items/magic/ItemTrinket.java | 42 +- .../pigment/ItemAmethystAndCopperPigment.java | 45 +- .../common/items/pigment/ItemDyePigment.java | 51 +- .../items/pigment/ItemPridePigment.java | 98 +- .../common/items/pigment/ItemUUIDPigment.java | 105 +- .../common/items/storage/ItemAbacus.java | 93 +- .../common/items/storage/ItemFocus.java | 146 +- .../common/items/storage/ItemScroll.java | 264 +-- .../common/items/storage/ItemSlate.java | 200 +-- .../common/items/storage/ItemSpellbook.java | 481 +++--- .../common/items/storage/ItemThoughtKnot.java | 83 +- .../hexcasting/common/lib/HexAttributes.java | 66 +- .../common/lib/HexBlockEntities.java | 120 +- .../common/lib/HexBlockSetTypes.java | 27 +- .../hexcasting/common/lib/HexBlocks.java | 625 +++---- .../hexcasting/common/lib/HexCommands.java | 16 +- .../common/lib/HexConfiguredFeatures.java | 16 +- .../common/lib/HexCreativeTabs.java | 46 +- .../hexcasting/common/lib/HexDamageTypes.java | 19 +- .../common/lib/HexFeatureConfigs.java | 65 +- .../hexcasting/common/lib/HexItems.java | 431 ++--- .../common/lib/HexLootFunctions.java | 47 +- .../hexcasting/common/lib/HexMobEffects.java | 66 +- .../hexcasting/common/lib/HexParticles.java | 72 +- .../hexcasting/common/lib/HexPotions.java | 76 +- .../hexcasting/common/lib/HexRegistries.java | 22 +- .../hexcasting/common/lib/HexSounds.java | 77 +- .../hexcasting/common/lib/hex/HexActions.java | 1448 +++++++++++------ .../common/lib/hex/HexArithmetics.java | 81 +- .../common/lib/hex/HexContinuationTypes.java | 69 +- .../common/lib/hex/HexEvalSounds.java | 66 +- .../common/lib/hex/HexIotaTypes.java | 79 +- .../common/lib/hex/HexSpecialHandlers.java | 44 +- .../common/lib/hex/package-info.java | 6 +- .../loot/AddPerWorldPatternToScrollFunc.java | 95 +- .../common/loot/AmethystReducerFunc.java | 78 +- .../common/loot/HexLootHandler.java | 112 +- .../common/misc/AkashicTreeGrower.java | 26 +- .../common/misc/BrainsweepingEvents.java | 36 +- .../hexcasting/common/misc/HexMobEffect.java | 10 +- .../common/misc/PatternTooltip.java | 4 +- .../common/misc/PlayerPositionRecorder.java | 40 +- .../hexcasting/common/misc/RegisterMisc.java | 70 +- .../hexcasting/common/msgs/IMessage.java | 24 +- .../hexcasting/common/msgs/MsgBeepS2C.java | 98 +- .../hexcasting/common/msgs/MsgBlinkS2C.java | 64 +- .../common/msgs/MsgCastParticleS2C.java | 180 +- .../msgs/MsgClearSpiralPatternsS2C.java | 73 +- .../common/msgs/MsgNewSpellPatternC2S.java | 85 +- .../common/msgs/MsgNewSpellPatternS2C.java | 92 +- .../common/msgs/MsgNewSpiralPatternsS2C.java | 92 +- .../common/msgs/MsgNewWallScrollS2C.java | 94 +- .../common/msgs/MsgOpenSpellGuiS2C.java | 113 +- .../msgs/MsgRecalcWallScrollDisplayS2C.java | 71 +- .../common/msgs/MsgShiftScrollC2S.java | 288 ++-- .../particles/ConjureParticleOptions.java | 91 +- .../common/recipe/BrainsweepRecipe.java | 15 +- .../common/recipe/HexRecipeStuffRegistry.java | 100 +- .../common/recipe/RecipeSerializerBase.java | 38 +- .../common/recipe/SealSpellbookRecipe.java | 76 +- .../common/recipe/SealThingsRecipe.java | 213 ++- .../recipe/ingredient/StateIngredient.java | 36 +- .../ingredient/StateIngredientBlock.java | 122 +- .../ingredient/StateIngredientBlockState.java | 176 +- .../ingredient/StateIngredientBlocks.java | 144 +- .../ingredient/StateIngredientHelper.java | 263 ++- .../recipe/ingredient/StateIngredientTag.java | 22 +- .../StateIngredientTagExcluding.java | 137 +- .../brainsweep/BrainsweepeeIngredient.java | 128 +- .../brainsweep/EntityTagIngredient.java | 227 ++- .../brainsweep/EntityTypeIngredient.java | 168 +- .../brainsweep/VillagerIngredient.java | 464 +++--- .../hexcasting/datagen/HexAdvancements.java | 240 +-- .../hexcasting/datagen/HexLootTables.java | 300 ++-- .../datagen/IXplatConditionsBuilder.java | 4 +- .../hexcasting/datagen/IXplatIngredients.java | 28 +- .../datagen/recipe/HexplatRecipes.java | 1213 ++++++++------ .../builders/BrainsweepRecipeBuilder.java | 52 +- .../builders/CompatIngredientValue.java | 38 +- .../builders/CompatProcessingOutput.java | 27 +- .../builders/CreateCrushingRecipeBuilder.java | 274 ++-- .../FarmersDelightCuttingRecipeBuilder.java | 283 ++-- .../FarmersDelightToolIngredient.java | 2 +- .../recipe/builders/ItemProcessingOutput.java | 35 +- .../recipe/builders/ProcessingOutput.java | 2 +- .../datagen/tag/HexActionTagProvider.java | 84 +- .../datagen/tag/HexBlockTagProvider.java | 297 ++-- .../datagen/tag/HexDamageTypeTagProvider.java | 38 +- .../datagen/tag/HexItemTagProvider.java | 119 +- .../petrak/hexcasting/interop/HexInterop.java | 133 +- .../interop/inline/HexPatternMatcher.java | 152 +- .../hexcasting/interop/inline/InlineHex.java | 6 +- .../interop/inline/InlineHexClient.java | 8 +- .../interop/inline/InlinePatternData.java | 114 +- .../interop/inline/InlinePatternRenderer.java | 149 +- .../patchouli/AbstractPatternComponent.java | 163 +- .../patchouli/BrainsweepProcessor.java | 13 +- .../patchouli/CustomComponentTooltip.java | 71 +- .../patchouli/LookupPatternComponent.java | 69 +- .../patchouli/ManualPatternComponent.java | 80 +- .../patchouli/MultiCraftingProcessor.java | 148 +- .../interop/patchouli/PatchouliUtils.java | 114 +- .../interop/patchouli/PatternProcessor.java | 39 +- .../hexcasting/interop/pehkui/OpGetScale.kt | 12 +- .../hexcasting/interop/pehkui/OpSetScale.kt | 37 +- .../interop/pehkui/PehkuiInterop.java | 24 +- .../interop/utils/PatternDrawingUtil.java | 241 +-- .../interop/utils/PatternEntry.java | 5 +- .../utils/PhialRecipeStackBuilder.java | 92 +- .../hexcasting/ktxt/AccessorWrappers.kt | 40 +- .../mixin/MixinAbstractVillager.java | 14 +- .../hexcasting/mixin/MixinLivingEntity.java | 18 +- .../at/petrak/hexcasting/mixin/MixinMob.java | 28 +- .../petrak/hexcasting/mixin/MixinRaider.java | 14 +- .../hexcasting/mixin/MixinVillager.java | 28 +- .../petrak/hexcasting/mixin/MixinWitch.java | 16 +- .../mixin/accessor/AccessorAbstractArrow.java | 4 +- .../mixin/accessor/AccessorEntity.java | 4 +- .../mixin/accessor/AccessorLivingEntity.java | 32 +- .../mixin/accessor/AccessorLootTable.java | 19 +- .../mixin/accessor/AccessorPotionBrewing.java | 5 +- .../mixin/accessor/AccessorUseOnContext.java | 13 +- .../mixin/accessor/AccessorVillager.java | 8 +- .../accessor/CriteriaTriggersAccessor.java | 8 +- .../AccessorBlockEntityRenderDispatcher.java | 7 +- .../client/AccessorCompositeRenderType.java | 4 +- .../AccessorEmptyTextureStateShard.java | 7 +- .../accessor/client/AccessorMouseHandler.java | 8 +- .../client/AccessorRenderStateShard.java | 4 +- .../accessor/client/AccessorRenderType.java | 17 +- .../mixin/client/MixinClientLevel.java | 70 +- .../mixin/client/MixinPlayerRenderer.java | 19 +- .../server/ScrungledPatternsSave.java | 212 +-- .../xplat/IClientXplatAbstractions.java | 56 +- .../hexcasting/xplat/IForgeLikeBlock.java | 21 +- .../hexcasting/xplat/IXplatAbstractions.java | 195 ++- .../petrak/hexcasting/xplat/IXplatTags.java | 4 +- .../at/petrak/hexcasting/xplat/Platform.java | 3 +- Common/src/test/java/EulerPathFinderTest.kt | 18 +- ...WhatRangeDoTheNoisesOutputAnywaysTest.java | 53 +- .../fabric/FabricHexClientInitializer.kt | 88 +- .../hexcasting/fabric/FabricHexConfig.java | 537 +++--- .../hexcasting/fabric/FabricHexInitializer.kt | 357 ++-- .../hexcasting/fabric/cc/CCAltiora.java | 80 +- .../hexcasting/fabric/cc/CCBrainswept.java | 53 +- .../fabric/cc/CCClientCastingStack.java | 27 +- .../fabric/cc/CCFavoredPigment.java | 50 +- .../petrak/hexcasting/fabric/cc/CCFlight.java | 97 +- .../hexcasting/fabric/cc/CCPatterns.java | 66 +- .../hexcasting/fabric/cc/CCSentinel.java | 93 +- .../fabric/cc/CCStaffcastImage.java | 68 +- .../fabric/cc/HexCardinalComponents.java | 223 +-- .../fabric/cc/adimpl/CCEntityIotaHolder.java | 85 +- .../fabric/cc/adimpl/CCHexHolder.java | 98 +- .../fabric/cc/adimpl/CCIotaHolder.java | 3 +- .../fabric/cc/adimpl/CCItemIotaHolder.java | 107 +- .../fabric/cc/adimpl/CCMediaHolder.java | 243 ++- .../fabric/cc/adimpl/CCPigment.java | 43 +- .../fabric/cc/adimpl/CCVariantItem.java | 52 +- .../hexcasting/fabric/cc/package-info.java | 12 +- .../fabric/client/ExtendedTexture.java | 4 +- .../datagen/HexFabricConditionsBuilder.java | 157 +- .../datagen/HexFabricDataGenerators.java | 301 ++-- .../fabric/event/MouseScrollCallback.java | 29 +- .../event/VillagerConversionCallback.java | 21 +- .../fabric/interop/ModMenuInterop.java | 8 +- .../interop/emi/BrainsweepeeEmiStack.java | 161 +- .../interop/emi/EmiBrainsweepRecipe.java | 115 +- .../fabric/interop/emi/EmiEdifyRecipe.java | 152 +- .../fabric/interop/emi/EmiPhialRecipe.java | 143 +- .../fabric/interop/emi/HexEMIPlugin.java | 46 +- .../interop/emi/PatternRendererEMI.java | 108 +- .../interop/emi/TheCoolerSlotWidget.java | 102 +- .../interop/trinkets/LensTrinketRenderer.java | 75 +- .../interop/trinkets/TrinketsApiInterop.java | 72 +- .../fabric/loot/FabricHexLootModJankery.java | 81 +- .../fabric/mixin/FabricAxeItemMixin.java | 21 +- .../mixin/FabricBlockBehaviorMixin.java | 18 +- .../fabric/mixin/FabricClipContextMixin.java | 23 +- .../FabricEnchantmentTableBlockMixin.java | 19 +- .../fabric/mixin/FabricItemEntityMixin.java | 12 +- .../fabric/mixin/FabricLivingEntityMixin.java | 59 +- .../FabricMixinReloadableServerResources.java | 55 +- .../fabric/mixin/FabricMobMixin.java | 17 +- .../fabric/mixin/FabricPlayerMixin.java | 18 +- .../FabricVillagerTurnIntoWitchMixin.java | 18 +- .../client/FabricAbstractTextureMixin.java | 36 +- .../client/FabricLevelRendererMixin.java | 43 +- .../mixin/client/FabricMixinGameRenderer.java | 41 +- .../mixin/client/FabricModelManagerMixin.java | 36 +- .../mixin/client/FabricMouseHandlerMixin.java | 19 +- .../client/FabricParticleEngineMixin.java | 22 +- .../client/FabricPlayerRendererMixin.java | 20 +- .../fabric/network/FabricPacketHandler.java | 86 +- .../FabricModConditionalIngredient.java | 198 +-- .../recipe/FabricUnsealedIngredient.java | 173 +- .../fabric/storage/FabricImpetusStorage.kt | 110 +- .../fabric/xplat/FabricClientXplatImpl.java | 114 +- .../fabric/xplat/FabricXplatImpl.java | 899 +++++----- .../forge/ForgeHexClientInitializer.java | 222 +-- .../hexcasting/forge/ForgeHexConfig.java | 491 +++--- .../hexcasting/forge/ForgeHexInitializer.java | 460 +++--- .../hexcasting/forge/cap/CapSyncers.java | 100 +- .../forge/cap/ForgeCapabilityHandler.java | 398 +++-- .../forge/cap/ForgeImpetusCapability.java | 88 +- .../hexcasting/forge/cap/HexCapabilities.java | 27 +- .../cap/adimpl/CapClientCastingStack.java | 28 +- .../forge/cap/adimpl/CapEntityIotaHolder.java | 65 +- .../forge/cap/adimpl/CapItemHexHolder.java | 68 +- .../forge/cap/adimpl/CapItemIotaHolder.java | 60 +- .../forge/cap/adimpl/CapItemMediaHolder.java | 97 +- .../forge/cap/adimpl/CapItemPigment.java | 14 +- .../forge/cap/adimpl/CapItemVariantItem.java | 27 +- .../forge/cap/adimpl/CapStaticIotaHolder.java | 43 +- .../cap/adimpl/CapStaticMediaHolder.java | 108 +- .../datagen/ForgeHexConditionsBuilder.java | 83 +- .../forge/datagen/ForgeHexDataGenerators.java | 310 ++-- .../forge/datagen/ForgeHexLootModGen.java | 57 +- .../forge/datagen/TagsProviderEFHSetter.java | 2 +- .../xplat/HexBlockStatesAndModels.java | 986 ++++++----- .../forge/datagen/xplat/HexItemModels.java | 580 ++++--- .../interop/curios/CuriosApiInterop.java | 113 +- .../forge/interop/curios/CuriosRenderers.java | 28 +- .../interop/curios/LensCurioRenderer.java | 90 +- .../interop/jei/BrainsweepRecipeCategory.java | 142 +- .../interop/jei/EdifyRecipeCategory.java | 97 +- .../forge/interop/jei/HexJEIPlugin.java | 112 +- .../forge/interop/jei/PatternDrawable.java | 110 +- .../interop/jei/PhialRecipeCategory.java | 88 +- .../lib/ForgeHexArgumentTypeRegistry.java | 39 +- .../forge/lib/ForgeHexLootMods.java | 16 +- .../forge/loot/ForgeHexAmethystLootMod.java | 68 +- .../forge/loot/ForgeHexLoreLootMod.java | 51 +- .../forge/loot/ForgeHexScrollLootMod.java | 57 +- .../mixin/ForgeAccessorBuiltInRegistries.java | 25 +- .../forge/mixin/ForgeMixinBlockColors.java | 8 +- .../ForgeMixinCursedRecipeSerializerBase.java | 15 +- .../forge/mixin/ForgeMixinItemColors.java | 9 +- .../forge/mixin/ForgeMixinTagsProvider.java | 63 +- .../forge/network/ForgePacketHandler.java | 188 ++- .../forge/network/MsgAltioraUpdateAck.java | 80 +- .../forge/network/MsgBrainsweepAck.java | 84 +- .../forge/network/MsgPigmentUpdateAck.java | 72 +- .../network/MsgSentinelStatusUpdateAck.java | 95 +- .../recipe/ForgeModConditionalIngredient.java | 200 +-- .../forge/recipe/ForgeUnsealedIngredient.java | 161 +- .../forge/xplat/ForgeClientXplatImpl.java | 81 +- .../forge/xplat/ForgeXplatImpl.java | 1010 ++++++------ 625 files changed, 33489 insertions(+), 30272 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/annotations/SoftImplement.java b/Common/src/main/java/at/petrak/hexcasting/annotations/SoftImplement.java index c90949187f..de6da6fb94 100644 --- a/Common/src/main/java/at/petrak/hexcasting/annotations/SoftImplement.java +++ b/Common/src/main/java/at/petrak/hexcasting/annotations/SoftImplement.java @@ -9,22 +9,18 @@ // yoinky sploinky /** - * A purely-documentative annotation. - * This annotation is used by developers in xplat code. The annotated method is intended - * to "soft implement" a certain method in a loader specific interface that cannot be - * named in xplat code and thus cannot be checked with @Override. - * In this context, "soft implement" means to implement the method by matching the signature - * with the intended interface method. - * Examples of interfaces that we would use this for is IForgeItem or FabricItem. - * <p> - * The intent is that we audit such sites every major Minecraft version or so, to ensure - * that they still properly override the intended target. + * A purely-documentative annotation. This annotation is used by developers in xplat code. The + * annotated method is intended to "soft implement" a certain method in a loader specific interface + * that cannot be named in xplat code and thus cannot be checked with @Override. In this context, + * "soft implement" means to implement the method by matching the signature with the intended + * interface method. Examples of interfaces that we would use this for is IForgeItem or FabricItem. + * + * <p>The intent is that we audit such sites every major Minecraft version or so, to ensure that + * they still properly override the intended target. */ @Retention(RetentionPolicy.SOURCE) @Target(ElementType.METHOD) public @interface SoftImplement { - /** - * What interface we're soft implementing - */ - String value(); + /** What interface we're soft implementing */ + String value(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/HexAPI.java b/Common/src/main/java/at/petrak/hexcasting/api/HexAPI.java index 8ddde5669b..eaf3fb5c8b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/HexAPI.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/HexAPI.java @@ -7,6 +7,8 @@ import at.petrak.hexcasting.api.player.Sentinel; import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.google.common.base.Suppliers; +import java.util.function.Consumer; +import java.util.function.Supplier; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; @@ -16,7 +18,6 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ArmorItem; @@ -29,206 +30,201 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.function.Consumer; -import java.util.function.Supplier; - public interface HexAPI { - String MOD_ID = "hexcasting"; - Logger LOGGER = LogManager.getLogger(MOD_ID); - - Supplier<HexAPI> INSTANCE = Suppliers.memoize(() -> { - try { - return (HexAPI) Class.forName("at.petrak.hexcasting.common.impl.HexAPIImpl") - .getDeclaredConstructor().newInstance(); - } catch (ReflectiveOperationException e) { - LogManager.getLogger().warn("Unable to find HexAPIImpl, using a dummy"); - return new HexAPI() { - }; - } - }); - - /** - * Return the localization key for the given action. - * <p> - * Note we're allowed to have action <em>resource keys</em> on the client, just no actual actions. - * <p> - * Special handlers should be calling {@link SpecialHandler#getName()} - */ - default String getActionI18nKey(ResourceKey<ActionRegistryEntry> action) { - return "hexcasting.action.%s".formatted(action.location().toString()); - } - - default String getSpecialHandlerI18nKey(ResourceKey<SpecialHandler.Factory<?>> action) { - return "hexcasting.special.%s".formatted(action.location().toString()); - } - - /** - * Currently introspection/retrospection/consideration are hardcoded, but at least their names won't be - */ - default String getRawHookI18nKey(ResourceLocation name) { - return "hexcasting.rawhook.%s".formatted(name); - } - - default Component getActionI18n(ResourceKey<ActionRegistryEntry> key, boolean isGreat) { - return Component.translatable(getActionI18nKey(key)) - .withStyle(isGreat ? ChatFormatting.GOLD : ChatFormatting.LIGHT_PURPLE); - } - - default Component getSpecialHandlerI18n(ResourceKey<SpecialHandler.Factory<?>> key) { - return Component.translatable(getSpecialHandlerI18nKey(key)) - .withStyle(ChatFormatting.LIGHT_PURPLE); - } - - default Component getRawHookI18n(ResourceLocation name) { - return Component.translatable(getRawHookI18nKey(name)).withStyle(ChatFormatting.LIGHT_PURPLE); - } - - /** - * Register an entity with the given ID to have its velocity as perceived by OpEntityVelocity be different - * than it's "normal" velocity - */ - // Should be OK to use the type directly as the key as they're singleton identity objects - default <T extends Entity> void registerSpecialVelocityGetter(EntityType<T> key, EntityVelocityGetter<T> getter) { - } - - /** - * If the entity has had a special getter registered with {@link HexAPI#registerSpecialVelocityGetter} then - * return that, otherwise return its normal delta movement - */ - default Vec3 getEntityVelocitySpecial(Entity entity) { - return entity.getDeltaMovement(); - } - - @FunctionalInterface - interface EntityVelocityGetter<T extends Entity> { - Vec3 getVelocity(T entity); - } - - /** - * Register an entity type to have a custom behavior when getting brainswept. - * <p> - * This knocks out the normal behavior; if you want that behavior you should call - */ - default <T extends Mob> void registerCustomBrainsweepingBehavior(EntityType<T> key, Consumer<T> hook) { - } - - /** - * The default behavior when an entity gets brainswept. - * <p> - * Something registered with {@link HexAPI#registerCustomBrainsweepingBehavior} doesn't call this automatically; - * you can use this to add things on top of the default behavior - */ - default Consumer<Mob> defaultBrainsweepingBehavior() { - return mob -> { - }; - } - - /** - * If something special's been returned with {@link HexAPI#registerCustomBrainsweepingBehavior}, return that, - * otherwise return the default behavior - */ - default <T extends Mob> Consumer<T> getBrainsweepBehavior(EntityType<T> mobType) { - return mob -> { - }; - } - - /** - * Brainsweep (flay the mind of) the given mob. - * <p> - * This ignores the unbrainsweepable tag. - */ - default void brainsweep(Mob mob) { - var type = (EntityType<? extends Mob>) mob.getType(); - var behavior = this.getBrainsweepBehavior(type); - var erasedBehavior = (Consumer<Mob>) behavior; - erasedBehavior.accept(mob); - - IXplatAbstractions.INSTANCE.setBrainsweepAddlData(mob); - } - - default boolean isBrainswept(Mob mob) { - return IXplatAbstractions.INSTANCE.isBrainswept(mob); - } - - // - @Nullable - default Sentinel getSentinel(ServerPlayer player) { - return null; - } - - @Nullable - default ADMediaHolder findMediaHolder(ItemStack stack) { - return null; - } - - default FrozenPigment getColorizer(Player player) { - return FrozenPigment.DEFAULT.get(); - } - - ArmorMaterial DUMMY_ARMOR_MATERIAL = new ArmorMaterial() { - @Override - public int getDurabilityForType(ArmorItem.Type type) { - return 0; - } - - @Override - public int getDefenseForType(ArmorItem.Type type) { - return 0; - } - - @Override - public int getEnchantmentValue() { - return 0; - } - - @NotNull - @Override - public SoundEvent getEquipSound() { - return SoundEvents.ARMOR_EQUIP_LEATHER; - } - - @NotNull - @Override - public Ingredient getRepairIngredient() { - return Ingredient.EMPTY; - } - - @Override - public String getName() { - return "missingno"; - } - - @Override - public float getToughness() { - return 0; - } - - @Override - public float getKnockbackResistance() { - return 0; - } - }; - - default ArmorMaterial robesMaterial() { - return DUMMY_ARMOR_MATERIAL; - } - - /** - * Location in the userdata of the ravenmind - */ - String RAVENMIND_USERDATA = modLoc("ravenmind").toString(); - /** - * Location in the userdata of the number of ops executed - */ - String OP_COUNT_USERDATA = modLoc("op_count").toString(); - - String MARKED_MOVED_USERDATA = modLoc("impulsed").toString(); - - static HexAPI instance() { - return INSTANCE.get(); - } - - static ResourceLocation modLoc(String s) { - return new ResourceLocation(MOD_ID, s); - } + String MOD_ID = "hexcasting"; + Logger LOGGER = LogManager.getLogger(MOD_ID); + + Supplier<HexAPI> INSTANCE = + Suppliers.memoize( + () -> { + try { + return (HexAPI) + Class.forName("at.petrak.hexcasting.common.impl.HexAPIImpl") + .getDeclaredConstructor() + .newInstance(); + } catch (ReflectiveOperationException e) { + LogManager.getLogger().warn("Unable to find HexAPIImpl, using a dummy"); + return new HexAPI() {}; + } + }); + + /** + * Return the localization key for the given action. + * + * <p>Note we're allowed to have action <em>resource keys</em> on the client, just no actual + * actions. + * + * <p>Special handlers should be calling {@link SpecialHandler#getName()} + */ + default String getActionI18nKey(ResourceKey<ActionRegistryEntry> action) { + return "hexcasting.action.%s".formatted(action.location().toString()); + } + + default String getSpecialHandlerI18nKey(ResourceKey<SpecialHandler.Factory<?>> action) { + return "hexcasting.special.%s".formatted(action.location().toString()); + } + + /** + * Currently introspection/retrospection/consideration are hardcoded, but at least their names + * won't be + */ + default String getRawHookI18nKey(ResourceLocation name) { + return "hexcasting.rawhook.%s".formatted(name); + } + + default Component getActionI18n(ResourceKey<ActionRegistryEntry> key, boolean isGreat) { + return Component.translatable(getActionI18nKey(key)) + .withStyle(isGreat ? ChatFormatting.GOLD : ChatFormatting.LIGHT_PURPLE); + } + + default Component getSpecialHandlerI18n(ResourceKey<SpecialHandler.Factory<?>> key) { + return Component.translatable(getSpecialHandlerI18nKey(key)) + .withStyle(ChatFormatting.LIGHT_PURPLE); + } + + default Component getRawHookI18n(ResourceLocation name) { + return Component.translatable(getRawHookI18nKey(name)).withStyle(ChatFormatting.LIGHT_PURPLE); + } + + /** + * Register an entity with the given ID to have its velocity as perceived by OpEntityVelocity be + * different than it's "normal" velocity + */ + // Should be OK to use the type directly as the key as they're singleton identity objects + default <T extends Entity> void registerSpecialVelocityGetter( + EntityType<T> key, EntityVelocityGetter<T> getter) {} + + /** + * If the entity has had a special getter registered with {@link + * HexAPI#registerSpecialVelocityGetter} then return that, otherwise return its normal delta + * movement + */ + default Vec3 getEntityVelocitySpecial(Entity entity) { + return entity.getDeltaMovement(); + } + + @FunctionalInterface + interface EntityVelocityGetter<T extends Entity> { + Vec3 getVelocity(T entity); + } + + /** + * Register an entity type to have a custom behavior when getting brainswept. + * + * <p>This knocks out the normal behavior; if you want that behavior you should call + */ + default <T extends Mob> void registerCustomBrainsweepingBehavior( + EntityType<T> key, Consumer<T> hook) {} + + /** + * The default behavior when an entity gets brainswept. + * + * <p>Something registered with {@link HexAPI#registerCustomBrainsweepingBehavior} doesn't call + * this automatically; you can use this to add things on top of the default behavior + */ + default Consumer<Mob> defaultBrainsweepingBehavior() { + return mob -> {}; + } + + /** + * If something special's been returned with {@link HexAPI#registerCustomBrainsweepingBehavior}, + * return that, otherwise return the default behavior + */ + default <T extends Mob> Consumer<T> getBrainsweepBehavior(EntityType<T> mobType) { + return mob -> {}; + } + + /** + * Brainsweep (flay the mind of) the given mob. + * + * <p>This ignores the unbrainsweepable tag. + */ + default void brainsweep(Mob mob) { + var type = (EntityType<? extends Mob>) mob.getType(); + var behavior = this.getBrainsweepBehavior(type); + var erasedBehavior = (Consumer<Mob>) behavior; + erasedBehavior.accept(mob); + + IXplatAbstractions.INSTANCE.setBrainsweepAddlData(mob); + } + + default boolean isBrainswept(Mob mob) { + return IXplatAbstractions.INSTANCE.isBrainswept(mob); + } + + // + @Nullable default Sentinel getSentinel(ServerPlayer player) { + return null; + } + + @Nullable default ADMediaHolder findMediaHolder(ItemStack stack) { + return null; + } + + default FrozenPigment getColorizer(Player player) { + return FrozenPigment.DEFAULT.get(); + } + + ArmorMaterial DUMMY_ARMOR_MATERIAL = + new ArmorMaterial() { + @Override + public int getDurabilityForType(ArmorItem.Type type) { + return 0; + } + + @Override + public int getDefenseForType(ArmorItem.Type type) { + return 0; + } + + @Override + public int getEnchantmentValue() { + return 0; + } + + @NotNull @Override + public SoundEvent getEquipSound() { + return SoundEvents.ARMOR_EQUIP_LEATHER; + } + + @NotNull @Override + public Ingredient getRepairIngredient() { + return Ingredient.EMPTY; + } + + @Override + public String getName() { + return "missingno"; + } + + @Override + public float getToughness() { + return 0; + } + + @Override + public float getKnockbackResistance() { + return 0; + } + }; + + default ArmorMaterial robesMaterial() { + return DUMMY_ARMOR_MATERIAL; + } + + /** Location in the userdata of the ravenmind */ + String RAVENMIND_USERDATA = modLoc("ravenmind").toString(); + + /** Location in the userdata of the number of ops executed */ + String OP_COUNT_USERDATA = modLoc("op_count").toString(); + + String MARKED_MOVED_USERDATA = modLoc("impulsed").toString(); + + static HexAPI instance() { + return INSTANCE.get(); + } + + static ResourceLocation modLoc(String s) { + return new ResourceLocation(MOD_ID, s); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADHexHolder.java b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADHexHolder.java index 15defd673b..654086587a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADHexHolder.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADHexHolder.java @@ -2,23 +2,21 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.pigment.FrozenPigment; +import java.util.List; import net.minecraft.server.level.ServerLevel; import org.jetbrains.annotations.Nullable; -import java.util.List; - public interface ADHexHolder { - boolean canDrawMediaFromInventory(); + boolean canDrawMediaFromInventory(); - boolean hasHex(); + boolean hasHex(); - @Nullable - List<Iota> getHex(ServerLevel level); + @Nullable List<Iota> getHex(ServerLevel level); - void writeHex(List<Iota> patterns, @Nullable FrozenPigment pigment, long media); + void writeHex(List<Iota> patterns, @Nullable FrozenPigment pigment, long media); - void clearHex(); + void clearHex(); - @Nullable FrozenPigment getPigment(); + @Nullable FrozenPigment getPigment(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADIotaHolder.java b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADIotaHolder.java index 7b8fcc1c95..1cf5910a67 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADIotaHolder.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADIotaHolder.java @@ -7,31 +7,28 @@ import org.jetbrains.annotations.Nullable; public interface ADIotaHolder { - @Nullable - CompoundTag readIotaTag(); + @Nullable CompoundTag readIotaTag(); - @Nullable - default Iota readIota(ServerLevel world) { - var tag = readIotaTag(); - if (tag != null) { - return IotaType.deserialize(tag, world); - } else { - return null; - } - } + @Nullable default Iota readIota(ServerLevel world) { + var tag = readIotaTag(); + if (tag != null) { + return IotaType.deserialize(tag, world); + } else { + return null; + } + } - @Nullable - default Iota emptyIota() { - return null; - } + @Nullable default Iota emptyIota() { + return null; + } - /** - * @return if the writing succeeded/would succeed - */ - boolean writeIota(@Nullable Iota iota, boolean simulate); + /** + * @return if the writing succeeded/would succeed + */ + boolean writeIota(@Nullable Iota iota, boolean simulate); - /** - * @return whether it is possible to write to this IotaHolder - */ - boolean writeable(); + /** + * @return whether it is possible to write to this IotaHolder + */ + boolean writeable(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADMediaHolder.java b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADMediaHolder.java index 547f6afc31..82d886dc41 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADMediaHolder.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADMediaHolder.java @@ -4,108 +4,103 @@ public interface ADMediaHolder { - /** - * Use {@code withdrawMedia(-1, true)} - * - * @see ADMediaHolder#withdrawMedia(long, boolean) - */ - @ApiStatus.OverrideOnly - long getMedia(); + /** + * Use {@code withdrawMedia(-1, true)} + * + * @see ADMediaHolder#withdrawMedia(long, boolean) + */ + @ApiStatus.OverrideOnly + long getMedia(); - /** - * Use {@code withdrawMedia(-1, true) + insertMedia(-1, true)} where possible - * - * @see ADMediaHolder#insertMedia(long, boolean) - * @see ADMediaHolder#withdrawMedia(long, boolean) - */ - @ApiStatus.OverrideOnly - long getMaxMedia(); + /** + * Use {@code withdrawMedia(-1, true) + insertMedia(-1, true)} where possible + * + * @see ADMediaHolder#insertMedia(long, boolean) + * @see ADMediaHolder#withdrawMedia(long, boolean) + */ + @ApiStatus.OverrideOnly + long getMaxMedia(); - /** - * Use {@code insertMedia(media - withdrawMedia(-1, true), false)} where possible - * - * @see ADMediaHolder#insertMedia(long, boolean) - * @see ADMediaHolder#withdrawMedia(long, boolean) - */ - @ApiStatus.OverrideOnly - void setMedia(long media); + /** + * Use {@code insertMedia(media - withdrawMedia(-1, true), false)} where possible + * + * @see ADMediaHolder#insertMedia(long, boolean) + * @see ADMediaHolder#withdrawMedia(long, boolean) + */ + @ApiStatus.OverrideOnly + void setMedia(long media); - /** - * Whether this media holder can have media inserted into it. - */ - boolean canRecharge(); + /** Whether this media holder can have media inserted into it. */ + boolean canRecharge(); - /** - * Whether this media holder can be extracted from. - */ - boolean canProvide(); + /** Whether this media holder can be extracted from. */ + boolean canProvide(); - /** - * The priority for this media holder to be selected when casting a hex. Higher priorities are taken first. - * <p> - * By default, - * * Charged Amethyst has priority 1000 - * * Amethyst Shards have priority 2000 - * * Amethyst Dust has priority 3000 - * * Items which hold media have priority 4000 - */ - int getConsumptionPriority(); + /** + * The priority for this media holder to be selected when casting a hex. Higher priorities are + * taken first. + * + * <p>By default, * Charged Amethyst has priority 1000 * Amethyst Shards have priority 2000 * + * Amethyst Dust has priority 3000 * Items which hold media have priority 4000 + */ + int getConsumptionPriority(); - /** - * Whether the media inside this media holder may be used to construct a battery. - */ - boolean canConstructBattery(); + /** Whether the media inside this media holder may be used to construct a battery. */ + boolean canConstructBattery(); - /** - * Withdraws media from the holder. Returns the amount of media extracted, which may be less or more than the cost. - * <p> - * Even if {@link ADMediaHolder#canProvide} is false, you can still withdraw media this way. - * <p> - * Withdrawing a negative amount will act as though you attempted to withdraw as much media as the holder contains. - */ - default long withdrawMedia(long cost, boolean simulate) { - var mediaHere = getMedia(); - if (cost < 0) { - cost = mediaHere; - } - if (!simulate) { - var mediaLeft = mediaHere - cost; - setMedia(mediaLeft); - } - return Math.min(cost, mediaHere); - } + /** + * Withdraws media from the holder. Returns the amount of media extracted, which may be less or + * more than the cost. + * + * <p>Even if {@link ADMediaHolder#canProvide} is false, you can still withdraw media this way. + * + * <p>Withdrawing a negative amount will act as though you attempted to withdraw as much media as + * the holder contains. + */ + default long withdrawMedia(long cost, boolean simulate) { + var mediaHere = getMedia(); + if (cost < 0) { + cost = mediaHere; + } + if (!simulate) { + var mediaLeft = mediaHere - cost; + setMedia(mediaLeft); + } + return Math.min(cost, mediaHere); + } - /** - * Inserts media into the holder. Returns the amount of media inserted, which may be less than the requested amount. - * <p> - * Even if {@link ADMediaHolder#canRecharge} is false, you can still insert media this way. - * <p> - * Inserting a negative amount will act as though you attempted to insert exactly as much media as the holder was - * missing. - */ - default long insertMedia(long amount, boolean simulate) { - var mediaHere = getMedia(); - long emptySpace = getMaxMedia() - mediaHere; - if (emptySpace <= 0) { - return 0; - } - if (amount < 0) { - amount = emptySpace; - } + /** + * Inserts media into the holder. Returns the amount of media inserted, which may be less than the + * requested amount. + * + * <p>Even if {@link ADMediaHolder#canRecharge} is false, you can still insert media this way. + * + * <p>Inserting a negative amount will act as though you attempted to insert exactly as much media + * as the holder was missing. + */ + default long insertMedia(long amount, boolean simulate) { + var mediaHere = getMedia(); + long emptySpace = getMaxMedia() - mediaHere; + if (emptySpace <= 0) { + return 0; + } + if (amount < 0) { + amount = emptySpace; + } - long inserting = Math.min(amount, emptySpace); + long inserting = Math.min(amount, emptySpace); - if (!simulate) { - var newMedia = mediaHere + inserting; - setMedia(newMedia); - } - return inserting; - } + if (!simulate) { + var newMedia = mediaHere + inserting; + setMedia(newMedia); + } + return inserting; + } - int QUENCHED_ALLAY_PRIORITY = 800; - int QUENCHED_SHARD_PRIORITY = 900; - int CHARGED_AMETHYST_PRIORITY = 1000; - int AMETHYST_SHARD_PRIORITY = 2000; - int AMETHYST_DUST_PRIORITY = 3000; - int BATTERY_PRIORITY = 4000; + int QUENCHED_ALLAY_PRIORITY = 800; + int QUENCHED_SHARD_PRIORITY = 900; + int CHARGED_AMETHYST_PRIORITY = 1000; + int AMETHYST_SHARD_PRIORITY = 2000; + int AMETHYST_DUST_PRIORITY = 3000; + int BATTERY_PRIORITY = 4000; } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADPigment.java b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADPigment.java index 86984439c9..e5ed045b68 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADPigment.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADPigment.java @@ -1,38 +1,37 @@ package at.petrak.hexcasting.api.addldata; import at.petrak.hexcasting.api.pigment.ColorProvider; +import java.util.UUID; import net.minecraft.util.FastColor; import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec3; -import java.util.UUID; - public interface ADPigment { - ColorProvider provideColor(UUID owner); - - static int morphBetweenColors(int[] colors, Vec3 gradientDir, float time, Vec3 position) { - float fIdx = Mth.positiveModulo(time + (float) gradientDir.dot(position), 1f) * colors.length; - - int baseIdx = Mth.floor(fIdx); - float tRaw = fIdx - baseIdx; - float t = tRaw < 0.5 ? 4 * tRaw * tRaw * tRaw : (float) (1 - Math.pow(-2 * tRaw + 2, 3) / 2); - int start = colors[baseIdx % colors.length]; - int end = colors[(baseIdx + 1) % colors.length]; - - var r1 = FastColor.ARGB32.red(start); - var g1 = FastColor.ARGB32.green(start); - var b1 = FastColor.ARGB32.blue(start); - var a1 = FastColor.ARGB32.alpha(start); - var r2 = FastColor.ARGB32.red(end); - var g2 = FastColor.ARGB32.green(end); - var b2 = FastColor.ARGB32.blue(end); - var a2 = FastColor.ARGB32.alpha(end); - - var r = Mth.lerp(t, r1, r2); - var g = Mth.lerp(t, g1, g2); - var b = Mth.lerp(t, b1, b2); - var a = Mth.lerp(t, a1, a2); - - return FastColor.ARGB32.color((int) a, (int) r, (int) g, (int) b); - } + ColorProvider provideColor(UUID owner); + + static int morphBetweenColors(int[] colors, Vec3 gradientDir, float time, Vec3 position) { + float fIdx = Mth.positiveModulo(time + (float) gradientDir.dot(position), 1f) * colors.length; + + int baseIdx = Mth.floor(fIdx); + float tRaw = fIdx - baseIdx; + float t = tRaw < 0.5 ? 4 * tRaw * tRaw * tRaw : (float) (1 - Math.pow(-2 * tRaw + 2, 3) / 2); + int start = colors[baseIdx % colors.length]; + int end = colors[(baseIdx + 1) % colors.length]; + + var r1 = FastColor.ARGB32.red(start); + var g1 = FastColor.ARGB32.green(start); + var b1 = FastColor.ARGB32.blue(start); + var a1 = FastColor.ARGB32.alpha(start); + var r2 = FastColor.ARGB32.red(end); + var g2 = FastColor.ARGB32.green(end); + var b2 = FastColor.ARGB32.blue(end); + var a2 = FastColor.ARGB32.alpha(end); + + var r = Mth.lerp(t, r1, r2); + var g = Mth.lerp(t, g1, g2); + var b = Mth.lerp(t, b1, b2); + var a = Mth.lerp(t, a1, a2); + + return FastColor.ARGB32.color((int) a, (int) r, (int) g, (int) b); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADVariantItem.java b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADVariantItem.java index 6b1a59f76d..925caddc01 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADVariantItem.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADVariantItem.java @@ -1,9 +1,9 @@ package at.petrak.hexcasting.api.addldata; public interface ADVariantItem { - int numVariants(); - int getVariant(); + int numVariants(); + int getVariant(); - void setVariant(int variant); + void setVariant(int variant); } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ItemDelegatingEntityIotaHolder.java b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ItemDelegatingEntityIotaHolder.java index 5af67a99ab..cbf4578f95 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ItemDelegatingEntityIotaHolder.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ItemDelegatingEntityIotaHolder.java @@ -3,6 +3,8 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.common.entities.EntityWallScroll; import at.petrak.hexcasting.xplat.IXplatAbstractions; +import java.util.function.Consumer; +import java.util.function.Supplier; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.decoration.ItemFrame; @@ -10,80 +12,79 @@ import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Nullable; -import java.util.function.Consumer; -import java.util.function.Supplier; - public abstract class ItemDelegatingEntityIotaHolder implements ADIotaHolder { - private final Supplier<ItemStack> stackSupplier; + private final Supplier<ItemStack> stackSupplier; - private final Consumer<ItemStack> save; + private final Consumer<ItemStack> save; - public ItemDelegatingEntityIotaHolder(Supplier<ItemStack> stackSupplier, Consumer<ItemStack> save) { - this.stackSupplier = stackSupplier; - this.save = save; - } + public ItemDelegatingEntityIotaHolder( + Supplier<ItemStack> stackSupplier, Consumer<ItemStack> save) { + this.stackSupplier = stackSupplier; + this.save = save; + } - @Override - public @Nullable CompoundTag readIotaTag() { - var delegate = IXplatAbstractions.INSTANCE.findDataHolder(this.stackSupplier.get()); - return delegate == null ? null : delegate.readIotaTag(); - } + @Override + public @Nullable CompoundTag readIotaTag() { + var delegate = IXplatAbstractions.INSTANCE.findDataHolder(this.stackSupplier.get()); + return delegate == null ? null : delegate.readIotaTag(); + } - @Override - public boolean writeable() { - var delegate = IXplatAbstractions.INSTANCE.findDataHolder(this.stackSupplier.get()); - return delegate != null && delegate.writeable(); - } + @Override + public boolean writeable() { + var delegate = IXplatAbstractions.INSTANCE.findDataHolder(this.stackSupplier.get()); + return delegate != null && delegate.writeable(); + } - @Override - public boolean writeIota(@Nullable Iota datum, boolean simulate) { - var stacc = this.stackSupplier.get(); - var delegate = IXplatAbstractions.INSTANCE.findDataHolder(stacc); - var success = delegate != null && delegate.writeIota(datum, simulate); - if (success && !simulate) { - this.save.accept(stacc); - } - return success; - } + @Override + public boolean writeIota(@Nullable Iota datum, boolean simulate) { + var stacc = this.stackSupplier.get(); + var delegate = IXplatAbstractions.INSTANCE.findDataHolder(stacc); + var success = delegate != null && delegate.writeIota(datum, simulate); + if (success && !simulate) { + this.save.accept(stacc); + } + return success; + } - @Override - public @Nullable Iota readIota(ServerLevel world) { - var delegate = IXplatAbstractions.INSTANCE.findDataHolder(this.stackSupplier.get()); - return delegate == null ? null : delegate.readIota(world); - } + @Override + public @Nullable Iota readIota(ServerLevel world) { + var delegate = IXplatAbstractions.INSTANCE.findDataHolder(this.stackSupplier.get()); + return delegate == null ? null : delegate.readIota(world); + } - @Override - public @Nullable Iota emptyIota() { - var delegate = IXplatAbstractions.INSTANCE.findDataHolder(this.stackSupplier.get()); - return delegate == null ? null : delegate.emptyIota(); - } + @Override + public @Nullable Iota emptyIota() { + var delegate = IXplatAbstractions.INSTANCE.findDataHolder(this.stackSupplier.get()); + return delegate == null ? null : delegate.emptyIota(); + } - public static class ToItemEntity extends ItemDelegatingEntityIotaHolder { - public ToItemEntity(ItemEntity entity) { - super(entity::getItem, stack -> { - // https://github.com/VazkiiMods/Botania/blob/e6d095ff5010074b45408d6cce8ee1e328af3383/Xplat/src/main/java/vazkii/botania/common/helper/EntityHelper.java#L16 - entity.setItem(ItemStack.EMPTY); - entity.setItem(stack); - entity.setUnlimitedLifetime(); - }); - } - } + public static class ToItemEntity extends ItemDelegatingEntityIotaHolder { + public ToItemEntity(ItemEntity entity) { + super( + entity::getItem, + stack -> { + // https://github.com/VazkiiMods/Botania/blob/e6d095ff5010074b45408d6cce8ee1e328af3383/Xplat/src/main/java/vazkii/botania/common/helper/EntityHelper.java#L16 + entity.setItem(ItemStack.EMPTY); + entity.setItem(stack); + entity.setUnlimitedLifetime(); + }); + } + } - public static class ToItemFrame extends ItemDelegatingEntityIotaHolder { - public ToItemFrame(ItemFrame entity) { - super(entity::getItem, entity::setItem); - } - } + public static class ToItemFrame extends ItemDelegatingEntityIotaHolder { + public ToItemFrame(ItemFrame entity) { + super(entity::getItem, entity::setItem); + } + } - public static class ToWallScroll extends ItemDelegatingEntityIotaHolder { - public ToWallScroll(EntityWallScroll entity) { - super(() -> entity.scroll.copy(), stack -> { - }); - } + public static class ToWallScroll extends ItemDelegatingEntityIotaHolder { + public ToWallScroll(EntityWallScroll entity) { + super(() -> entity.scroll.copy(), stack -> {}); + } - @Override - public boolean writeIota(@Nullable Iota datum, boolean simulate) { - return false; - } - } + @Override + public boolean writeIota(@Nullable Iota datum, boolean simulate) { + return false; + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/addldata/package-info.java b/Common/src/main/java/at/petrak/hexcasting/api/addldata/package-info.java index a11787c85a..0e6736a833 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/addldata/package-info.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/addldata/package-info.java @@ -1,10 +1,11 @@ /** * An "Additional Data," or AD, is what I am calling the abstraction over capabilities on Forge and * cardinal components on Fabric. - * <p> - * An {@code ADFooBar} in this package will be implemented by a {@code CCFooBar} on Fabric. - * On Forge, there are a set of private records that implement them. - * <p> - * The point is, this provides an interface for interacting with however whatever platform sticks extra info on stuff. + * + * <p>An {@code ADFooBar} in this package will be implemented by a {@code CCFooBar} on Fabric. On + * Forge, there are a set of private records that implement them. + * + * <p>The point is, this provides an interface for interacting with however whatever platform sticks + * extra info on stuff. */ package at.petrak.hexcasting.api.addldata; diff --git a/Common/src/main/java/at/petrak/hexcasting/api/advancements/FailToCastGreatSpellTrigger.java b/Common/src/main/java/at/petrak/hexcasting/api/advancements/FailToCastGreatSpellTrigger.java index fe85fec5b3..05e169f172 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/advancements/FailToCastGreatSpellTrigger.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/advancements/FailToCastGreatSpellTrigger.java @@ -5,35 +5,38 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; -public class FailToCastGreatSpellTrigger extends SimpleCriterionTrigger<FailToCastGreatSpellTrigger.Instance> { - private static final ResourceLocation ID = new ResourceLocation("hexcasting", "fail_to_cast_great_spell"); - - @Override - public ResourceLocation getId() { - return ID; - } - - @Override - protected Instance createInstance(JsonObject json, ContextAwarePredicate predicate, DeserializationContext context) { - return new Instance(predicate); - } - - public void trigger(ServerPlayer player) { - super.trigger(player, e -> true); - } - - public static class Instance extends AbstractCriterionTriggerInstance { - public Instance(ContextAwarePredicate predicate) { - super(ID, predicate); - } - - @Override - public ResourceLocation getCriterion() { - return ID; - } - - public JsonObject serializeToJson(SerializationContext pConditions) { - return new JsonObject(); - } - } +public class FailToCastGreatSpellTrigger + extends SimpleCriterionTrigger<FailToCastGreatSpellTrigger.Instance> { + private static final ResourceLocation ID = + new ResourceLocation("hexcasting", "fail_to_cast_great_spell"); + + @Override + public ResourceLocation getId() { + return ID; + } + + @Override + protected Instance createInstance( + JsonObject json, ContextAwarePredicate predicate, DeserializationContext context) { + return new Instance(predicate); + } + + public void trigger(ServerPlayer player) { + super.trigger(player, e -> true); + } + + public static class Instance extends AbstractCriterionTriggerInstance { + public Instance(ContextAwarePredicate predicate) { + super(ID, predicate); + } + + @Override + public ResourceLocation getCriterion() { + return ID; + } + + public JsonObject serializeToJson(SerializationContext pConditions) { + return new JsonObject(); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/advancements/HexAdvancementTriggers.java b/Common/src/main/java/at/petrak/hexcasting/api/advancements/HexAdvancementTriggers.java index 16af02ab39..979edd4ca1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/advancements/HexAdvancementTriggers.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/advancements/HexAdvancementTriggers.java @@ -3,13 +3,14 @@ import at.petrak.hexcasting.mixin.accessor.CriteriaTriggersAccessor; public class HexAdvancementTriggers { - public static final OvercastTrigger OVERCAST_TRIGGER = new OvercastTrigger(); - public static final SpendMediaTrigger SPEND_MEDIA_TRIGGER = new SpendMediaTrigger(); - public static final FailToCastGreatSpellTrigger FAIL_GREAT_SPELL_TRIGGER = new FailToCastGreatSpellTrigger(); + public static final OvercastTrigger OVERCAST_TRIGGER = new OvercastTrigger(); + public static final SpendMediaTrigger SPEND_MEDIA_TRIGGER = new SpendMediaTrigger(); + public static final FailToCastGreatSpellTrigger FAIL_GREAT_SPELL_TRIGGER = + new FailToCastGreatSpellTrigger(); - public static void registerTriggers() { - CriteriaTriggersAccessor.hex$register(OVERCAST_TRIGGER); - CriteriaTriggersAccessor.hex$register(SPEND_MEDIA_TRIGGER); - CriteriaTriggersAccessor.hex$register(FAIL_GREAT_SPELL_TRIGGER); - } + public static void registerTriggers() { + CriteriaTriggersAccessor.hex$register(OVERCAST_TRIGGER); + CriteriaTriggersAccessor.hex$register(SPEND_MEDIA_TRIGGER); + CriteriaTriggersAccessor.hex$register(FAIL_GREAT_SPELL_TRIGGER); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/advancements/MinMaxLongs.java b/Common/src/main/java/at/petrak/hexcasting/api/advancements/MinMaxLongs.java index 0be502c86e..7f64df6b03 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/advancements/MinMaxLongs.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/advancements/MinMaxLongs.java @@ -4,82 +4,81 @@ import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.BuiltInExceptionProvider; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.advancements.critereon.MinMaxBounds; -import net.minecraft.util.GsonHelper; - -import javax.annotation.Nullable; import java.util.Objects; import java.util.function.Function; +import javax.annotation.Nullable; +import net.minecraft.advancements.critereon.MinMaxBounds; +import net.minecraft.util.GsonHelper; public class MinMaxLongs extends MinMaxBounds<Long> { - public static final MinMaxLongs ANY = new MinMaxLongs(null, null); - @Nullable - private final Long minSq; - @Nullable - private final Long maxSq; + public static final MinMaxLongs ANY = new MinMaxLongs(null, null); + @Nullable private final Long minSq; + @Nullable private final Long maxSq; - private static MinMaxLongs create(StringReader reader, @Nullable Long min, @Nullable Long max) throws CommandSyntaxException { - if (min != null && max != null && min > max) { - throw ERROR_SWAPPED.createWithContext(reader); - } else { - return new MinMaxLongs(min, max); - } - } + private static MinMaxLongs create(StringReader reader, @Nullable Long min, @Nullable Long max) + throws CommandSyntaxException { + if (min != null && max != null && min > max) { + throw ERROR_SWAPPED.createWithContext(reader); + } else { + return new MinMaxLongs(min, max); + } + } - @Nullable - private static Long squareOpt(@Nullable Long l) { - return l == null ? null : l * l; - } + @Nullable private static Long squareOpt(@Nullable Long l) { + return l == null ? null : l * l; + } - private MinMaxLongs(@Nullable Long min, @Nullable Long max) { - super(min, max); - this.minSq = squareOpt(min); - this.maxSq = squareOpt(max); - } + private MinMaxLongs(@Nullable Long min, @Nullable Long max) { + super(min, max); + this.minSq = squareOpt(min); + this.maxSq = squareOpt(max); + } - public static MinMaxLongs exactly(long l) { - return new MinMaxLongs(l, l); - } + public static MinMaxLongs exactly(long l) { + return new MinMaxLongs(l, l); + } - public static MinMaxLongs between(long min, long max) { - return new MinMaxLongs(min, max); - } + public static MinMaxLongs between(long min, long max) { + return new MinMaxLongs(min, max); + } - public static MinMaxLongs atLeast(long min) { - return new MinMaxLongs(min, null); - } + public static MinMaxLongs atLeast(long min) { + return new MinMaxLongs(min, null); + } - public static MinMaxLongs atMost(long max) { - return new MinMaxLongs(null, max); - } + public static MinMaxLongs atMost(long max) { + return new MinMaxLongs(null, max); + } - public boolean matches(long l) { - if (this.min != null && this.min > l) { - return false; - } else { - return this.max == null || this.max >= l; - } - } + public boolean matches(long l) { + if (this.min != null && this.min > l) { + return false; + } else { + return this.max == null || this.max >= l; + } + } - public boolean matchesSqr(long l) { - if (this.minSq != null && this.minSq > l) { - return false; - } else { - return this.maxSq == null || this.maxSq >= l; - } - } + public boolean matchesSqr(long l) { + if (this.minSq != null && this.minSq > l) { + return false; + } else { + return this.maxSq == null || this.maxSq >= l; + } + } - public static MinMaxLongs fromJson(@Nullable JsonElement json) { - return fromJson(json, ANY, GsonHelper::convertToLong, MinMaxLongs::new); - } + public static MinMaxLongs fromJson(@Nullable JsonElement json) { + return fromJson(json, ANY, GsonHelper::convertToLong, MinMaxLongs::new); + } - public static MinMaxLongs fromReader(StringReader reader) throws CommandSyntaxException { - return fromReader(reader, (l) -> l); - } + public static MinMaxLongs fromReader(StringReader reader) throws CommandSyntaxException { + return fromReader(reader, (l) -> l); + } - public static MinMaxLongs fromReader(StringReader reader, Function<Long, Long> map) throws CommandSyntaxException { - BuiltInExceptionProvider builtInExceptions = CommandSyntaxException.BUILT_IN_EXCEPTIONS; - Objects.requireNonNull(builtInExceptions); - return fromReader(reader, MinMaxLongs::create, Long::parseLong, builtInExceptions::readerInvalidInt, map); - } + public static MinMaxLongs fromReader(StringReader reader, Function<Long, Long> map) + throws CommandSyntaxException { + BuiltInExceptionProvider builtInExceptions = CommandSyntaxException.BUILT_IN_EXCEPTIONS; + Objects.requireNonNull(builtInExceptions); + return fromReader( + reader, MinMaxLongs::create, Long::parseLong, builtInExceptions::readerInvalidInt, map); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/advancements/OvercastTrigger.java b/Common/src/main/java/at/petrak/hexcasting/api/advancements/OvercastTrigger.java index b1661e869e..2401158ebf 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/advancements/OvercastTrigger.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/advancements/OvercastTrigger.java @@ -10,77 +10,83 @@ // https://github.com/VazkiiMods/Botania/blob/b8706e2e0bba20f67f1e103559a4ce39d63d48f9/src/main/java/vazkii/botania/common/advancements/CorporeaRequestTrigger.java public class OvercastTrigger extends SimpleCriterionTrigger<OvercastTrigger.Instance> { - private static final ResourceLocation ID = new ResourceLocation("hexcasting", "overcast"); + private static final ResourceLocation ID = new ResourceLocation("hexcasting", "overcast"); - private static final String TAG_MEDIA_GENERATED = "media_generated"; - private static final String TAG_HEALTH_USED = "health_used"; - // HEY KIDS DID YOYU KNOW THERE'S NOT A CRITERIA FOR HOW MUCH ***HEALTH*** AN ENTITY HAS - private static final String TAG_HEALTH_LEFT = - "mojang_i_am_begging_and_crying_please_add_an_entity_health_criterion"; + private static final String TAG_MEDIA_GENERATED = "media_generated"; + private static final String TAG_HEALTH_USED = "health_used"; + // HEY KIDS DID YOYU KNOW THERE'S NOT A CRITERIA FOR HOW MUCH ***HEALTH*** AN ENTITY HAS + private static final String TAG_HEALTH_LEFT = + "mojang_i_am_begging_and_crying_please_add_an_entity_health_criterion"; - @Override - public ResourceLocation getId() { - return ID; - } + @Override + public ResourceLocation getId() { + return ID; + } - @Override - protected Instance createInstance(JsonObject json, ContextAwarePredicate predicate, - DeserializationContext pContext) { - return new Instance(predicate, - MinMaxBounds.Ints.fromJson(json.get(TAG_MEDIA_GENERATED)), - MinMaxBounds.Doubles.fromJson(json.get(TAG_HEALTH_USED)), - MinMaxBounds.Doubles.fromJson(json.get(TAG_HEALTH_LEFT))); - } + @Override + protected Instance createInstance( + JsonObject json, ContextAwarePredicate predicate, DeserializationContext pContext) { + return new Instance( + predicate, + MinMaxBounds.Ints.fromJson(json.get(TAG_MEDIA_GENERATED)), + MinMaxBounds.Doubles.fromJson(json.get(TAG_HEALTH_USED)), + MinMaxBounds.Doubles.fromJson(json.get(TAG_HEALTH_LEFT))); + } - public void trigger(ServerPlayer player, int mediaGenerated) { - super.trigger(player, inst -> { - var mediaToHealth = HexConfig.common().mediaToHealthRate(); - var healthUsed = mediaGenerated / mediaToHealth; - return inst.test(mediaGenerated, healthUsed / player.getMaxHealth(), player.getHealth()); - }); - } + public void trigger(ServerPlayer player, int mediaGenerated) { + super.trigger( + player, + inst -> { + var mediaToHealth = HexConfig.common().mediaToHealthRate(); + var healthUsed = mediaGenerated / mediaToHealth; + return inst.test(mediaGenerated, healthUsed / player.getMaxHealth(), player.getHealth()); + }); + } - public static class Instance extends AbstractCriterionTriggerInstance { - protected final MinMaxBounds.Ints mediaGenerated; - // This is the *proporttion* of the health bar. - protected final MinMaxBounds.Doubles healthUsed; - // DID YOU KNOW THERES ONE TO CHECK THE WORLD TIME, BUT NOT THE HEALTH!? - protected final MinMaxBounds.Doubles healthLeft; + public static class Instance extends AbstractCriterionTriggerInstance { + protected final MinMaxBounds.Ints mediaGenerated; + // This is the *proporttion* of the health bar. + protected final MinMaxBounds.Doubles healthUsed; + // DID YOU KNOW THERES ONE TO CHECK THE WORLD TIME, BUT NOT THE HEALTH!? + protected final MinMaxBounds.Doubles healthLeft; - public Instance(ContextAwarePredicate predicate, MinMaxBounds.Ints mediaGenerated, - MinMaxBounds.Doubles healthUsed, MinMaxBounds.Doubles healthLeft) { - super(OvercastTrigger.ID, predicate); - this.mediaGenerated = mediaGenerated; - this.healthUsed = healthUsed; - // DID YOU KNOW THERE'S ONE TO CHECK THE FUCKING C A T T Y P E BUT NOT THE HEALTH - this.healthLeft = healthLeft; - } + public Instance( + ContextAwarePredicate predicate, + MinMaxBounds.Ints mediaGenerated, + MinMaxBounds.Doubles healthUsed, + MinMaxBounds.Doubles healthLeft) { + super(OvercastTrigger.ID, predicate); + this.mediaGenerated = mediaGenerated; + this.healthUsed = healthUsed; + // DID YOU KNOW THERE'S ONE TO CHECK THE FUCKING C A T T Y P E BUT NOT THE HEALTH + this.healthLeft = healthLeft; + } - @Override - public ResourceLocation getCriterion() { - return ID; - } + @Override + public ResourceLocation getCriterion() { + return ID; + } - @Override - public JsonObject serializeToJson(SerializationContext ctx) { - JsonObject json = super.serializeToJson(ctx); - if (!this.mediaGenerated.isAny()) { - json.add(TAG_MEDIA_GENERATED, this.mediaGenerated.serializeToJson()); - } - if (!this.healthUsed.isAny()) { - json.add(TAG_HEALTH_USED, this.healthUsed.serializeToJson()); - } - if (!this.healthLeft.isAny()) { - json.add(TAG_HEALTH_LEFT, this.healthLeft.serializeToJson()); - } - return json; - } + @Override + public JsonObject serializeToJson(SerializationContext ctx) { + JsonObject json = super.serializeToJson(ctx); + if (!this.mediaGenerated.isAny()) { + json.add(TAG_MEDIA_GENERATED, this.mediaGenerated.serializeToJson()); + } + if (!this.healthUsed.isAny()) { + json.add(TAG_HEALTH_USED, this.healthUsed.serializeToJson()); + } + if (!this.healthLeft.isAny()) { + json.add(TAG_HEALTH_LEFT, this.healthLeft.serializeToJson()); + } + return json; + } - private boolean test(int mediaGeneratedIn, double healthUsedIn, float healthLeftIn) { - return this.mediaGenerated.matches(mediaGeneratedIn) - && this.healthUsed.matches(healthUsedIn) - // DID YOU KNOW ALL THE ENEITYT PREDICATES ARE HARD-CODED AND YOU CANT MAKE NEW ONES - && this.healthLeft.matches(healthLeftIn); - } - } + private boolean test(int mediaGeneratedIn, double healthUsedIn, float healthLeftIn) { + return this.mediaGenerated.matches(mediaGeneratedIn) + && this.healthUsed.matches(healthUsedIn) + // DID YOU KNOW ALL THE ENEITYT PREDICATES ARE HARD-CODED AND YOU CANT MAKE NEW ONES + && this.healthLeft.matches(healthLeftIn); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/advancements/SpendMediaTrigger.java b/Common/src/main/java/at/petrak/hexcasting/api/advancements/SpendMediaTrigger.java index d610807f59..07bc8cfbf0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/advancements/SpendMediaTrigger.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/advancements/SpendMediaTrigger.java @@ -6,58 +6,59 @@ import net.minecraft.server.level.ServerPlayer; public class SpendMediaTrigger extends SimpleCriterionTrigger<SpendMediaTrigger.Instance> { - private static final ResourceLocation ID = new ResourceLocation("hexcasting", "spend_media"); - - private static final String TAG_MEDIA_SPENT = "media_spent"; - private static final String TAG_MEDIA_WASTED = "media_wasted"; - - @Override - public ResourceLocation getId() { - return ID; - } - - @Override - protected Instance createInstance(JsonObject json, ContextAwarePredicate predicate, - DeserializationContext context) { - return new Instance(predicate, - MinMaxLongs.fromJson(json.get(TAG_MEDIA_SPENT)), - MinMaxLongs.fromJson(json.get(TAG_MEDIA_WASTED))); - } - - public void trigger(ServerPlayer player, long mediaSpent, long mediaWasted) { - super.trigger(player, inst -> inst.test(mediaSpent, mediaWasted)); - } - - public static class Instance extends AbstractCriterionTriggerInstance { - protected final MinMaxLongs mediaSpent; - protected final MinMaxLongs mediaWasted; - - public Instance(ContextAwarePredicate predicate, MinMaxLongs mediaSpent, - MinMaxLongs mediaWasted) { - super(SpendMediaTrigger.ID, predicate); - this.mediaSpent = mediaSpent; - this.mediaWasted = mediaWasted; - } - - @Override - public ResourceLocation getCriterion() { - return ID; - } - - @Override - public JsonObject serializeToJson(SerializationContext ctx) { - JsonObject json = super.serializeToJson(ctx); - if (!this.mediaSpent.isAny()) { - json.add(TAG_MEDIA_SPENT, this.mediaSpent.serializeToJson()); - } - if (!this.mediaWasted.isAny()) { - json.add(TAG_MEDIA_WASTED, this.mediaWasted.serializeToJson()); - } - return json; - } - - private boolean test(long mediaSpentIn, long mediaWastedIn) { - return this.mediaSpent.matches(mediaSpentIn) && this.mediaWasted.matches(mediaWastedIn); - } - } + private static final ResourceLocation ID = new ResourceLocation("hexcasting", "spend_media"); + + private static final String TAG_MEDIA_SPENT = "media_spent"; + private static final String TAG_MEDIA_WASTED = "media_wasted"; + + @Override + public ResourceLocation getId() { + return ID; + } + + @Override + protected Instance createInstance( + JsonObject json, ContextAwarePredicate predicate, DeserializationContext context) { + return new Instance( + predicate, + MinMaxLongs.fromJson(json.get(TAG_MEDIA_SPENT)), + MinMaxLongs.fromJson(json.get(TAG_MEDIA_WASTED))); + } + + public void trigger(ServerPlayer player, long mediaSpent, long mediaWasted) { + super.trigger(player, inst -> inst.test(mediaSpent, mediaWasted)); + } + + public static class Instance extends AbstractCriterionTriggerInstance { + protected final MinMaxLongs mediaSpent; + protected final MinMaxLongs mediaWasted; + + public Instance( + ContextAwarePredicate predicate, MinMaxLongs mediaSpent, MinMaxLongs mediaWasted) { + super(SpendMediaTrigger.ID, predicate); + this.mediaSpent = mediaSpent; + this.mediaWasted = mediaWasted; + } + + @Override + public ResourceLocation getCriterion() { + return ID; + } + + @Override + public JsonObject serializeToJson(SerializationContext ctx) { + JsonObject json = super.serializeToJson(ctx); + if (!this.mediaSpent.isAny()) { + json.add(TAG_MEDIA_SPENT, this.mediaSpent.serializeToJson()); + } + if (!this.mediaWasted.isAny()) { + json.add(TAG_MEDIA_WASTED, this.mediaWasted.serializeToJson()); + } + return json; + } + + private boolean test(long mediaSpentIn, long mediaWastedIn) { + return this.mediaSpent.matches(mediaSpentIn) && this.mediaWasted.matches(mediaWastedIn); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/block/HexBlockEntity.java b/Common/src/main/java/at/petrak/hexcasting/api/block/HexBlockEntity.java index e531ddb12d..e77702a7d6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/block/HexBlockEntity.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/block/HexBlockEntity.java @@ -10,40 +10,39 @@ import net.minecraft.world.level.block.state.BlockState; public abstract class HexBlockEntity extends BlockEntity { - public HexBlockEntity(BlockEntityType<?> pType, BlockPos pWorldPosition, BlockState pBlockState) { - super(pType, pWorldPosition, pBlockState); - } - - protected abstract void saveModData(CompoundTag tag); - - protected abstract void loadModData(CompoundTag tag); - - @Override - protected void saveAdditional(CompoundTag pTag) { - this.saveModData(pTag); - } - - @Override - public void load(CompoundTag pTag) { - super.load(pTag); - this.loadModData(pTag); - } - - @Override - public CompoundTag getUpdateTag() { - CompoundTag tag = new CompoundTag(); - this.saveModData(tag); - return tag; - } - - @Override - public Packet<ClientGamePacketListener> getUpdatePacket() { - return ClientboundBlockEntityDataPacket.create(this); - } - - public void sync() { - this.setChanged(); - this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); - } - + public HexBlockEntity(BlockEntityType<?> pType, BlockPos pWorldPosition, BlockState pBlockState) { + super(pType, pWorldPosition, pBlockState); + } + + protected abstract void saveModData(CompoundTag tag); + + protected abstract void loadModData(CompoundTag tag); + + @Override + protected void saveAdditional(CompoundTag pTag) { + this.saveModData(pTag); + } + + @Override + public void load(CompoundTag pTag) { + super.load(pTag); + this.loadModData(pTag); + } + + @Override + public CompoundTag getUpdateTag() { + CompoundTag tag = new CompoundTag(); + this.saveModData(tag); + return tag; + } + + @Override + public Packet<ClientGamePacketListener> getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + public void sync() { + this.setChanged(); + this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockAbstractImpetus.java b/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockAbstractImpetus.java index d5197fce68..e1d7413559 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockAbstractImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockAbstractImpetus.java @@ -3,6 +3,7 @@ import at.petrak.hexcasting.api.casting.circles.BlockEntityAbstractImpetus; import at.petrak.hexcasting.api.casting.eval.env.CircleCastEnv; import at.petrak.hexcasting.api.casting.eval.vm.CastingImage; +import java.util.EnumSet; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; @@ -18,81 +19,87 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.DirectionProperty; -import java.util.EnumSet; - // Facing dir is the direction it starts searching for slates in to start public abstract class BlockAbstractImpetus extends BlockCircleComponent implements EntityBlock { - public static final DirectionProperty FACING = BlockStateProperties.FACING; + public static final DirectionProperty FACING = BlockStateProperties.FACING; - public BlockAbstractImpetus(Properties p_49795_) { - super(p_49795_); - this.registerDefaultState( - this.stateDefinition.any().setValue(ENERGIZED, false).setValue(FACING, Direction.NORTH)); - } + public BlockAbstractImpetus(Properties p_49795_) { + super(p_49795_); + this.registerDefaultState( + this.stateDefinition.any().setValue(ENERGIZED, false).setValue(FACING, Direction.NORTH)); + } - @Override - public ControlFlow acceptControlFlow(CastingImage imageIn, CircleCastEnv env, Direction enterDir, BlockPos pos, - BlockState bs, ServerLevel world) { - return new ControlFlow.Stop(); - } + @Override + public ControlFlow acceptControlFlow( + CastingImage imageIn, + CircleCastEnv env, + Direction enterDir, + BlockPos pos, + BlockState bs, + ServerLevel world) { + return new ControlFlow.Stop(); + } - @Override - public boolean canEnterFromDirection(Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world) { - // FACING is the direction media EXITS from, so we can't have media entering in that direction - // so, flip it - return enterDir != bs.getValue(FACING).getOpposite(); - } + @Override + public boolean canEnterFromDirection( + Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world) { + // FACING is the direction media EXITS from, so we can't have media entering in that direction + // so, flip it + return enterDir != bs.getValue(FACING).getOpposite(); + } - @Override - public EnumSet<Direction> possibleExitDirections(BlockPos pos, BlockState bs, Level world) { - return EnumSet.of(bs.getValue(FACING)); - } + @Override + public EnumSet<Direction> possibleExitDirections(BlockPos pos, BlockState bs, Level world) { + return EnumSet.of(bs.getValue(FACING)); + } - @Override - public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) { - return normalDirOfOther(pos.relative(bs.getValue(FACING)), world, recursionLeft); - } + @Override + public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) { + return normalDirOfOther(pos.relative(bs.getValue(FACING)), world, recursionLeft); + } - @Override - public float particleHeight(BlockPos pos, BlockState bs, Level world) { - return 0.5f; - } + @Override + public float particleHeight(BlockPos pos, BlockState bs, Level world) { + return 0.5f; + } - @Override - public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRandom) { - if (pLevel.getBlockEntity(pPos) instanceof BlockEntityAbstractImpetus tile && pState.getValue(ENERGIZED)) { - tile.tickExecution(); - } - } + @Override + public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRandom) { + if (pLevel.getBlockEntity(pPos) instanceof BlockEntityAbstractImpetus tile + && pState.getValue(ENERGIZED)) { + tile.tickExecution(); + } + } - @Override - public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { - if (!pNewState.is(pState.getBlock()) - && pLevel.getBlockEntity(pPos) instanceof BlockEntityAbstractImpetus impetus) { - impetus.endExecution(); // TODO: Determine if this was important - // TODO: Fix this, it should make all the glowy circle components stop glowing. - } - super.onRemove(pState, pLevel, pPos, pNewState, pIsMoving); - } + @Override + public void onRemove( + BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { + if (!pNewState.is(pState.getBlock()) + && pLevel.getBlockEntity(pPos) instanceof BlockEntityAbstractImpetus impetus) { + impetus.endExecution(); // TODO: Determine if this was important + // TODO: Fix this, it should make all the glowy circle components stop glowing. + } + super.onRemove(pState, pLevel, pPos, pNewState, pIsMoving); + } - @Override - protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { - super.createBlockStateDefinition(builder); - builder.add(FACING); - } + @Override + protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { + super.createBlockStateDefinition(builder); + builder.add(FACING); + } - @Override - public BlockState getStateForPlacement(BlockPlaceContext pContext) { - return BlockCircleComponent.placeStateDirAndSneak(this.defaultBlockState(), pContext); - } + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + return BlockCircleComponent.placeStateDirAndSneak(this.defaultBlockState(), pContext); + } - @Override - public BlockState rotate(BlockState pState, Rotation pRot) { - return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING))); - } + @Override + public BlockState rotate(BlockState pState, Rotation pRot) { + return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING))); + } - @Override - public BlockState mirror(BlockState pState, Mirror pMirror) { - return pState.rotate(pMirror.getRotation(pState.getValue(FACING))); - } + @Override + public BlockState mirror(BlockState pState, Mirror pMirror) { + return pState.rotate(pMirror.getRotation(pState.getValue(FACING))); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockCircleComponent.java b/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockCircleComponent.java index f2c1458c7b..35eac540f1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockCircleComponent.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockCircleComponent.java @@ -14,82 +14,82 @@ // Convenience impl of ICircleComponent public abstract class BlockCircleComponent extends Block implements ICircleComponent { - public static final BooleanProperty ENERGIZED = BooleanProperty.create("energized"); - - public BlockCircleComponent(Properties p_49795_) { - super(p_49795_); - } - - @Override - public BlockState startEnergized(BlockPos pos, BlockState bs, Level world) { - var newState = bs.setValue(ENERGIZED, true); - world.setBlockAndUpdate(pos, newState); - - return newState; - } - - @Override - public boolean isEnergized(BlockPos pos, BlockState bs, Level world) { - return bs.getValue(ENERGIZED); - } - - @Override - public BlockState endEnergized(BlockPos pos, BlockState bs, Level world) { - var newState = bs.setValue(ENERGIZED, false); - world.setBlockAndUpdate(pos, newState); - return newState; - } - - /** - * Which direction points "up" or "out" for this block? - * This is used for {@link ICircleComponent#canEnterFromDirection(Direction, BlockPos, BlockState, ServerLevel)} - * as well as particles. - */ - public Direction normalDir(BlockPos pos, BlockState bs, Level world) { - return normalDir(pos, bs, world, 16); - } - - abstract public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft); - - public static Direction normalDirOfOther(BlockPos other, Level world, int recursionLeft) { - if (recursionLeft <= 0) { - return Direction.UP; - } - - var stateThere = world.getBlockState(other); - if (stateThere.getBlock() instanceof BlockCircleComponent bcc) { - return bcc.normalDir(other, stateThere, world, recursionLeft - 1); - } else { - return Direction.UP; - } - } - - /** - * How many blocks in the {@link BlockCircleComponent#normalDir(BlockPos, BlockState, Level)} from the center - * particles should be spawned in - */ - abstract public float particleHeight(BlockPos pos, BlockState bs, Level world); - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> pBuilder) { - pBuilder.add(ENERGIZED); - } - - @Override - public boolean hasAnalogOutputSignal(BlockState pState) { - return true; - } - - @Override - public int getAnalogOutputSignal(BlockState pState, Level pLevel, BlockPos pPos) { - return pState.getValue(ENERGIZED) ? 15 : 0; - } - - public static BlockState placeStateDirAndSneak(BlockState stock, BlockPlaceContext ctx) { - var dir = ctx.getNearestLookingDirection(); - if (ctx.getPlayer() != null && ctx.getPlayer().isDiscrete()) { - dir = dir.getOpposite(); - } - return stock.setValue(BlockStateProperties.FACING, dir); - } + public static final BooleanProperty ENERGIZED = BooleanProperty.create("energized"); + + public BlockCircleComponent(Properties p_49795_) { + super(p_49795_); + } + + @Override + public BlockState startEnergized(BlockPos pos, BlockState bs, Level world) { + var newState = bs.setValue(ENERGIZED, true); + world.setBlockAndUpdate(pos, newState); + + return newState; + } + + @Override + public boolean isEnergized(BlockPos pos, BlockState bs, Level world) { + return bs.getValue(ENERGIZED); + } + + @Override + public BlockState endEnergized(BlockPos pos, BlockState bs, Level world) { + var newState = bs.setValue(ENERGIZED, false); + world.setBlockAndUpdate(pos, newState); + return newState; + } + + /** + * Which direction points "up" or "out" for this block? This is used for {@link + * ICircleComponent#canEnterFromDirection(Direction, BlockPos, BlockState, ServerLevel)} as well + * as particles. + */ + public Direction normalDir(BlockPos pos, BlockState bs, Level world) { + return normalDir(pos, bs, world, 16); + } + + public abstract Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft); + + public static Direction normalDirOfOther(BlockPos other, Level world, int recursionLeft) { + if (recursionLeft <= 0) { + return Direction.UP; + } + + var stateThere = world.getBlockState(other); + if (stateThere.getBlock() instanceof BlockCircleComponent bcc) { + return bcc.normalDir(other, stateThere, world, recursionLeft - 1); + } else { + return Direction.UP; + } + } + + /** + * How many blocks in the {@link BlockCircleComponent#normalDir(BlockPos, BlockState, Level)} from + * the center particles should be spawned in + */ + public abstract float particleHeight(BlockPos pos, BlockState bs, Level world); + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> pBuilder) { + pBuilder.add(ENERGIZED); + } + + @Override + public boolean hasAnalogOutputSignal(BlockState pState) { + return true; + } + + @Override + public int getAnalogOutputSignal(BlockState pState, Level pLevel, BlockPos pPos) { + return pState.getValue(ENERGIZED) ? 15 : 0; + } + + public static BlockState placeStateDirAndSneak(BlockState stock, BlockPlaceContext ctx) { + var dir = ctx.getNearestLookingDirection(); + if (ctx.getPlayer() != null && ctx.getPlayer().isDiscrete()) { + dir = dir.getOpposite(); + } + return stock.setValue(BlockStateProperties.FACING, dir); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionRegistryEntry.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionRegistryEntry.java index dbc5dc060b..d7bb7876b6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionRegistryEntry.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionRegistryEntry.java @@ -6,10 +6,9 @@ /** * A bit of wrapper information around an action to go in the registry. * - * @param prototype The pattern associated with this action. The start dir acts as the "canonical" start direction - * for display in the book. For per-world patterns, the angle signature is the *shape* of the pattern - * but probably not the pattern itself. - * @param action The action itself + * @param prototype The pattern associated with this action. The start dir acts as the "canonical" + * start direction for display in the book. For per-world patterns, the angle signature is the + * *shape* of the pattern but probably not the pattern itself. + * @param action The action itself */ -public record ActionRegistryEntry(HexPattern prototype, Action action) { -} +public record ActionRegistryEntry(HexPattern prototype, Action action) {} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt index 26f39da2f3..1ebb1cf06d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt @@ -8,6 +8,10 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapInvalidIota import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs import at.petrak.hexcasting.api.utils.asTranslatedComponent import com.mojang.datafixers.util.Either +import java.util.function.DoubleUnaryOperator +import kotlin.math.abs +import kotlin.math.roundToInt +import kotlin.math.roundToLong import net.minecraft.core.BlockPos import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.Entity @@ -17,273 +21,281 @@ import net.minecraft.world.entity.decoration.ArmorStand import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.phys.Vec3 import org.joml.Vector3f -import java.util.function.DoubleUnaryOperator -import kotlin.math.abs -import kotlin.math.roundToInt -import kotlin.math.roundToLong fun List<Iota>.getDouble(idx: Int, argc: Int = 0): Double { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is DoubleIota) { - return x.double - } else { - // TODO: I'm not sure this calculation is correct - throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "double") - } + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is DoubleIota) { + return x.double + } else { + // TODO: I'm not sure this calculation is correct + throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "double") + } } fun List<Iota>.getEntity(idx: Int, argc: Int = 0): Entity { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is EntityIota) { - return x.entity - } else { - throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity") - } + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is EntityIota) { + return x.entity + } else { + throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity") + } } fun List<Iota>.getList(idx: Int, argc: Int = 0): SpellList { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is ListIota) { - return x.list - } else { - throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "list") - } + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is ListIota) { + return x.list + } else { + throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "list") + } } fun List<Iota>.getPattern(idx: Int, argc: Int = 0): HexPattern { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is PatternIota) { - return x.pattern - } else { - throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "pattern") - } + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is PatternIota) { + return x.pattern + } else { + throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "pattern") + } } fun List<Iota>.getVec3(idx: Int, argc: Int = 0): Vec3 { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is Vec3Iota) { - return x.vec3 - } else { - throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "vector") - } + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is Vec3Iota) { + return x.vec3 + } else { + throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "vector") + } } fun List<Iota>.getBool(idx: Int, argc: Int = 0): Boolean { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is BooleanIota) { - return x.bool - } else { - throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "boolean") - } + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is BooleanIota) { + return x.bool + } else { + throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "boolean") + } } // Helpers fun List<Iota>.getItemEntity(idx: Int, argc: Int = 0): ItemEntity { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is EntityIota) { - val e = x.entity - if (e is ItemEntity) - return e - } - throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.item") + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is EntityIota) { + val e = x.entity + if (e is ItemEntity) return e + } + throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.item") } fun List<Iota>.getPlayer(idx: Int, argc: Int = 0): ServerPlayer { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is EntityIota) { - val e = x.entity - if (e is ServerPlayer) - return e - } - throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.player") + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is EntityIota) { + val e = x.entity + if (e is ServerPlayer) return e + } + throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.player") } fun List<Iota>.getMob(idx: Int, argc: Int = 0): Mob { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is EntityIota) { - val e = x.entity - if (e is Mob) - return e - } - throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.mob") + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is EntityIota) { + val e = x.entity + if (e is Mob) return e + } + throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.mob") } fun List<Iota>.getLivingEntityButNotArmorStand(idx: Int, argc: Int = 0): LivingEntity { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is EntityIota) { - val e = x.entity - if (e is LivingEntity && e !is ArmorStand) - return e - } - throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.living") + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is EntityIota) { + val e = x.entity + if (e is LivingEntity && e !is ArmorStand) return e + } + throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.living") } fun List<Iota>.getPositiveDouble(idx: Int, argc: Int = 0): Double { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is DoubleIota) { - val double = x.double - if (0 <= double) { - return double - } - } - throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "double.positive") + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is DoubleIota) { + val double = x.double + if (0 <= double) { + return double + } + } + throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "double.positive") } fun List<Iota>.getPositiveDoubleUnder(idx: Int, max: Double, argc: Int = 0): Double { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is DoubleIota) { - val double = x.double - if (0.0 <= double && double < max) { - return double - } - } - throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "double.positive.less", max) + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is DoubleIota) { + val double = x.double + if (0.0 <= double && double < max) { + return double + } + } + throw MishapInvalidIota.of( + x, + if (argc == 0) idx else argc - (idx + 1), + "double.positive.less", + max + ) } fun List<Iota>.getPositiveDoubleUnderInclusive(idx: Int, max: Double, argc: Int = 0): Double { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is DoubleIota) { - val double = x.double - if (double in 0.0..max) { - return double - } - } - throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "double.positive.less.equal", max) + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is DoubleIota) { + val double = x.double + if (double in 0.0..max) { + return double + } + } + throw MishapInvalidIota.of( + x, + if (argc == 0) idx else argc - (idx + 1), + "double.positive.less.equal", + max + ) } fun List<Iota>.getDoubleBetween(idx: Int, min: Double, max: Double, argc: Int = 0): Double { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is DoubleIota) { - val double = x.double - if (double in min..max) { - return double - } - } - throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "double.between", min, max) + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is DoubleIota) { + val double = x.double + if (double in min..max) { + return double + } + } + throw MishapInvalidIota.of( + x, + if (argc == 0) idx else argc - (idx + 1), + "double.between", + min, + max + ) } fun List<Iota>.getInt(idx: Int, argc: Int = 0): Int { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is DoubleIota) { - val double = x.double - val rounded = double.roundToInt() - if (abs(double - rounded) <= DoubleIota.TOLERANCE) { - return rounded - } - } - throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int") + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is DoubleIota) { + val double = x.double + val rounded = double.roundToInt() + if (abs(double - rounded) <= DoubleIota.TOLERANCE) { + return rounded + } + } + throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int") } fun List<Iota>.getLong(idx: Int, argc: Int = 0): Long { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is DoubleIota) { - val double = x.double - val rounded = double.roundToLong() - if (abs(double - rounded) <= DoubleIota.TOLERANCE) { - return rounded - } - } - throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int") // shh we're lying + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is DoubleIota) { + val double = x.double + val rounded = double.roundToLong() + if (abs(double - rounded) <= DoubleIota.TOLERANCE) { + return rounded + } + } + throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int") // shh we're lying } fun List<Iota>.getPositiveInt(idx: Int, argc: Int = 0): Int { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is DoubleIota) { - val double = x.double - val rounded = double.roundToInt() - if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded >= 0) { - return rounded - } - } - throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int.positive") + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is DoubleIota) { + val double = x.double + val rounded = double.roundToInt() + if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded >= 0) { + return rounded + } + } + throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int.positive") } fun List<Iota>.getPositiveIntUnder(idx: Int, max: Int, argc: Int = 0): Int { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is DoubleIota) { - val double = x.double - val rounded = double.roundToInt() - if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded in 0 until max) { - return rounded - } - } - throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int.positive.less", max) + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is DoubleIota) { + val double = x.double + val rounded = double.roundToInt() + if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded in 0 until max) { + return rounded + } + } + throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int.positive.less", max) } fun List<Iota>.getPositiveIntUnderInclusive(idx: Int, max: Int, argc: Int = 0): Int { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is DoubleIota) { - val double = x.double - val rounded = double.roundToInt() - if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded in 0..max) { - return rounded - } - } - throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int.positive.less.equal", max) + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is DoubleIota) { + val double = x.double + val rounded = double.roundToInt() + if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded in 0..max) { + return rounded + } + } + throw MishapInvalidIota.of( + x, + if (argc == 0) idx else argc - (idx + 1), + "int.positive.less.equal", + max + ) } fun List<Iota>.getIntBetween(idx: Int, min: Int, max: Int, argc: Int = 0): Int { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is DoubleIota) { - val double = x.double - val rounded = double.roundToInt() - if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded in min..max) { - return rounded - } - } - throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int.between", min, max) + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is DoubleIota) { + val double = x.double + val rounded = double.roundToInt() + if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded in min..max) { + return rounded + } + } + throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int.between", min, max) } fun List<Iota>.getBlockPos(idx: Int, argc: Int = 0): BlockPos { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is Vec3Iota) { - return BlockPos.containing(x.vec3) - } + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is Vec3Iota) { + return BlockPos.containing(x.vec3) + } - throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "vector") + throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "vector") } fun List<Iota>.getNumOrVec(idx: Int, argc: Int = 0): Either<Double, Vec3> { - val datum = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - return when (datum) { - is DoubleIota -> Either.left(datum.double) - is Vec3Iota -> Either.right(datum.vec3) - else -> throw MishapInvalidIota.of( - datum, - if (argc == 0) idx else argc - (idx + 1), - "numvec" - ) - } + val datum = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + return when (datum) { + is DoubleIota -> Either.left(datum.double) + is Vec3Iota -> Either.right(datum.vec3) + else -> throw MishapInvalidIota.of(datum, if (argc == 0) idx else argc - (idx + 1), "numvec") + } } fun List<Iota>.getLongOrList(idx: Int, argc: Int = 0): Either<Long, SpellList> { - val datum = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (datum is DoubleIota) { - val double = datum.double - val rounded = double.roundToLong() - if (abs(double - rounded) <= DoubleIota.TOLERANCE) { - return Either.left(rounded) - } - } else if (datum is ListIota) { - return Either.right(datum.list) - } - throw MishapInvalidIota.of( - datum, - if (argc == 0) idx else argc - (idx + 1), - "numlist" - ) + val datum = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (datum is DoubleIota) { + val double = datum.double + val rounded = double.roundToLong() + if (abs(double - rounded) <= DoubleIota.TOLERANCE) { + return Either.left(rounded) + } + } else if (datum is ListIota) { + return Either.right(datum.list) + } + throw MishapInvalidIota.of(datum, if (argc == 0) idx else argc - (idx + 1), "numlist") } fun evaluatable(datum: Iota, reverseIdx: Int): Either<Iota, SpellList> = - when (datum) { - is ListIota -> Either.right(datum.list) - else -> if (datum.executable()) Either.left(datum) else throw MishapInvalidIota( - datum, - reverseIdx, - "hexcasting.mishap.invalid_value.evaluatable".asTranslatedComponent - ) - } + when (datum) { + is ListIota -> Either.right(datum.list) + else -> + if (datum.executable()) Either.left(datum) + else + throw MishapInvalidIota( + datum, + reverseIdx, + "hexcasting.mishap.invalid_value.evaluatable".asTranslatedComponent + ) + } fun Iota?.orNull() = this ?: NullIota() @@ -291,21 +303,33 @@ fun Iota?.orNull() = this ?: NullIota() // there should probably be some way to abstract function application over lists, vecs, and numbers, // and i bet it's fucking monads fun aplKinnie(operatee: Either<Double, Vec3>, fn: DoubleUnaryOperator): Iota = - operatee.map( - { num -> DoubleIota(fn.applyAsDouble(num)) }, - { vec -> Vec3Iota(Vec3(fn.applyAsDouble(vec.x), fn.applyAsDouble(vec.y), fn.applyAsDouble(vec.z))) } - ) - -inline val Boolean.asActionResult get() = listOf(BooleanIota(this)) -inline val Double.asActionResult get() = listOf(DoubleIota(this)) -inline val Number.asActionResult get() = listOf(DoubleIota(this.toDouble())) - -inline val SpellList.asActionResult get() = listOf(ListIota(this)) -inline val List<Iota>.asActionResult get() = listOf(ListIota(this)) - -inline val BlockPos.asActionResult get() = listOf(Vec3Iota(Vec3.atCenterOf(this))) -inline val Vector3f.asActionResult get() = listOf(Vec3Iota(Vec3(this))) -inline val Vec3.asActionResult get() = listOf(Vec3Iota(this)) - -inline val Entity?.asActionResult get() = listOf(if (this == null) NullIota() else EntityIota(this)) -inline val HexPattern.asActionResult get() = listOf(PatternIota(this)) + operatee.map( + { num -> DoubleIota(fn.applyAsDouble(num)) }, + { vec -> + Vec3Iota(Vec3(fn.applyAsDouble(vec.x), fn.applyAsDouble(vec.y), fn.applyAsDouble(vec.z))) + } + ) + +inline val Boolean.asActionResult + get() = listOf(BooleanIota(this)) +inline val Double.asActionResult + get() = listOf(DoubleIota(this)) +inline val Number.asActionResult + get() = listOf(DoubleIota(this.toDouble())) + +inline val SpellList.asActionResult + get() = listOf(ListIota(this)) +inline val List<Iota>.asActionResult + get() = listOf(ListIota(this)) + +inline val BlockPos.asActionResult + get() = listOf(Vec3Iota(Vec3.atCenterOf(this))) +inline val Vector3f.asActionResult + get() = listOf(Vec3Iota(Vec3(this))) +inline val Vec3.asActionResult + get() = listOf(Vec3Iota(this)) + +inline val Entity?.asActionResult + get() = listOf(if (this == null) NullIota() else EntityIota(this)) +inline val HexPattern.asActionResult + get() = listOf(PatternIota(this)) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/ParticleSpray.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/ParticleSpray.kt index 88129e6bf8..dc7e8e0963 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/ParticleSpray.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/ParticleSpray.kt @@ -10,20 +10,31 @@ import net.minecraft.world.phys.Vec3 * @param fuzziness the radius of the sphere the particle might happen in (pos) * @param spread the max angle in radians the particle can move in, in relation to vel */ -data class ParticleSpray(val pos: Vec3, val vel: Vec3, val fuzziness: Double, val spread: Double, val count: Int = 20) { - companion object { - @JvmStatic - fun burst(pos: Vec3, size: Double, count: Int = 20): ParticleSpray { - return ParticleSpray(pos, Vec3(size, 0.0, 0.0), 0.0, 3.14, count) - } +data class ParticleSpray( + val pos: Vec3, + val vel: Vec3, + val fuzziness: Double, + val spread: Double, + val count: Int = 20 +) { + companion object { + @JvmStatic + fun burst(pos: Vec3, size: Double, count: Int = 20): ParticleSpray { + return ParticleSpray(pos, Vec3(size, 0.0, 0.0), 0.0, 3.14, count) + } - @JvmStatic - fun cloud(pos: Vec3, size: Double, count: Int = 20): ParticleSpray { - return ParticleSpray(pos, Vec3(0.0, 0.001, 0.0), size, 0.0, count) - } - } + @JvmStatic + fun cloud(pos: Vec3, size: Double, count: Int = 20): ParticleSpray { + return ParticleSpray(pos, Vec3(0.0, 0.001, 0.0), size, 0.0, count) + } + } - fun sprayParticles(world: ServerLevel, color: FrozenPigment) { - IXplatAbstractions.INSTANCE.sendPacketNear(this.pos, 128.0, world, MsgCastParticleS2C(this, color)) - } + fun sprayParticles(world: ServerLevel, color: FrozenPigment) { + IXplatAbstractions.INSTANCE.sendPacketNear( + this.pos, + 128.0, + world, + MsgCastParticleS2C(this, color) + ) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/PatternShapeMatch.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/PatternShapeMatch.java index b72d349895..b66f025a4b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/PatternShapeMatch.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/PatternShapeMatch.java @@ -3,55 +3,46 @@ import at.petrak.hexcasting.api.casting.castables.SpecialHandler; import net.minecraft.resources.ResourceKey; -/** - * Possible things we find when trying to match a pattern's shape. - */ +/** Possible things we find when trying to match a pattern's shape. */ public abstract sealed class PatternShapeMatch { - /** - * I've never met that pattern in my life - */ - public static final class Nothing extends PatternShapeMatch { - } - - /** - * The shape exactly matches a pattern that isn't altered per world - */ - public static final class Normal extends PatternShapeMatch { - public final ResourceKey<ActionRegistryEntry> key; - - public Normal(ResourceKey<ActionRegistryEntry> key) { - this.key = key; - } - } - - /** - * The pattern is the right <em>shape</em> to be one of the per-world patterns. - * <p> - * On the server, {@link PerWorld#certain} means whether this is an exact match, or if it's just the - * right shape. (In other words it should only actually be casted if it is true.) - * <p> - * On the client, it is always false. - */ - public static final class PerWorld extends PatternShapeMatch { - public final ResourceKey<ActionRegistryEntry> key; - public final boolean certain; - - public PerWorld(ResourceKey<ActionRegistryEntry> key, boolean certain) { - this.key = key; - this.certain = certain; - } - } - - /** - * The shape matches a special handler - */ - public static final class Special extends PatternShapeMatch { - public final ResourceKey<SpecialHandler.Factory<?>> key; - public final SpecialHandler handler; - - public Special(ResourceKey<SpecialHandler.Factory<?>> key, SpecialHandler handler) { - this.key = key; - this.handler = handler; - } - } + /** I've never met that pattern in my life */ + public static final class Nothing extends PatternShapeMatch {} + + /** The shape exactly matches a pattern that isn't altered per world */ + public static final class Normal extends PatternShapeMatch { + public final ResourceKey<ActionRegistryEntry> key; + + public Normal(ResourceKey<ActionRegistryEntry> key) { + this.key = key; + } + } + + /** + * The pattern is the right <em>shape</em> to be one of the per-world patterns. + * + * <p>On the server, {@link PerWorld#certain} means whether this is an exact match, or if it's + * just the right shape. (In other words it should only actually be casted if it is true.) + * + * <p>On the client, it is always false. + */ + public static final class PerWorld extends PatternShapeMatch { + public final ResourceKey<ActionRegistryEntry> key; + public final boolean certain; + + public PerWorld(ResourceKey<ActionRegistryEntry> key, boolean certain) { + this.key = key; + this.certain = certain; + } + } + + /** The shape matches a special handler */ + public static final class Special extends PatternShapeMatch { + public final ResourceKey<SpecialHandler.Factory<?>> key; + public final SpecialHandler handler; + + public Special(ResourceKey<SpecialHandler.Factory<?>> key, SpecialHandler handler) { + this.key = key; + this.handler = handler; + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/RenderedSpell.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/RenderedSpell.kt index 20ea047d91..d4dfc938b4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/RenderedSpell.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/RenderedSpell.kt @@ -4,10 +4,10 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.eval.vm.CastingImage interface RenderedSpell { - fun cast(env: CastingEnvironment) + fun cast(env: CastingEnvironment) - fun cast(env: CastingEnvironment, image: CastingImage): CastingImage? { - cast(env) - return null - } + fun cast(env: CastingEnvironment, image: CastingImage): CastingImage? { + cast(env) + return null + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/SpellList.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/SpellList.kt index 2e76c18c76..b5468251e5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/SpellList.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/SpellList.kt @@ -9,85 +9,86 @@ import at.petrak.hexcasting.api.casting.iota.Iota */ sealed class SpellList : Iterable<Iota> { - abstract val nonEmpty: Boolean - abstract val car: Iota - abstract val cdr: SpellList + abstract val nonEmpty: Boolean + abstract val car: Iota + abstract val cdr: SpellList - class LPair(override val car: Iota, override val cdr: SpellList) : SpellList() { - override val nonEmpty = true - } + class LPair(override val car: Iota, override val cdr: SpellList) : SpellList() { + override val nonEmpty = true + } - class LList(val idx: Int, val list: List<Iota>) : SpellList() { - override val nonEmpty: Boolean - get() = idx < list.size - override val car: Iota - get() = list[idx] - override val cdr: SpellList - get() = LList(idx + 1, list) + class LList(val idx: Int, val list: List<Iota>) : SpellList() { + override val nonEmpty: Boolean + get() = idx < list.size - constructor(list: List<Iota>) : this(0, list) - } + override val car: Iota + get() = list[idx] - fun modifyAt(startIdx: Int, modify: (SpellList) -> SpellList): SpellList { - val stack = mutableListOf<Iota>() - val ptr = iterator() - var idx = startIdx - if (idx < 0) { - return this - } - while (idx > 0) { - if (!ptr.hasNext()) { - return this - } - idx-- - stack.add(ptr.next()) - } - var value = modify(ptr.list) - for (datum in stack.asReversed()) { - value = LPair(datum, value) - } - return value - } + override val cdr: SpellList + get() = LList(idx + 1, list) - fun getAt(startIdx: Int): Iota { - var ptr = this - var idx = startIdx - if (idx < 0) { - throw ArrayIndexOutOfBoundsException() - } - while (idx > 0) { - when (ptr) { - is LPair -> ptr = ptr.cdr - is LList -> return ptr.list[ptr.idx + idx] - } - idx-- - } - return ptr.car - } + constructor(list: List<Iota>) : this(0, list) + } - override fun toString() = toList().toString() + fun modifyAt(startIdx: Int, modify: (SpellList) -> SpellList): SpellList { + val stack = mutableListOf<Iota>() + val ptr = iterator() + var idx = startIdx + if (idx < 0) { + return this + } + while (idx > 0) { + if (!ptr.hasNext()) { + return this + } + idx-- + stack.add(ptr.next()) + } + var value = modify(ptr.list) + for (datum in stack.asReversed()) { + value = LPair(datum, value) + } + return value + } - override fun iterator() = SpellListIterator(this) + fun getAt(startIdx: Int): Iota { + var ptr = this + var idx = startIdx + if (idx < 0) { + throw ArrayIndexOutOfBoundsException() + } + while (idx > 0) { + when (ptr) { + is LPair -> ptr = ptr.cdr + is LList -> return ptr.list[ptr.idx + idx] + } + idx-- + } + return ptr.car + } - /** - * Note this is O(n), probably. - */ - fun size(): Int { - var size = 0 - var ptr = this - while (ptr.nonEmpty) { - ptr = ptr.cdr - size++ - } - return size - } + override fun toString() = toList().toString() - class SpellListIterator(var list: SpellList) : Iterator<Iota> { - override fun hasNext() = list.nonEmpty - override operator fun next(): Iota { - val car = list.car - list = list.cdr - return car - } - } + override fun iterator() = SpellListIterator(this) + + /** Note this is O(n), probably. */ + fun size(): Int { + var size = 0 + var ptr = this + while (ptr.nonEmpty) { + ptr = ptr.cdr + size++ + } + return size + } + + class SpellListIterator(var list: SpellList) : Iterator<Iota> { + override fun hasNext() = list.nonEmpty + + override operator fun next(): Iota { + val car = list.car + list = list.cdr + return car + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/Arithmetic.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/Arithmetic.java index 10f9f9cd6e..3ae9067de3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/Arithmetic.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/Arithmetic.java @@ -5,8 +5,8 @@ import at.petrak.hexcasting.api.casting.math.HexPattern; /** - * This is the interface to implement if you want to override the behaviour of an Operator pattern like ADD, SUB, etc. for some type/s of - * iotas for which that Operator pattern is not yet defined. + * This is the interface to implement if you want to override the behaviour of an Operator pattern + * like ADD, SUB, etc. for some type/s of iotas for which that Operator pattern is not yet defined. */ public interface Arithmetic { String arithName(); @@ -42,7 +42,6 @@ public interface Arithmetic { HexPattern LOG = HexPattern.fromAngles("eqaqe", HexDir.NORTH_WEST); HexPattern MOD = HexPattern.fromAngles("addwaad", HexDir.NORTH_EAST); - // Vecs HexPattern PACK = HexPattern.fromAngles("eqqqqq", HexDir.EAST); HexPattern UNPACK = HexPattern.fromAngles("qeeeee", HexDir.EAST); diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/IterPair.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/IterPair.java index 64ff91fb25..9771e027ac 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/IterPair.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/IterPair.java @@ -7,15 +7,19 @@ public record IterPair<T>(T left, T right) implements Iterable<T> { public Iterator<T> iterator() { return new Iterator<T>() { int ix; + @Override public boolean hasNext() { return ix < 2; } + @Override public T next() { switch (ix++) { - case 0: return left; - case 1: return right; + case 0: + return left; + case 1: + return right; } return null; } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/TripleIterable.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/TripleIterable.java index e066a106c1..45eb510eab 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/TripleIterable.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/TripleIterable.java @@ -1,43 +1,45 @@ package at.petrak.hexcasting.api.casting.arithmetic; +import java.util.Iterator; import org.apache.commons.lang3.function.TriFunction; import org.jetbrains.annotations.NotNull; -import java.util.Iterator; - -public class TripleIterable<A,B,C,D> implements Iterable<D> { - private final Iterable<A> iterableA; - private final Iterable<B> iterableB; - private final Iterable<C> iterableC; - - private final TriFunction<A, B, C, D> map; - - public TripleIterable(Iterable<A> iterableA, Iterable<B> iterableB, Iterable<C> iterableC, TriFunction<A, B, C, D> map) { - this.iterableA = iterableA; - this.iterableB = iterableB; - this.iterableC = iterableC; - this.map = map; - } - - @NotNull - @Override - public Iterator<D> iterator() { - return new TripleIterator(); - } - - class TripleIterator implements Iterator<D> { - private final Iterator<A> iteratorA = iterableA.iterator(); - private final Iterator<B> iteratorB = iterableB.iterator(); - private final Iterator<C> iteratorC = iterableC.iterator(); - - @Override - public boolean hasNext() { - return iteratorA.hasNext() && iteratorB.hasNext() && iteratorC.hasNext(); - } - - @Override - public D next() { - return map.apply(iteratorA.next(), iteratorB.next(), iteratorC.next()); - } - } +public class TripleIterable<A, B, C, D> implements Iterable<D> { + private final Iterable<A> iterableA; + private final Iterable<B> iterableB; + private final Iterable<C> iterableC; + + private final TriFunction<A, B, C, D> map; + + public TripleIterable( + Iterable<A> iterableA, + Iterable<B> iterableB, + Iterable<C> iterableC, + TriFunction<A, B, C, D> map) { + this.iterableA = iterableA; + this.iterableB = iterableB; + this.iterableC = iterableC; + this.map = map; + } + + @NotNull @Override + public Iterator<D> iterator() { + return new TripleIterator(); + } + + class TripleIterator implements Iterator<D> { + private final Iterator<A> iteratorA = iterableA.iterator(); + private final Iterator<B> iteratorB = iterableB.iterator(); + private final Iterator<C> iteratorC = iterableC.iterator(); + + @Override + public boolean hasNext() { + return iteratorA.hasNext() && iteratorB.hasNext() && iteratorC.hasNext(); + } + + @Override + public D next() { + return map.apply(iteratorA.next(), iteratorB.next(), iteratorC.next()); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/ArithmeticEngine.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/ArithmeticEngine.java index 2f7e1fe7dc..7e5a0a931e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/ArithmeticEngine.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/ArithmeticEngine.java @@ -10,101 +10,124 @@ import at.petrak.hexcasting.api.casting.math.HexPattern; import at.petrak.hexcasting.api.casting.mishaps.Mishap; import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs; - import java.util.*; /** - * This is the class responsible for managing the various Arithmetics that are in use, deciding based on the current - * stack which Operator should be called, etc. + * This is the class responsible for managing the various Arithmetics that are in use, deciding + * based on the current stack which Operator should be called, etc. */ public class ArithmeticEngine { - /** - * Data structure for mapping the pattern that gets drawn on the stack to the list of Operators that - * are overloading that pattern. - * @param pattern The pattern that the caster will need to draw to cast one of these operators. - * @param arity The number of arguments that all of these operators must consume from the stack. - * @param operators The list of all operators that overload this pattern. - */ - private record OpCandidates(HexPattern pattern, int arity, List<Operator> operators) { - public void addOp(Operator next) { - if (next.arity != arity) { - throw new IllegalArgumentException("Operators exist of differing arity! The pattern " + pattern - + " already had arity " + arity + " when the operator with arity " + next.arity + ", " + next + " was added."); - } - operators.add(next); - } - } + /** + * Data structure for mapping the pattern that gets drawn on the stack to the list of Operators + * that are overloading that pattern. + * + * @param pattern The pattern that the caster will need to draw to cast one of these operators. + * @param arity The number of arguments that all of these operators must consume from the stack. + * @param operators The list of all operators that overload this pattern. + */ + private record OpCandidates(HexPattern pattern, int arity, List<Operator> operators) { + public void addOp(Operator next) { + if (next.arity != arity) { + throw new IllegalArgumentException( + "Operators exist of differing arity! The pattern " + + pattern + + " already had arity " + + arity + + " when the operator with arity " + + next.arity + + ", " + + next + + " was added."); + } + operators.add(next); + } + } - public final Arithmetic[] arithmetics; - private final Map<HexPattern, OpCandidates> operators = new HashMap<>(); + public final Arithmetic[] arithmetics; + private final Map<HexPattern, OpCandidates> operators = new HashMap<>(); - /** - * A cache mapping specific sets of Pattern, IotaType, IotaType, ..., IotaType to Operators so that the Operators don't need to be - * queried for what types they accept every time they are used. - */ - private final Map<HashCons, Operator> cache = new HashMap<>(); + /** + * A cache mapping specific sets of Pattern, IotaType, IotaType, ..., IotaType to Operators so + * that the Operators don't need to be queried for what types they accept every time they are + * used. + */ + private final Map<HashCons, Operator> cache = new HashMap<>(); - public ArithmeticEngine(List<Arithmetic> arithmetics) { - this.arithmetics = arithmetics.toArray(new Arithmetic[0]); - for (var arith : arithmetics) { - for (var op : arith.opTypes()) { - operators.compute(op, ($, info) -> { - var operator = arith.getOperator(op); - if (info == null) { - info = new OpCandidates(op, operator.arity, new ArrayList<>()); - } - info.addOp(operator); - return info; - }); - } - } - } + public ArithmeticEngine(List<Arithmetic> arithmetics) { + this.arithmetics = arithmetics.toArray(new Arithmetic[0]); + for (var arith : arithmetics) { + for (var op : arith.opTypes()) { + operators.compute( + op, + ($, info) -> { + var operator = arith.getOperator(op); + if (info == null) { + info = new OpCandidates(op, operator.arity, new ArrayList<>()); + } + info.addOp(operator); + return info; + }); + } + } + } - public Iterable<HexPattern> operatorSyms() { - return operators.keySet(); - } + public Iterable<HexPattern> operatorSyms() { + return operators.keySet(); + } - /** - * Runs one of the contained Operators assigned to the given pattern, modifying the passed stack of iotas. - * @param pattern The pattern that was drawn, used to determine which operators are candidates. - * @param env The casting environment. - * @param image The casting image. - * @param continuation The current continuation. - * @return The iotas to be added to the stack. - * @throws Mishap mishaps if invalid input to the operators is given by the caster. - */ - public OperationResult run(HexPattern pattern, CastingEnvironment env, CastingImage image, SpellContinuation continuation) throws Mishap { - var stackList = image.getStack(); - var stack = new Stack<Iota>(); - stack.addAll(stackList); - var startingLength = stackList.size(); + /** + * Runs one of the contained Operators assigned to the given pattern, modifying the passed stack + * of iotas. + * + * @param pattern The pattern that was drawn, used to determine which operators are candidates. + * @param env The casting environment. + * @param image The casting image. + * @param continuation The current continuation. + * @return The iotas to be added to the stack. + * @throws Mishap mishaps if invalid input to the operators is given by the caster. + */ + public OperationResult run( + HexPattern pattern, + CastingEnvironment env, + CastingImage image, + SpellContinuation continuation) + throws Mishap { + var stackList = image.getStack(); + var stack = new Stack<Iota>(); + stack.addAll(stackList); + var startingLength = stackList.size(); - var candidates = operators.get(pattern); - if (candidates == null) - throw new InvalidOperatorException("the pattern " + pattern + " is not an operator."); // - HashCons hash = new HashCons.Pattern(pattern); - var args = new ArrayList<Iota>(candidates.arity()); - for (var i = 0; i < candidates.arity(); i++) { - if (stack.isEmpty()) { - throw new MishapNotEnoughArgs(candidates.arity, startingLength); - } - var iota = stack.pop(); - hash = new HashCons.Pair(iota.getType(), hash); - args.add(iota); - } - Collections.reverse(args); - var op = resolveCandidates(args, hash, candidates); - return op.operate(env, image, continuation); - } + var candidates = operators.get(pattern); + if (candidates == null) + throw new InvalidOperatorException("the pattern " + pattern + " is not an operator."); // + HashCons hash = new HashCons.Pattern(pattern); + var args = new ArrayList<Iota>(candidates.arity()); + for (var i = 0; i < candidates.arity(); i++) { + if (stack.isEmpty()) { + throw new MishapNotEnoughArgs(candidates.arity, startingLength); + } + var iota = stack.pop(); + hash = new HashCons.Pair(iota.getType(), hash); + args.add(iota); + } + Collections.reverse(args); + var op = resolveCandidates(args, hash, candidates); + return op.operate(env, image, continuation); + } - private Operator resolveCandidates(List<Iota> args, HashCons hash, OpCandidates candidates) { - return cache.computeIfAbsent(hash, $ -> { - for (var op : candidates.operators()) { - if (op.accepts.test(args)) { - return op; - } - } - throw new NoOperatorCandidatesException(candidates.pattern(), args, "No implementation candidates for op " + candidates.pattern() + " on args: " + args); - }); - } + private Operator resolveCandidates(List<Iota> args, HashCons hash, OpCandidates candidates) { + return cache.computeIfAbsent( + hash, + $ -> { + for (var op : candidates.operators()) { + if (op.accepts.test(args)) { + return op; + } + } + throw new NoOperatorCandidatesException( + candidates.pattern(), + args, + "No implementation candidates for op " + candidates.pattern() + " on args: " + args); + }); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/HashCons.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/HashCons.java index c7566e783b..4c77496844 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/HashCons.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/HashCons.java @@ -1,6 +1,5 @@ package at.petrak.hexcasting.api.casting.arithmetic.engine; - import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.casting.math.HexPattern; diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/InvalidOperatorException.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/InvalidOperatorException.java index 1d826da67e..49a8de1e15 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/InvalidOperatorException.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/InvalidOperatorException.java @@ -1,18 +1,17 @@ package at.petrak.hexcasting.api.casting.arithmetic.engine; public class InvalidOperatorException extends RuntimeException { - public InvalidOperatorException() { - } + public InvalidOperatorException() {} - public InvalidOperatorException(String s) { - super(s); - } + public InvalidOperatorException(String s) { + super(s); + } - public InvalidOperatorException(String message, Throwable cause) { - super(message, cause); - } + public InvalidOperatorException(String message, Throwable cause) { + super(message, cause); + } - public InvalidOperatorException(Throwable cause) { - super(cause); - } + public InvalidOperatorException(Throwable cause) { + super(cause); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/NoOperatorCandidatesException.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/NoOperatorCandidatesException.java index 5b742fc1f2..6a42efa5db 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/NoOperatorCandidatesException.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/engine/NoOperatorCandidatesException.java @@ -2,39 +2,38 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.math.HexPattern; - import java.util.List; public class NoOperatorCandidatesException extends RuntimeException { - HexPattern pattern; - List<Iota> args; - - public NoOperatorCandidatesException(HexPattern pattern, List<Iota> args) { - this.pattern = pattern; - this.args = args; - } - - public NoOperatorCandidatesException(HexPattern pattern, List<Iota> args, String s) { - super(s); - this.pattern = pattern; - this.args = args; - } - - public HexPattern getPattern() { - return pattern; - } - - public HexPattern setPattern(HexPattern pattern) { - this.pattern = pattern; - return this.pattern; - } - - public List<Iota> getArgs() { - return args; - } - - public List<Iota> setArgs(List<Iota> args) { - this.args = args; - return this.args; - } + HexPattern pattern; + List<Iota> args; + + public NoOperatorCandidatesException(HexPattern pattern, List<Iota> args) { + this.pattern = pattern; + this.args = args; + } + + public NoOperatorCandidatesException(HexPattern pattern, List<Iota> args, String s) { + super(s); + this.pattern = pattern; + this.args = args; + } + + public HexPattern getPattern() { + return pattern; + } + + public HexPattern setPattern(HexPattern pattern) { + this.pattern = pattern; + return this.pattern; + } + + public List<Iota> getArgs() { + return args; + } + + public List<Iota> setArgs(List<Iota> args) { + this.args = args; + return this.args; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/Operator.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/Operator.kt index 8804e0d628..22dc727f18 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/Operator.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/Operator.kt @@ -8,36 +8,33 @@ import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.IotaType import at.petrak.hexcasting.api.casting.mishaps.Mishap -import at.petrak.hexcasting.common.lib.hex.HexEvalSounds -import java.util.function.Consumer abstract class Operator /** - * @param arity The number of arguments from the stack that this Operator requires; all Operators with the same pattern must have arity. - * @param accepts A function that should return true if the passed list of Iotas satisfies this Operator's type constraints, and false otherwise. + * @param arity The number of arguments from the stack that this Operator requires; all Operators + * with the same pattern must have arity. + * @param accepts A function that should return true if the passed list of Iotas satisfies this + * Operator's type constraints, and false otherwise. */ - ( - @JvmField - val arity: Int, - @JvmField - val accepts: IotaMultiPredicate -) { +(@JvmField val arity: Int, @JvmField val accepts: IotaMultiPredicate) { - /** - * Functionally update the image. Return the image and any side effects. - */ - @Throws(Mishap::class) - abstract fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult + /** Functionally update the image. Return the image and any side effects. */ + @Throws(Mishap::class) + abstract fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult - - companion object { - /** - * A helper method to take an iota that you know is of iotaType and returning it as an iota of that type. - */ - @JvmStatic - fun <T : Iota?> downcast(iota: Iota, iotaType: IotaType<T>): T { - check(iota.type === iotaType) { "Attempting to downcast $iota to type: $iotaType" } - return iota as T - } - } -} \ No newline at end of file + companion object { + /** + * A helper method to take an iota that you know is of iotaType and returning it as an iota of + * that type. + */ + @JvmStatic + fun <T : Iota?> downcast(iota: Iota, iotaType: IotaType<T>): T { + check(iota.type === iotaType) { "Attempting to downcast $iota to type: $iotaType" } + return iota as T + } + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorBasic.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorBasic.kt index 1d43c890ce..edccc43d9f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorBasic.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorBasic.kt @@ -12,28 +12,34 @@ import java.util.function.Consumer abstract class OperatorBasic(arity: Int, accepts: IotaMultiPredicate) : Operator(arity, accepts) { - @Throws(Mishap::class) - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() - val args = stack.takeLast(arity) - repeat(arity) { stack.removeLast() } + @Throws(Mishap::class) + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + val stack = image.stack.toMutableList() + val args = stack.takeLast(arity) + repeat(arity) { stack.removeLast() } - val ret = apply(args, env) - ret.forEach(Consumer { e: Iota -> stack.add(e) }) + val ret = apply(args, env) + ret.forEach(Consumer { e: Iota -> stack.add(e) }) - val image2 = image.copy(stack = stack, opsConsumed = image.opsConsumed + 1) - return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) - } + val image2 = image.copy(stack = stack, opsConsumed = image.opsConsumed + 1) + return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) + } - /** - * / ** - * The method called when this Operator is actually acting on the stack, for real. - * @param iotas An iterable of iotas with [Operator.arity] elements that satisfied [Operator.accepts]. - * @param env The casting environment, to make use of if this operator needs it. - * @return the iotas that this operator will return to the stack (with the first element of the returned iterable being placed deepest into the stack, and the last element on top of the stack). - * @throws Mishap if the Operator mishaps for any reason it will be passed up the chain. - */ - @Throws(Mishap::class) - abstract fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> - -} \ No newline at end of file + /** + * / ** The method called when this Operator is actually acting on the stack, for real. + * + * @param iotas An iterable of iotas with [Operator.arity] elements that satisfied + * [Operator.accepts]. + * @param env The casting environment, to make use of if this operator needs it. + * @return the iotas that this operator will return to the stack (with the first element of the + * returned iterable being placed deepest into the stack, and the last element on top of the + * stack). + * @throws Mishap if the Operator mishaps for any reason it will be passed up the chain. + */ + @Throws(Mishap::class) + abstract fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorBinary.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorBinary.java index 02914dc4d1..abb25e75e8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorBinary.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorBinary.java @@ -1,17 +1,13 @@ package at.petrak.hexcasting.api.casting.arithmetic.operator; - import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate; import at.petrak.hexcasting.api.casting.eval.CastingEnvironment; import at.petrak.hexcasting.api.casting.iota.Iota; -import org.jetbrains.annotations.NotNull; - import java.util.List; import java.util.function.BinaryOperator; +import org.jetbrains.annotations.NotNull; -/** - * A helper class for defining {@link Operator}s of two iotas. - */ +/** A helper class for defining {@link Operator}s of two iotas. */ public class OperatorBinary extends OperatorBasic { public BinaryOperator<Iota> inner; @@ -21,7 +17,8 @@ public OperatorBinary(IotaMultiPredicate accepts, BinaryOperator<Iota> inner) { } @Override - public @NotNull Iterable<Iota> apply(Iterable<? extends Iota> iotas, @NotNull CastingEnvironment env) { + public @NotNull Iterable<Iota> apply( + Iterable<? extends Iota> iotas, @NotNull CastingEnvironment env) { var it = iotas.iterator(); return List.of(inner.apply(it.next(), it.next())); } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorUnary.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorUnary.java index 9797b83b1d..fd6eb3bcae 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorUnary.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorUnary.java @@ -1,17 +1,13 @@ package at.petrak.hexcasting.api.casting.arithmetic.operator; - import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate; import at.petrak.hexcasting.api.casting.eval.CastingEnvironment; import at.petrak.hexcasting.api.casting.iota.Iota; -import org.jetbrains.annotations.NotNull; - import java.util.List; import java.util.function.UnaryOperator; +import org.jetbrains.annotations.NotNull; -/** - * A helper class for defining {@link Operator}s of one iota. - */ +/** A helper class for defining {@link Operator}s of one iota. */ public class OperatorUnary extends OperatorBasic { public UnaryOperator<Iota> inner; @@ -21,7 +17,8 @@ public OperatorUnary(IotaMultiPredicate accepts, UnaryOperator<Iota> inner) { } @Override - public @NotNull Iterable<Iota> apply(Iterable<? extends Iota> iotas, @NotNull CastingEnvironment env) { + public @NotNull Iterable<Iota> apply( + Iterable<? extends Iota> iotas, @NotNull CastingEnvironment env) { return List.of(inner.apply(iotas.iterator().next())); } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/predicates/IotaMultiPredicate.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/predicates/IotaMultiPredicate.java index 63a64b5a02..837a355bab 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/predicates/IotaMultiPredicate.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/predicates/IotaMultiPredicate.java @@ -3,40 +3,48 @@ import at.petrak.hexcasting.api.casting.iota.Iota; /** - * Used to determine whether a given set of iotas on the stack are acceptable types for - * the operator that is storing this IotaMultiPredicate. + * Used to determine whether a given set of iotas on the stack are acceptable types for the operator + * that is storing this IotaMultiPredicate. */ @FunctionalInterface public interface IotaMultiPredicate { boolean test(Iterable<Iota> iotas); /** - * The resulting IotaMultiPredicate only returns true if all iotas passed into test match the type dictated by child. + * The resulting IotaMultiPredicate only returns true if all iotas passed into test match the type + * dictated by child. */ static IotaMultiPredicate all(IotaPredicate child) { return new All(child); } + /** - * The resulting IotaMultiPredicate returns true if two iotas are passed, the first matching first, and the second matching second. + * The resulting IotaMultiPredicate returns true if two iotas are passed, the first matching + * first, and the second matching second. */ static IotaMultiPredicate pair(IotaPredicate first, IotaPredicate second) { return new Pair(first, second); } + /** - * The resulting IotaMultiPredicate returns true if three iotas are passed, the first matching first, the second matching second, and the third matching third. + * The resulting IotaMultiPredicate returns true if three iotas are passed, the first matching + * first, the second matching second, and the third matching third. */ static IotaMultiPredicate triple(IotaPredicate first, IotaPredicate second, IotaPredicate third) { return new Triple(first, second, third); } + /** - * The resulting IotaMultiPredicate returns true if at least one iota passed matches needs, and the rest match fallback. + * The resulting IotaMultiPredicate returns true if at least one iota passed matches needs, and + * the rest match fallback. */ static IotaMultiPredicate any(IotaPredicate needs, IotaPredicate fallback) { return new Any(needs, fallback); } /** - * The resulting IotaMultiPredicate returns true if either the first returns true or the second returns true. + * The resulting IotaMultiPredicate returns true if either the first returns true or the second + * returns true. */ static IotaMultiPredicate either(IotaMultiPredicate first, IotaMultiPredicate second) { return new Either(first, second); @@ -46,16 +54,29 @@ record Pair(IotaPredicate first, IotaPredicate second) implements IotaMultiPredi @Override public boolean test(Iterable<Iota> iotas) { var it = iotas.iterator(); - return it.hasNext() && first.test(it.next()) && it.hasNext() && second.test(it.next()) && !it.hasNext(); + return it.hasNext() + && first.test(it.next()) + && it.hasNext() + && second.test(it.next()) + && !it.hasNext(); } } - record Triple(IotaPredicate first, IotaPredicate second, IotaPredicate third) implements IotaMultiPredicate { + + record Triple(IotaPredicate first, IotaPredicate second, IotaPredicate third) + implements IotaMultiPredicate { @Override public boolean test(Iterable<Iota> iotas) { var it = iotas.iterator(); - return it.hasNext() && first.test(it.next()) && it.hasNext() && second.test(it.next()) && it.hasNext() && third.test(it.next()) && !it.hasNext(); + return it.hasNext() + && first.test(it.next()) + && it.hasNext() + && second.test(it.next()) + && it.hasNext() + && third.test(it.next()) + && !it.hasNext(); } } + record Any(IotaPredicate needs, IotaPredicate fallback) implements IotaMultiPredicate { @Override public boolean test(Iterable<Iota> iotas) { @@ -70,6 +91,7 @@ public boolean test(Iterable<Iota> iotas) { return ok; } } + record All(IotaPredicate inner) implements IotaMultiPredicate { @Override public boolean test(Iterable<Iota> iotas) { diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/predicates/IotaPredicate.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/predicates/IotaPredicate.java index 41d0648145..60b3208f84 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/predicates/IotaPredicate.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/predicates/IotaPredicate.java @@ -2,19 +2,20 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; - import java.util.List; /** - * Used to determine whether a given iota is an acceptable type for the operator that is storing this. It must be strictly a function - * of the passed Iota's IotaType, or the caching done by ArithmeticEngine will be invalid. + * Used to determine whether a given iota is an acceptable type for the operator that is storing + * this. It must be strictly a function of the passed Iota's IotaType, or the caching done by + * ArithmeticEngine will be invalid. */ @FunctionalInterface public interface IotaPredicate { boolean test(Iota iota); /** - * The resulting IotaPredicate returns true if the given iota matches either the left or right predicates. + * The resulting IotaPredicate returns true if the given iota matches either the left or right + * predicates. */ static IotaPredicate or(IotaPredicate left, IotaPredicate right) { return new Or(left, right); @@ -28,9 +29,7 @@ static IotaPredicate any(List<IotaPredicate> any) { return new Any(any.toArray(IotaPredicate[]::new)); } - /** - * The resulting IotaPredicate returns true if the given iota's type is type. - */ + /** The resulting IotaPredicate returns true if the given iota's type is type. */ static IotaPredicate ofType(IotaType<?> type) { return new OfType(type); } @@ -47,8 +46,7 @@ record Any(IotaPredicate[] any) implements IotaPredicate { @Override public boolean test(Iota iota) { for (var i : any) { - if (i.test(iota)) - return true; + if (i.test(iota)) return true; } return false; } @@ -61,8 +59,6 @@ public boolean test(Iota iota) { } } - /** - * This IotaPredicate returns true for all iotas. - */ + /** This IotaPredicate returns true for all iotas. */ IotaPredicate TRUE = iota -> true; } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/Action.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/Action.kt index e60ff2dfe3..f2b818491f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/Action.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/Action.kt @@ -5,60 +5,61 @@ import at.petrak.hexcasting.api.casting.eval.OperationResult import at.petrak.hexcasting.api.casting.eval.vm.CastingImage import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation import at.petrak.hexcasting.api.casting.iota.Iota -import net.minecraft.world.phys.Vec3 import java.text.DecimalFormat +import net.minecraft.world.phys.Vec3 /** - * Manipulates the stack in some way, usually by popping some number of values off the stack - * and pushing one new value. - * For a more "traditional" pop arguments, push return experience, see [ConstMediaAction]. + * Manipulates the stack in some way, usually by popping some number of values off the stack and + * pushing one new value. For a more "traditional" pop arguments, push return experience, see + * [ConstMediaAction]. * - * Instances of this can exist on the client, but they should NEVER be used there. They only - * exist on the client because Minecraft's registry system demands they do; any information - * the client needs about them is stored elsewhere. (For example, their canonical stroke order - * is stored in [ActionRegistryEntry], and their localization key is gotten from the resource key - * via [at.petrak.hexcasting.api.HexAPI.getActionI18nKey].) + * Instances of this can exist on the client, but they should NEVER be used there. They only exist + * on the client because Minecraft's registry system demands they do; any information the client + * needs about them is stored elsewhere. (For example, their canonical stroke order is stored in + * [ActionRegistryEntry], and their localization key is gotten from the resource key via + * [at.petrak.hexcasting.api.HexAPI.getActionI18nKey].) * * Each action is a singleton */ interface Action { - /** - * Functionally update the image. Return the image and any side effects. - * - * This is a <i>very</i> low-level function -- the implementor is responsible for a lot. For example, - * remember to increment the op count, sil vous plait. - * - * A particle effect at the cast site and various messages and advancements are done automagically. - * - * The userdata tag is copied for you, so you don't need to worry about mutation messing up things - * behind the scenes. - */ - fun operate( - env: CastingEnvironment, - image: CastingImage, - continuation: SpellContinuation - ): OperationResult + /** + * Functionally update the image. Return the image and any side effects. + * + * This is a <i>very</i> low-level function -- the implementor is responsible for a lot. For + * example, remember to increment the op count, sil vous plait. + * + * A particle effect at the cast site and various messages and advancements are done + * automagically. + * + * The userdata tag is copied for you, so you don't need to worry about mutation messing up things + * behind the scenes. + */ + fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult - companion object { - // I see why vazkii did this: you can't raycast out to infinity! - const val RAYCAST_DISTANCE: Double = 32.0 + companion object { + // I see why vazkii did this: you can't raycast out to infinity! + const val RAYCAST_DISTANCE: Double = 32.0 - // TODO: currently, this means you can't raycast in a very long spell circle, or out of your local ambit into - // your sentinel's. - @JvmStatic - fun raycastEnd(origin: Vec3, look: Vec3): Vec3 = - origin.add(look.normalize().scale(RAYCAST_DISTANCE)) + // TODO: currently, this means you can't raycast in a very long spell circle, or out of your + // local ambit into + // your sentinel's. + @JvmStatic + fun raycastEnd(origin: Vec3, look: Vec3): Vec3 = + origin.add(look.normalize().scale(RAYCAST_DISTANCE)) - @JvmStatic - fun makeConstantOp(x: Iota): Action = object : ConstMediaAction { - override val argc: Int - get() = 0 + @JvmStatic + fun makeConstantOp(x: Iota): Action = + object : ConstMediaAction { + override val argc: Int + get() = 0 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> = - listOf(x) - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> = listOf(x) + } - public val DOUBLE_FORMATTER = DecimalFormat("####.####") - } + public val DOUBLE_FORMATTER = DecimalFormat("####.####") + } } - diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/ConstMediaAction.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/ConstMediaAction.kt index 276ee73122..d7cb713ab1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/ConstMediaAction.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/ConstMediaAction.kt @@ -10,38 +10,39 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughMedia import at.petrak.hexcasting.common.lib.hex.HexEvalSounds -/** - * A SimpleOperator that always costs the same amount of media. - */ +/** A SimpleOperator that always costs the same amount of media. */ interface ConstMediaAction : Action { - val argc: Int - val mediaCost: Long - get() = 0 - - fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> - - fun executeWithOpCount(args: List<Iota>, env: CastingEnvironment): CostMediaActionResult { - val stack = this.execute(args, env) - return CostMediaActionResult(stack) - } - - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() - - if (env.extractMedia(this.mediaCost, true) > 0) - throw MishapNotEnoughMedia(this.mediaCost) - if (this.argc > stack.size) - throw MishapNotEnoughArgs(this.argc, stack.size) - val args = stack.takeLast(this.argc) - repeat(this.argc) { stack.removeLast() } - val result = this.executeWithOpCount(args, env) - stack.addAll(result.resultStack) - - val sideEffects = mutableListOf<OperatorSideEffect>(OperatorSideEffect.ConsumeMedia(this.mediaCost)) - - val image2 = image.copy(stack = stack, opsConsumed = image.opsConsumed + result.opCount) - return OperationResult(image2, sideEffects, continuation, HexEvalSounds.NORMAL_EXECUTE) - } - - data class CostMediaActionResult(val resultStack: List<Iota>, val opCount: Long = 1) + val argc: Int + val mediaCost: Long + get() = 0 + + fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> + + fun executeWithOpCount(args: List<Iota>, env: CastingEnvironment): CostMediaActionResult { + val stack = this.execute(args, env) + return CostMediaActionResult(stack) + } + + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + val stack = image.stack.toMutableList() + + if (env.extractMedia(this.mediaCost, true) > 0) throw MishapNotEnoughMedia(this.mediaCost) + if (this.argc > stack.size) throw MishapNotEnoughArgs(this.argc, stack.size) + val args = stack.takeLast(this.argc) + repeat(this.argc) { stack.removeLast() } + val result = this.executeWithOpCount(args, env) + stack.addAll(result.resultStack) + + val sideEffects = + mutableListOf<OperatorSideEffect>(OperatorSideEffect.ConsumeMedia(this.mediaCost)) + + val image2 = image.copy(stack = stack, opsConsumed = image.opsConsumed + result.opCount) + return OperationResult(image2, sideEffects, continuation, HexEvalSounds.NORMAL_EXECUTE) + } + + data class CostMediaActionResult(val resultStack: List<Iota>, val opCount: Long = 1) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/OperationAction.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/OperationAction.kt index 1e9a39f80f..b81947d0bf 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/OperationAction.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/OperationAction.kt @@ -10,15 +10,20 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapInvalidOperatorArgs import at.petrak.hexcasting.common.lib.hex.HexArithmetics /** - * Represents an Operator with the give pattern as its identifier, a special type of Action that calls a different function depending on the type of its arguments. - * This exists so that addons can easily define their own overloads to patterns like addition, subtraction, etc. + * Represents an Operator with the give pattern as its identifier, a special type of Action that + * calls a different function depending on the type of its arguments. This exists so that addons can + * easily define their own overloads to patterns like addition, subtraction, etc. */ data class OperationAction(val pattern: HexPattern) : Action { - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - return try { - HexArithmetics.getEngine().run(pattern, env, image, continuation) - } catch (e: NoOperatorCandidatesException) { - throw MishapInvalidOperatorArgs(e.args) - } - } -} \ No newline at end of file + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + return try { + HexArithmetics.getEngine().run(pattern, env, image, continuation) + } catch (e: NoOperatorCandidatesException) { + throw MishapInvalidOperatorArgs(e.args) + } + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/SpecialHandler.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/SpecialHandler.java index 14a64879e9..b2299439c3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/SpecialHandler.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/SpecialHandler.java @@ -7,35 +7,33 @@ /** * Special handling of a pattern. Before checking any of the normal angle-signature based patterns, - * a given pattern is run by all of these special handlers patterns. If none of them return non-null, - * then its signature is checked. - * <p> - * In the base mod, this is used for number patterns and Bookkeeper's Gambit. - * <p> - * There's a separation between the special handlers and their factories so we never have to use - * {@link Action} instances on the client. We can have SpecialHandlers on the client though because they're just - * wrappers. + * a given pattern is run by all of these special handlers patterns. If none of them return + * non-null, then its signature is checked. + * + * <p>In the base mod, this is used for number patterns and Bookkeeper's Gambit. + * + * <p>There's a separation between the special handlers and their factories so we never have to use + * {@link Action} instances on the client. We can have SpecialHandlers on the client though because + * they're just wrappers. */ public interface SpecialHandler { - /** - * Convert this to an action, for modification of the stack and state. - * <p> - * This is called on the SERVER-SIDE ONLY. - */ - Action act(); + /** + * Convert this to an action, for modification of the stack and state. + * + * <p>This is called on the SERVER-SIDE ONLY. + */ + Action act(); - /** - * Get the name of this handler. - */ - Component getName(); + /** Get the name of this handler. */ + Component getName(); - /** - * Given a pattern, possibly make up the special handler from it. - * <p> - * This is what goes in the registry! Think of it like BlockEntityType vs BlockEntity. - */ - @FunctionalInterface - public interface Factory<T extends SpecialHandler> { - @Nullable T tryMatch(HexPattern pattern, CastingEnvironment env); - } + /** + * Given a pattern, possibly make up the special handler from it. + * + * <p>This is what goes in the registry! Think of it like BlockEntityType vs BlockEntity. + */ + @FunctionalInterface + public interface Factory<T extends SpecialHandler> { + @Nullable T tryMatch(HexPattern pattern, CastingEnvironment env); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/SpellAction.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/SpellAction.kt index fcf17d08d0..17febc5051 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/SpellAction.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/SpellAction.kt @@ -14,58 +14,67 @@ import at.petrak.hexcasting.common.lib.hex.HexEvalSounds import net.minecraft.nbt.CompoundTag interface SpellAction : Action { - val argc: Int - - fun hasCastingSound(ctx: CastingEnvironment): Boolean = true - - fun awardsCastingStat(ctx: CastingEnvironment): Boolean = true - - fun execute( - args: List<Iota>, - env: CastingEnvironment - ): Result - - fun executeWithUserdata( - args: List<Iota>, env: CastingEnvironment, userData: CompoundTag - ): Result { - return this.execute(args, env) - } - - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() - - if (this.argc > stack.size) - throw MishapNotEnoughArgs(this.argc, stack.size) - val args = stack.takeLast(this.argc) - for (_i in 0 until this.argc) stack.removeLast() - - // execute! - val userDataMut = image.userData.copy() - val result = this.executeWithUserdata(args, env, userDataMut) - - val sideEffects = mutableListOf<OperatorSideEffect>() - - if (env.extractMedia(result.cost, true) > 0) - throw MishapNotEnoughMedia(result.cost) - if (result.cost > 0) - sideEffects.add(OperatorSideEffect.ConsumeMedia(result.cost)) - - sideEffects.add( - OperatorSideEffect.AttemptSpell( - result.effect, - this.hasCastingSound(env), - this.awardsCastingStat(env) - ) - ) - - for (spray in result.particles) - sideEffects.add(OperatorSideEffect.Particles(spray)) - - val image2 = image.copy(stack = stack, opsConsumed = image.opsConsumed + result.opCount, userData = userDataMut) - - val sound = if (this.hasCastingSound(env)) HexEvalSounds.SPELL else HexEvalSounds.MUTE - return OperationResult(image2, sideEffects, continuation, sound) - } - - data class Result(val effect: RenderedSpell, val cost: Long, val particles: List<ParticleSpray>, val opCount: Long = 1) + val argc: Int + + fun hasCastingSound(ctx: CastingEnvironment): Boolean = true + + fun awardsCastingStat(ctx: CastingEnvironment): Boolean = true + + fun execute(args: List<Iota>, env: CastingEnvironment): Result + + fun executeWithUserdata( + args: List<Iota>, + env: CastingEnvironment, + userData: CompoundTag + ): Result { + return this.execute(args, env) + } + + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + val stack = image.stack.toMutableList() + + if (this.argc > stack.size) throw MishapNotEnoughArgs(this.argc, stack.size) + val args = stack.takeLast(this.argc) + for (_i in 0 until this.argc) stack.removeLast() + + // execute! + val userDataMut = image.userData.copy() + val result = this.executeWithUserdata(args, env, userDataMut) + + val sideEffects = mutableListOf<OperatorSideEffect>() + + if (env.extractMedia(result.cost, true) > 0) throw MishapNotEnoughMedia(result.cost) + if (result.cost > 0) sideEffects.add(OperatorSideEffect.ConsumeMedia(result.cost)) + + sideEffects.add( + OperatorSideEffect.AttemptSpell( + result.effect, + this.hasCastingSound(env), + this.awardsCastingStat(env) + ) + ) + + for (spray in result.particles) sideEffects.add(OperatorSideEffect.Particles(spray)) + + val image2 = + image.copy( + stack = stack, + opsConsumed = image.opsConsumed + result.opCount, + userData = userDataMut + ) + + val sound = if (this.hasCastingSound(env)) HexEvalSounds.SPELL else HexEvalSounds.MUTE + return OperationResult(image2, sideEffects, continuation, sound) + } + + data class Result( + val effect: RenderedSpell, + val cost: Long, + val particles: List<ParticleSpray>, + val opCount: Long = 1 + ) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/BlockEntityAbstractImpetus.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/BlockEntityAbstractImpetus.java index ac8bf92d0d..73c793f41d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/BlockEntityAbstractImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/BlockEntityAbstractImpetus.java @@ -8,6 +8,8 @@ import at.petrak.hexcasting.common.items.magic.ItemCreativeUnlocker; import at.petrak.hexcasting.common.lib.HexItems; import com.mojang.datafixers.util.Pair; +import java.text.DecimalFormat; +import java.util.List; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -31,428 +33,427 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Nullable; -import java.text.DecimalFormat; -import java.util.List; - /** * Default impl for an impetus, not tecnically necessary but I'm exposing it for ease of use - * <p> - * This does assume a great deal so you might have to re-implement a lot of this yourself if you + * + * <p>This does assume a great deal so you might have to re-implement a lot of this yourself if you * wanna do something wild and new */ -public abstract class BlockEntityAbstractImpetus extends HexBlockEntity implements WorldlyContainer { - private static final DecimalFormat DUST_AMOUNT = new DecimalFormat("###,###.##"); - private static final long MAX_CAPACITY = 9_000_000_000_000_000_000L; - - public static final String - TAG_EXECUTION_STATE = "executor", - TAG_MEDIA = "media", - TAG_ERROR_MSG = "errorMsg", - TAG_ERROR_DISPLAY = "errorDisplay", - TAG_PIGMENT = "pigment"; - - // We might try to load the executor in loadModData when the level doesn't exist yet, - // so save the tag and load it lazy - @Nullable CompoundTag lazyExecutionState; - @Nullable - protected CircleExecutionState executionState; - - protected long media = 0; - - // these are null together - @Nullable - protected Component displayMsg = null; - @Nullable - protected ItemStack displayItem = null; - @Nullable - protected FrozenPigment pigment = null; - - - public BlockEntityAbstractImpetus(BlockEntityType<?> pType, BlockPos pWorldPosition, BlockState pBlockState) { - super(pType, pWorldPosition, pBlockState); - } - - public Direction getStartDirection() { - return this.getBlockState().getValue(BlockStateProperties.FACING); - } - - @Nullable - public Component getDisplayMsg() { - return displayMsg; - } - - public void clearDisplay() { - this.displayMsg = null; - this.displayItem = null; - this.sync(); - } - - public void postDisplay(Component error, ItemStack display) { - this.displayMsg = error; - this.displayItem = display; - this.sync(); - } - - public void postMishap(Component mishapDisplay) { - this.postDisplay(mishapDisplay, new ItemStack(Items.MUSIC_DISC_11)); - } - - public void postPrint(Component printDisplay) { - this.postDisplay(printDisplay, new ItemStack(Items.BOOK)); - } - - // Pull this out because we may need to call it both on startup and halfway thru - public void postNoExits(BlockPos pos) { - this.postDisplay( - Component.translatable("hexcasting.tooltip.circle.no_exit", - Component.literal(pos.toShortString()).withStyle(ChatFormatting.RED)), - new ItemStack(Items.OAK_SIGN)); - } - - //region execution - - public void tickExecution() { - if (this.level == null) - return; - - this.setChanged(); - - var state = this.getExecutionState(); - if (state == null) { - return; - } - - var shouldContinue = state.tick(this); - - if (!shouldContinue) { - this.endExecution(); - this.executionState = null; - } else - this.level.scheduleTick(this.getBlockPos(), this.getBlockState().getBlock(), state.getTickSpeed()); - } - - public void endExecution() { - if (this.executionState == null) - return; - - this.executionState.endExecution(this); - } - - /** - * ONLY CALL THIS WHEN YOU KNOW THE WORLD EXISTS AND ON THE SERVER, lazy-loads it - */ - public @Nullable CircleExecutionState getExecutionState() { - if (this.level == null) { - throw new IllegalStateException("didn't you read the doc comment, don't call this if the level is null"); - } - - if (this.executionState != null) - return this.executionState; - - if (this.lazyExecutionState != null) - this.executionState = CircleExecutionState.load(this.lazyExecutionState, (ServerLevel) this.level); - - return this.executionState; - } - - public void startExecution(@Nullable ServerPlayer player) { - if (this.level == null) - return; // TODO: error here? - if (this.level.isClientSide) - return; // TODO: error here? - - if (this.executionState != null) { - return; - } - var result = CircleExecutionState.createNew(this, player); - if (result.isErr()) { - var errPos = result.unwrapErr(); - if (errPos == null) { - ICircleComponent.sfx(this.getBlockPos(), this.getBlockState(), this.level, null, false); - this.postNoExits(this.getBlockPos()); - } else { - ICircleComponent.sfx(errPos, this.level.getBlockState(errPos), this.level, null, false); - this.postDisplay(Component.translatable("hexcasting.tooltip.circle.no_closure", - Component.literal(errPos.toShortString()).withStyle(ChatFormatting.RED)), - new ItemStack(Items.LEAD)); - } - - return; - } - this.executionState = result.unwrap(); - - this.clearDisplay(); - var serverLevel = (ServerLevel) this.level; - serverLevel.scheduleTick(this.getBlockPos(), this.getBlockState().getBlock(), - this.executionState.getTickSpeed()); - serverLevel.setBlockAndUpdate(this.getBlockPos(), - this.getBlockState().setValue(BlockCircleComponent.ENERGIZED, true)); - } - - @Contract(pure = true) - protected static AABB getBounds(List<BlockPos> poses) { - int minX = Integer.MAX_VALUE; - int minY = Integer.MAX_VALUE; - int minZ = Integer.MAX_VALUE; - int maxX = Integer.MIN_VALUE; - int maxY = Integer.MIN_VALUE; - int maxZ = Integer.MIN_VALUE; - - for (var pos : poses) { - if (pos.getX() < minX) { - minX = pos.getX(); - } - if (pos.getY() < minY) { - minY = pos.getY(); - } - if (pos.getZ() < minZ) { - minZ = pos.getZ(); - } - if (pos.getX() > maxX) { - maxX = pos.getX(); - } - if (pos.getY() > maxY) { - maxY = pos.getY(); - } - if (pos.getZ() > maxZ) { - maxZ = pos.getZ(); - } - } - - return new AABB(minX, minY, minZ, maxX + 1, maxY + 1, maxZ + 1); - } - - //endregion - - //region media handling - - public long getMedia() { - return this.media; - } - - public void setMedia(long media) { - this.media = media; - sync(); - } - - public long extractMediaFromInsertedItem(ItemStack stack, boolean simulate) { - if (this.media < 0) { - return 0; - } - return MediaHelper.extractMedia(stack, remainingMediaCapacity(), true, simulate); - } - - public void insertMedia(ItemStack stack) { - if (getMedia() >= 0 && !stack.isEmpty() && stack.getItem() == HexItems.CREATIVE_UNLOCKER) { - setInfiniteMedia(); - stack.shrink(1); - } else { - var mediamount = extractMediaFromInsertedItem(stack, false); - if (mediamount > 0) { - this.media = Math.min(mediamount + media, MAX_CAPACITY); - this.sync(); - } - } - } - - public void setInfiniteMedia() { - this.media = -1; - this.sync(); - } - - public long remainingMediaCapacity() { - if (this.media < 0) { - return 0; - } - return Math.max(0, MAX_CAPACITY - this.media); - } - - //endregion - - - public FrozenPigment getPigment() { - if (pigment != null) - return pigment; - if (executionState != null && executionState.casterPigment != null) - return executionState.casterPigment; - return FrozenPigment.DEFAULT.get(); - } - - public @Nullable FrozenPigment setPigment(@Nullable FrozenPigment pigment) { - this.pigment = pigment; - return this.pigment; - } - - @Override - protected void saveModData(CompoundTag tag) { - if (this.executionState != null) { - tag.put(TAG_EXECUTION_STATE, this.executionState.save()); - } - - tag.putLong(TAG_MEDIA, this.media); - - if (this.displayMsg != null && this.displayItem != null) { - tag.putString(TAG_ERROR_MSG, Component.Serializer.toJson(this.displayMsg)); - var itemTag = new CompoundTag(); - this.displayItem.save(itemTag); - tag.put(TAG_ERROR_DISPLAY, itemTag); - } - if (this.pigment != null) - tag.put(TAG_PIGMENT, this.pigment.serializeToNBT()); - } - - @Override - protected void loadModData(CompoundTag tag) { - this.executionState = null; - if (tag.contains(TAG_EXECUTION_STATE, Tag.TAG_COMPOUND)) { - this.lazyExecutionState = tag.getCompound(TAG_EXECUTION_STATE); - } else { - this.lazyExecutionState = null; - } - - if (tag.contains(TAG_MEDIA, Tag.TAG_LONG)) { - this.media = tag.getLong(TAG_MEDIA); - } - - if (tag.contains(TAG_ERROR_MSG, Tag.TAG_STRING) && tag.contains(TAG_ERROR_DISPLAY, Tag.TAG_COMPOUND)) { - var msg = Component.Serializer.fromJson(tag.getString(TAG_ERROR_MSG)); - var display = ItemStack.of(tag.getCompound(TAG_ERROR_DISPLAY)); - this.displayMsg = msg; - this.displayItem = display; - } else { - this.displayMsg = null; - this.displayItem = null; - } - if (tag.contains(TAG_PIGMENT, Tag.TAG_COMPOUND)) - this.pigment = FrozenPigment.fromNBT(tag.getCompound(TAG_PIGMENT)); - } - - public void applyScryingLensOverlay(List<Pair<ItemStack, Component>> lines, - BlockState state, BlockPos pos, Player observer, Level world, Direction hitFace) { - if (world.getBlockEntity(pos) instanceof BlockEntityAbstractImpetus beai) { - if (beai.getMedia() < 0) { - lines.add(new Pair<>(new ItemStack(HexItems.AMETHYST_DUST), ItemCreativeUnlocker.infiniteMedia(world))); - } else { - var dustCount = (float) beai.getMedia() / (float) MediaConstants.DUST_UNIT; - var dustCmp = Component.translatable("hexcasting.tooltip.media", - DUST_AMOUNT.format(dustCount)); - lines.add(new Pair<>(new ItemStack(HexItems.AMETHYST_DUST), dustCmp)); - } - - if (this.displayMsg != null && this.displayItem != null) { - lines.add(new Pair<>(this.displayItem, this.displayMsg)); - } - } - } - - //region music - - protected int semitoneFromScale(int note) { - var blockBelow = this.level.getBlockState(this.getBlockPos().below()); - var scale = MAJOR_SCALE; - if (blockBelow.is(Blocks.CRYING_OBSIDIAN)) { - scale = MINOR_SCALE; - } else if (blockBelow.is(BlockTags.DOORS) || blockBelow.is(BlockTags.TRAPDOORS)) { - scale = DORIAN_SCALE; - } else if (blockBelow.is(Blocks.PISTON) || blockBelow.is(Blocks.STICKY_PISTON)) { - scale = MIXOLYDIAN_SCALE; - } else if (blockBelow.is(Blocks.BLUE_WOOL) - || blockBelow.is(Blocks.BLUE_CONCRETE) || blockBelow.is(Blocks.BLUE_CONCRETE_POWDER) - || blockBelow.is(Blocks.BLUE_TERRACOTTA) || blockBelow.is(Blocks.BLUE_GLAZED_TERRACOTTA) - || blockBelow.is(Blocks.BLUE_STAINED_GLASS) || blockBelow.is(Blocks.BLUE_STAINED_GLASS_PANE)) { - scale = BLUES_SCALE; - } else if (blockBelow.is(Blocks.BONE_BLOCK)) { - scale = BAD_TIME; - } else if (blockBelow.is(Blocks.COMPOSTER)) { - scale = SUSSY_BAKA; - } - - note = Mth.clamp(note, 0, scale.length - 1); - return scale[note]; - } - - // this is a good use of my time - private static final int[] MAJOR_SCALE = {0, 2, 4, 5, 7, 9, 11, 12}; - private static final int[] MINOR_SCALE = {0, 2, 3, 5, 7, 8, 11, 12}; - private static final int[] DORIAN_SCALE = {0, 2, 3, 5, 7, 9, 10, 12}; - private static final int[] MIXOLYDIAN_SCALE = {0, 2, 4, 5, 7, 9, 10, 12}; - private static final int[] BLUES_SCALE = {0, 3, 5, 6, 7, 10, 12}; - private static final int[] BAD_TIME = {0, 0, 12, 7, 6, 5, 3, 0, 3, 5}; - private static final int[] SUSSY_BAKA = {5, 8, 10, 11, 10, 8, 5, 3, 7, 5}; - - //endregion - - //region item handler contract stuff - private static final int[] SLOTS = {0}; - - @Override - public int[] getSlotsForFace(Direction var1) { - return SLOTS; - } - - @Override - public boolean canPlaceItemThroughFace(int index, ItemStack stack, @Nullable Direction dir) { - return this.canPlaceItem(index, stack); - } - - @Override - public boolean canTakeItemThroughFace(int var1, ItemStack var2, Direction var3) { - return false; - } - - @Override - public int getContainerSize() { - return 1; - } - - @Override - public boolean isEmpty() { - return true; - } - - @Override - public ItemStack getItem(int index) { - return ItemStack.EMPTY.copy(); - } - - @Override - public ItemStack removeItem(int index, int count) { - return ItemStack.EMPTY.copy(); - } - - @Override - public ItemStack removeItemNoUpdate(int index) { - return ItemStack.EMPTY.copy(); - } - - @Override - public void setItem(int index, ItemStack stack) { - insertMedia(stack); - } - - @Override - public boolean stillValid(Player player) { - return false; - } - - @Override - public void clearContent() { - // NO-OP - } - - @Override - public boolean canPlaceItem(int index, ItemStack stack) { - if (remainingMediaCapacity() == 0) { - return false; - } - - if (stack.is(HexItems.CREATIVE_UNLOCKER)) { - return true; - } - - var mediamount = extractMediaFromInsertedItem(stack, true); - return mediamount > 0; - } - - //endregion +public abstract class BlockEntityAbstractImpetus extends HexBlockEntity + implements WorldlyContainer { + private static final DecimalFormat DUST_AMOUNT = new DecimalFormat("###,###.##"); + private static final long MAX_CAPACITY = 9_000_000_000_000_000_000L; + + public static final String TAG_EXECUTION_STATE = "executor", + TAG_MEDIA = "media", + TAG_ERROR_MSG = "errorMsg", + TAG_ERROR_DISPLAY = "errorDisplay", + TAG_PIGMENT = "pigment"; + + // We might try to load the executor in loadModData when the level doesn't exist yet, + // so save the tag and load it lazy + @Nullable CompoundTag lazyExecutionState; + @Nullable protected CircleExecutionState executionState; + + protected long media = 0; + + // these are null together + @Nullable protected Component displayMsg = null; + @Nullable protected ItemStack displayItem = null; + @Nullable protected FrozenPigment pigment = null; + + public BlockEntityAbstractImpetus( + BlockEntityType<?> pType, BlockPos pWorldPosition, BlockState pBlockState) { + super(pType, pWorldPosition, pBlockState); + } + + public Direction getStartDirection() { + return this.getBlockState().getValue(BlockStateProperties.FACING); + } + + @Nullable public Component getDisplayMsg() { + return displayMsg; + } + + public void clearDisplay() { + this.displayMsg = null; + this.displayItem = null; + this.sync(); + } + + public void postDisplay(Component error, ItemStack display) { + this.displayMsg = error; + this.displayItem = display; + this.sync(); + } + + public void postMishap(Component mishapDisplay) { + this.postDisplay(mishapDisplay, new ItemStack(Items.MUSIC_DISC_11)); + } + + public void postPrint(Component printDisplay) { + this.postDisplay(printDisplay, new ItemStack(Items.BOOK)); + } + + // Pull this out because we may need to call it both on startup and halfway thru + public void postNoExits(BlockPos pos) { + this.postDisplay( + Component.translatable( + "hexcasting.tooltip.circle.no_exit", + Component.literal(pos.toShortString()).withStyle(ChatFormatting.RED)), + new ItemStack(Items.OAK_SIGN)); + } + + // region execution + + public void tickExecution() { + if (this.level == null) return; + + this.setChanged(); + + var state = this.getExecutionState(); + if (state == null) { + return; + } + + var shouldContinue = state.tick(this); + + if (!shouldContinue) { + this.endExecution(); + this.executionState = null; + } else + this.level.scheduleTick( + this.getBlockPos(), this.getBlockState().getBlock(), state.getTickSpeed()); + } + + public void endExecution() { + if (this.executionState == null) return; + + this.executionState.endExecution(this); + } + + /** ONLY CALL THIS WHEN YOU KNOW THE WORLD EXISTS AND ON THE SERVER, lazy-loads it */ + public @Nullable CircleExecutionState getExecutionState() { + if (this.level == null) { + throw new IllegalStateException( + "didn't you read the doc comment, don't call this if the level is null"); + } + + if (this.executionState != null) return this.executionState; + + if (this.lazyExecutionState != null) + this.executionState = + CircleExecutionState.load(this.lazyExecutionState, (ServerLevel) this.level); + + return this.executionState; + } + + public void startExecution(@Nullable ServerPlayer player) { + if (this.level == null) return; // TODO: error here? + if (this.level.isClientSide) return; // TODO: error here? + + if (this.executionState != null) { + return; + } + var result = CircleExecutionState.createNew(this, player); + if (result.isErr()) { + var errPos = result.unwrapErr(); + if (errPos == null) { + ICircleComponent.sfx(this.getBlockPos(), this.getBlockState(), this.level, null, false); + this.postNoExits(this.getBlockPos()); + } else { + ICircleComponent.sfx(errPos, this.level.getBlockState(errPos), this.level, null, false); + this.postDisplay( + Component.translatable( + "hexcasting.tooltip.circle.no_closure", + Component.literal(errPos.toShortString()).withStyle(ChatFormatting.RED)), + new ItemStack(Items.LEAD)); + } + + return; + } + this.executionState = result.unwrap(); + + this.clearDisplay(); + var serverLevel = (ServerLevel) this.level; + serverLevel.scheduleTick( + this.getBlockPos(), this.getBlockState().getBlock(), this.executionState.getTickSpeed()); + serverLevel.setBlockAndUpdate( + this.getBlockPos(), this.getBlockState().setValue(BlockCircleComponent.ENERGIZED, true)); + } + + @Contract(pure = true) + protected static AABB getBounds(List<BlockPos> poses) { + int minX = Integer.MAX_VALUE; + int minY = Integer.MAX_VALUE; + int minZ = Integer.MAX_VALUE; + int maxX = Integer.MIN_VALUE; + int maxY = Integer.MIN_VALUE; + int maxZ = Integer.MIN_VALUE; + + for (var pos : poses) { + if (pos.getX() < minX) { + minX = pos.getX(); + } + if (pos.getY() < minY) { + minY = pos.getY(); + } + if (pos.getZ() < minZ) { + minZ = pos.getZ(); + } + if (pos.getX() > maxX) { + maxX = pos.getX(); + } + if (pos.getY() > maxY) { + maxY = pos.getY(); + } + if (pos.getZ() > maxZ) { + maxZ = pos.getZ(); + } + } + + return new AABB(minX, minY, minZ, maxX + 1, maxY + 1, maxZ + 1); + } + + // endregion + + // region media handling + + public long getMedia() { + return this.media; + } + + public void setMedia(long media) { + this.media = media; + sync(); + } + + public long extractMediaFromInsertedItem(ItemStack stack, boolean simulate) { + if (this.media < 0) { + return 0; + } + return MediaHelper.extractMedia(stack, remainingMediaCapacity(), true, simulate); + } + + public void insertMedia(ItemStack stack) { + if (getMedia() >= 0 && !stack.isEmpty() && stack.getItem() == HexItems.CREATIVE_UNLOCKER) { + setInfiniteMedia(); + stack.shrink(1); + } else { + var mediamount = extractMediaFromInsertedItem(stack, false); + if (mediamount > 0) { + this.media = Math.min(mediamount + media, MAX_CAPACITY); + this.sync(); + } + } + } + + public void setInfiniteMedia() { + this.media = -1; + this.sync(); + } + + public long remainingMediaCapacity() { + if (this.media < 0) { + return 0; + } + return Math.max(0, MAX_CAPACITY - this.media); + } + + // endregion + + public FrozenPigment getPigment() { + if (pigment != null) return pigment; + if (executionState != null && executionState.casterPigment != null) + return executionState.casterPigment; + return FrozenPigment.DEFAULT.get(); + } + + public @Nullable FrozenPigment setPigment(@Nullable FrozenPigment pigment) { + this.pigment = pigment; + return this.pigment; + } + + @Override + protected void saveModData(CompoundTag tag) { + if (this.executionState != null) { + tag.put(TAG_EXECUTION_STATE, this.executionState.save()); + } + + tag.putLong(TAG_MEDIA, this.media); + + if (this.displayMsg != null && this.displayItem != null) { + tag.putString(TAG_ERROR_MSG, Component.Serializer.toJson(this.displayMsg)); + var itemTag = new CompoundTag(); + this.displayItem.save(itemTag); + tag.put(TAG_ERROR_DISPLAY, itemTag); + } + if (this.pigment != null) tag.put(TAG_PIGMENT, this.pigment.serializeToNBT()); + } + + @Override + protected void loadModData(CompoundTag tag) { + this.executionState = null; + if (tag.contains(TAG_EXECUTION_STATE, Tag.TAG_COMPOUND)) { + this.lazyExecutionState = tag.getCompound(TAG_EXECUTION_STATE); + } else { + this.lazyExecutionState = null; + } + + if (tag.contains(TAG_MEDIA, Tag.TAG_LONG)) { + this.media = tag.getLong(TAG_MEDIA); + } + + if (tag.contains(TAG_ERROR_MSG, Tag.TAG_STRING) + && tag.contains(TAG_ERROR_DISPLAY, Tag.TAG_COMPOUND)) { + var msg = Component.Serializer.fromJson(tag.getString(TAG_ERROR_MSG)); + var display = ItemStack.of(tag.getCompound(TAG_ERROR_DISPLAY)); + this.displayMsg = msg; + this.displayItem = display; + } else { + this.displayMsg = null; + this.displayItem = null; + } + if (tag.contains(TAG_PIGMENT, Tag.TAG_COMPOUND)) + this.pigment = FrozenPigment.fromNBT(tag.getCompound(TAG_PIGMENT)); + } + + public void applyScryingLensOverlay( + List<Pair<ItemStack, Component>> lines, + BlockState state, + BlockPos pos, + Player observer, + Level world, + Direction hitFace) { + if (world.getBlockEntity(pos) instanceof BlockEntityAbstractImpetus beai) { + if (beai.getMedia() < 0) { + lines.add( + new Pair<>( + new ItemStack(HexItems.AMETHYST_DUST), ItemCreativeUnlocker.infiniteMedia(world))); + } else { + var dustCount = (float) beai.getMedia() / (float) MediaConstants.DUST_UNIT; + var dustCmp = + Component.translatable("hexcasting.tooltip.media", DUST_AMOUNT.format(dustCount)); + lines.add(new Pair<>(new ItemStack(HexItems.AMETHYST_DUST), dustCmp)); + } + + if (this.displayMsg != null && this.displayItem != null) { + lines.add(new Pair<>(this.displayItem, this.displayMsg)); + } + } + } + + // region music + + protected int semitoneFromScale(int note) { + var blockBelow = this.level.getBlockState(this.getBlockPos().below()); + var scale = MAJOR_SCALE; + if (blockBelow.is(Blocks.CRYING_OBSIDIAN)) { + scale = MINOR_SCALE; + } else if (blockBelow.is(BlockTags.DOORS) || blockBelow.is(BlockTags.TRAPDOORS)) { + scale = DORIAN_SCALE; + } else if (blockBelow.is(Blocks.PISTON) || blockBelow.is(Blocks.STICKY_PISTON)) { + scale = MIXOLYDIAN_SCALE; + } else if (blockBelow.is(Blocks.BLUE_WOOL) + || blockBelow.is(Blocks.BLUE_CONCRETE) + || blockBelow.is(Blocks.BLUE_CONCRETE_POWDER) + || blockBelow.is(Blocks.BLUE_TERRACOTTA) + || blockBelow.is(Blocks.BLUE_GLAZED_TERRACOTTA) + || blockBelow.is(Blocks.BLUE_STAINED_GLASS) + || blockBelow.is(Blocks.BLUE_STAINED_GLASS_PANE)) { + scale = BLUES_SCALE; + } else if (blockBelow.is(Blocks.BONE_BLOCK)) { + scale = BAD_TIME; + } else if (blockBelow.is(Blocks.COMPOSTER)) { + scale = SUSSY_BAKA; + } + + note = Mth.clamp(note, 0, scale.length - 1); + return scale[note]; + } + + // this is a good use of my time + private static final int[] MAJOR_SCALE = {0, 2, 4, 5, 7, 9, 11, 12}; + private static final int[] MINOR_SCALE = {0, 2, 3, 5, 7, 8, 11, 12}; + private static final int[] DORIAN_SCALE = {0, 2, 3, 5, 7, 9, 10, 12}; + private static final int[] MIXOLYDIAN_SCALE = {0, 2, 4, 5, 7, 9, 10, 12}; + private static final int[] BLUES_SCALE = {0, 3, 5, 6, 7, 10, 12}; + private static final int[] BAD_TIME = {0, 0, 12, 7, 6, 5, 3, 0, 3, 5}; + private static final int[] SUSSY_BAKA = {5, 8, 10, 11, 10, 8, 5, 3, 7, 5}; + + // endregion + + // region item handler contract stuff + private static final int[] SLOTS = {0}; + + @Override + public int[] getSlotsForFace(Direction var1) { + return SLOTS; + } + + @Override + public boolean canPlaceItemThroughFace(int index, ItemStack stack, @Nullable Direction dir) { + return this.canPlaceItem(index, stack); + } + + @Override + public boolean canTakeItemThroughFace(int var1, ItemStack var2, Direction var3) { + return false; + } + + @Override + public int getContainerSize() { + return 1; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public ItemStack getItem(int index) { + return ItemStack.EMPTY.copy(); + } + + @Override + public ItemStack removeItem(int index, int count) { + return ItemStack.EMPTY.copy(); + } + + @Override + public ItemStack removeItemNoUpdate(int index) { + return ItemStack.EMPTY.copy(); + } + + @Override + public void setItem(int index, ItemStack stack) { + insertMedia(stack); + } + + @Override + public boolean stillValid(Player player) { + return false; + } + + @Override + public void clearContent() { + // NO-OP + } + + @Override + public boolean canPlaceItem(int index, ItemStack stack) { + if (remainingMediaCapacity() == 0) { + return false; + } + + if (stack.is(HexItems.CREATIVE_UNLOCKER)) { + return true; + } + + var mediamount = extractMediaFromInsertedItem(stack, true); + return mediamount > 0; + } + + // endregion } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java index f95fa84f01..9abaf8e67a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java @@ -7,6 +7,7 @@ import at.petrak.hexcasting.api.pigment.FrozenPigment; import at.petrak.hexcasting.api.utils.HexUtils; import com.mojang.datafixers.util.Pair; +import java.util.*; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -22,287 +23,323 @@ import net.minecraft.world.phys.AABB; import org.jetbrains.annotations.Nullable; -import java.util.*; - -/** - * See {@link BlockEntityAbstractImpetus}, this is what's stored in it - */ +/** See {@link BlockEntityAbstractImpetus}, this is what's stored in it */ public class CircleExecutionState { - public static final String - TAG_IMPETUS_POS = "impetus_pos", - TAG_IMPETUS_DIR = "impetus_dir", - TAG_KNOWN_POSITIONS = "known_positions", - TAG_REACHED_POSITIONS = "reached_positions", - TAG_CURRENT_POS = "current_pos", - TAG_ENTERED_FROM = "entered_from", - TAG_IMAGE = "image", - TAG_CASTER = "caster", - TAG_PIGMENT = "pigment"; - - public final BlockPos impetusPos; - public final Direction impetusDir; - // Does contain the starting impetus - public final Set<BlockPos> knownPositions; - public final List<BlockPos> reachedPositions; - public BlockPos currentPos; - public Direction enteredFrom; - public CastingImage currentImage; - public @Nullable UUID caster; - public @Nullable FrozenPigment casterPigment; - - public final AABB bounds; - - - protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, Set<BlockPos> knownPositions, - List<BlockPos> reachedPositions, BlockPos currentPos, Direction enteredFrom, - CastingImage currentImage, @Nullable UUID caster, @Nullable FrozenPigment casterPigment) { - this.impetusPos = impetusPos; - this.impetusDir = impetusDir; - this.knownPositions = knownPositions; - this.reachedPositions = reachedPositions; - this.currentPos = currentPos; - this.enteredFrom = enteredFrom; - this.currentImage = currentImage; - this.caster = caster; - this.casterPigment = casterPigment; - - this.bounds = BlockEntityAbstractImpetus.getBounds(new ArrayList<>(this.knownPositions)); - } - - public @Nullable ServerPlayer getCaster(ServerLevel world) { - if (this.caster == null) { - return null; - } - var entity = world.getEntity(this.caster); - if (entity instanceof ServerPlayer serverPlayer) { - return serverPlayer; - } - // there's a problem if this branch is reached - return null; - } - - // Return OK if it succeeded; returns Err if it didn't close and the location - public static Result<CircleExecutionState, @Nullable BlockPos> createNew(BlockEntityAbstractImpetus impetus, - @Nullable ServerPlayer caster) { - var level = (ServerLevel) impetus.getLevel(); - - if (level == null) - return new Result.Err<>(null); - - // Flood fill! Just like VCC all over again. - // this contains tentative positions and directions entered from - var todo = new Stack<Pair<Direction, BlockPos>>(); - todo.add(Pair.of(impetus.getStartDirection(), impetus.getBlockPos().relative(impetus.getStartDirection()))); - var seenGoodPosSet = new HashSet<BlockPos>(); - var seenGoodPositions = new ArrayList<BlockPos>(); - - while (!todo.isEmpty()) { - var pair = todo.pop(); - var enterDir = pair.getFirst(); - var herePos = pair.getSecond(); - - var hereBs = level.getBlockState(herePos); - if (!(hereBs.getBlock() instanceof ICircleComponent cmp)) { - continue; - } - if (!cmp.canEnterFromDirection(enterDir, herePos, hereBs, level)) { - continue; - } - - if (seenGoodPosSet.add(herePos)) { - // it's new - seenGoodPositions.add(herePos); - var outs = cmp.possibleExitDirections(herePos, hereBs, level); - for (var out : outs) { - todo.add(Pair.of(out, herePos.relative(out))); - } - } - } - - if (seenGoodPositions.isEmpty()) { - return new Result.Err<>(null); - } else if (!seenGoodPosSet.contains(impetus.getBlockPos())) { - // we can't enter from the side the directrix exits from, so this means we couldn't loop back. - // the last item we tried to examine will always be a terminal slate (b/c if it wasn't, - // then the *next* slate would be last qed) - return new Result.Err<>(seenGoodPositions.get(seenGoodPositions.size() - 1)); - } - - var knownPositions = new HashSet<>(seenGoodPositions); - var reachedPositions = new ArrayList<BlockPos>(); - reachedPositions.add(impetus.getBlockPos()); - var start = seenGoodPositions.get(0); - - FrozenPigment colorizer = null; - UUID casterUUID; - if (caster == null) { - casterUUID = null; - } else { - colorizer = HexAPI.instance().getColorizer(caster); - casterUUID = caster.getUUID(); - } - return new Result.Ok<>( - new CircleExecutionState(impetus.getBlockPos(), impetus.getStartDirection(), knownPositions, - reachedPositions, start, impetus.getStartDirection(), new CastingImage(), casterUUID, colorizer)); - } - - public CompoundTag save() { - var out = new CompoundTag(); - - out.put(TAG_IMPETUS_POS, NbtUtils.writeBlockPos(this.impetusPos)); - out.putByte(TAG_IMPETUS_DIR, (byte) this.impetusDir.ordinal()); - - var knownTag = new ListTag(); - for (var bp : this.knownPositions) { - knownTag.add(NbtUtils.writeBlockPos(bp)); - } - out.put(TAG_KNOWN_POSITIONS, knownTag); - - var reachedTag = new ListTag(); - for (var bp : this.reachedPositions) { - reachedTag.add(NbtUtils.writeBlockPos(bp)); - } - out.put(TAG_REACHED_POSITIONS, reachedTag); - - out.put(TAG_CURRENT_POS, NbtUtils.writeBlockPos(this.currentPos)); - out.putByte(TAG_ENTERED_FROM, (byte) this.enteredFrom.ordinal()); - out.put(TAG_IMAGE, this.currentImage.serializeToNbt()); - - if (this.caster != null) - out.putUUID(TAG_CASTER, this.caster); - - if (this.casterPigment != null) - out.put(TAG_PIGMENT, this.casterPigment.serializeToNBT()); - - return out; - } - - public static CircleExecutionState load(CompoundTag nbt, ServerLevel world) { - var startPos = NbtUtils.readBlockPos(nbt.getCompound(TAG_IMPETUS_POS)); - var startDir = Direction.values()[nbt.getByte(TAG_IMPETUS_DIR)]; - - var knownPositions = new HashSet<BlockPos>(); - var knownTag = nbt.getList(TAG_KNOWN_POSITIONS, Tag.TAG_COMPOUND); - for (var tag : knownTag) { - knownPositions.add(NbtUtils.readBlockPos(HexUtils.downcast(tag, CompoundTag.TYPE))); - } - var reachedPositions = new ArrayList<BlockPos>(); - var reachedTag = nbt.getList(TAG_REACHED_POSITIONS, Tag.TAG_COMPOUND); - for (var tag : reachedTag) { - reachedPositions.add(NbtUtils.readBlockPos(HexUtils.downcast(tag, CompoundTag.TYPE))); - } - - var currentPos = NbtUtils.readBlockPos(nbt.getCompound(TAG_CURRENT_POS)); - var enteredFrom = Direction.values()[nbt.getByte(TAG_ENTERED_FROM)]; - var image = CastingImage.loadFromNbt(nbt.getCompound(TAG_IMAGE), world); - - UUID caster = null; - if (nbt.hasUUID(TAG_CASTER)) - caster = nbt.getUUID(TAG_CASTER); - - FrozenPigment pigment = null; - if (nbt.contains(TAG_PIGMENT, Tag.TAG_COMPOUND)) - pigment = FrozenPigment.fromNBT(nbt.getCompound(TAG_PIGMENT)); - - return new CircleExecutionState(startPos, startDir, knownPositions, reachedPositions, currentPos, - enteredFrom, image, caster, pigment); - } - - /** - * Update this, also mutates the impetus. - * <p> - * Returns whether to continue. - */ - public boolean tick(BlockEntityAbstractImpetus impetus) { - var world = (ServerLevel) impetus.getLevel(); - - if (world == null) - return true; // if the world is null, try again next tick. - - var env = new CircleCastEnv(world, this); - - var executorBlockState = world.getBlockState(this.currentPos); - if (!(executorBlockState.getBlock() instanceof ICircleComponent executor)) { - // TODO: notification of the error? - ICircleComponent.sfx(this.currentPos, executorBlockState, world, - Objects.requireNonNull(env.getImpetus()), false); - return false; - } - - executorBlockState = executor.startEnergized(this.currentPos, executorBlockState, world); - this.reachedPositions.add(this.currentPos); - - // Do the execution! - boolean halt = false; - var ctrl = executor.acceptControlFlow(this.currentImage, env, this.enteredFrom, this.currentPos, - executorBlockState, world); - - if (env.getImpetus() == null) - return false; //the impetus got removed during the cast and no longer exists in the world. stop casting - - if (ctrl instanceof ICircleComponent.ControlFlow.Stop) { - // acceptControlFlow should have already posted the error - halt = true; - } else if (ctrl instanceof ICircleComponent.ControlFlow.Continue cont) { - Pair<BlockPos, Direction> found = null; - - for (var exit : cont.exits) { - var there = world.getBlockState(exit.getFirst()); - if (there.getBlock() instanceof ICircleComponent cc - && cc.canEnterFromDirection(exit.getSecond(), exit.getFirst(), there, world)) { - if (found != null) { - // oh no! - impetus.postDisplay( - Component.translatable("hexcasting.tooltip.circle.many_exits", - Component.literal(this.currentPos.toShortString()).withStyle(ChatFormatting.RED)), - new ItemStack(Items.COMPASS)); - ICircleComponent.sfx(this.currentPos, executorBlockState, world, - Objects.requireNonNull(env.getImpetus()), false); - halt = true; - break; - } else { - found = exit; - } - } - } - - if (found == null) { - // will never enter here if there were too many because found will have been set - ICircleComponent.sfx(this.currentPos, executorBlockState, world, - Objects.requireNonNull(env.getImpetus()), false); - impetus.postNoExits(this.currentPos); - halt = true; - } else { - // A single valid exit position has been found. - ICircleComponent.sfx(this.currentPos, executorBlockState, world, - Objects.requireNonNull(env.getImpetus()), true); - currentPos = found.getFirst(); - enteredFrom = found.getSecond(); - currentImage = cont.update.withOverriddenUsedOps(0); // reset ops used after each slate finishes executing - } - } - - return !halt; - } - - /** - * How many ticks should pass between activations, given the number of blocks encountered so far. - */ - protected int getTickSpeed() { - return Math.max(2, 10 - (this.reachedPositions.size() - 1) / 3); - } - - public void endExecution(BlockEntityAbstractImpetus impetus) { - var world = (ServerLevel) impetus.getLevel(); - - if (world == null) - return; // TODO: error here? - - for (var pos : this.reachedPositions) { - var there = world.getBlockState(pos); - if (there.getBlock() instanceof ICircleComponent cc) { - cc.endEnergized(pos, there, world); - } - } - } + public static final String TAG_IMPETUS_POS = "impetus_pos", + TAG_IMPETUS_DIR = "impetus_dir", + TAG_KNOWN_POSITIONS = "known_positions", + TAG_REACHED_POSITIONS = "reached_positions", + TAG_CURRENT_POS = "current_pos", + TAG_ENTERED_FROM = "entered_from", + TAG_IMAGE = "image", + TAG_CASTER = "caster", + TAG_PIGMENT = "pigment"; + + public final BlockPos impetusPos; + public final Direction impetusDir; + // Does contain the starting impetus + public final Set<BlockPos> knownPositions; + public final List<BlockPos> reachedPositions; + public BlockPos currentPos; + public Direction enteredFrom; + public CastingImage currentImage; + public @Nullable UUID caster; + public @Nullable FrozenPigment casterPigment; + + public final AABB bounds; + + protected CircleExecutionState( + BlockPos impetusPos, + Direction impetusDir, + Set<BlockPos> knownPositions, + List<BlockPos> reachedPositions, + BlockPos currentPos, + Direction enteredFrom, + CastingImage currentImage, + @Nullable UUID caster, + @Nullable FrozenPigment casterPigment) { + this.impetusPos = impetusPos; + this.impetusDir = impetusDir; + this.knownPositions = knownPositions; + this.reachedPositions = reachedPositions; + this.currentPos = currentPos; + this.enteredFrom = enteredFrom; + this.currentImage = currentImage; + this.caster = caster; + this.casterPigment = casterPigment; + + this.bounds = BlockEntityAbstractImpetus.getBounds(new ArrayList<>(this.knownPositions)); + } + + public @Nullable ServerPlayer getCaster(ServerLevel world) { + if (this.caster == null) { + return null; + } + var entity = world.getEntity(this.caster); + if (entity instanceof ServerPlayer serverPlayer) { + return serverPlayer; + } + // there's a problem if this branch is reached + return null; + } + + // Return OK if it succeeded; returns Err if it didn't close and the location + public static Result<CircleExecutionState, @Nullable BlockPos> createNew( + BlockEntityAbstractImpetus impetus, @Nullable ServerPlayer caster) { + var level = (ServerLevel) impetus.getLevel(); + + if (level == null) return new Result.Err<>(null); + + // Flood fill! Just like VCC all over again. + // this contains tentative positions and directions entered from + var todo = new Stack<Pair<Direction, BlockPos>>(); + todo.add( + Pair.of( + impetus.getStartDirection(), + impetus.getBlockPos().relative(impetus.getStartDirection()))); + var seenGoodPosSet = new HashSet<BlockPos>(); + var seenGoodPositions = new ArrayList<BlockPos>(); + + while (!todo.isEmpty()) { + var pair = todo.pop(); + var enterDir = pair.getFirst(); + var herePos = pair.getSecond(); + + var hereBs = level.getBlockState(herePos); + if (!(hereBs.getBlock() instanceof ICircleComponent cmp)) { + continue; + } + if (!cmp.canEnterFromDirection(enterDir, herePos, hereBs, level)) { + continue; + } + + if (seenGoodPosSet.add(herePos)) { + // it's new + seenGoodPositions.add(herePos); + var outs = cmp.possibleExitDirections(herePos, hereBs, level); + for (var out : outs) { + todo.add(Pair.of(out, herePos.relative(out))); + } + } + } + + if (seenGoodPositions.isEmpty()) { + return new Result.Err<>(null); + } else if (!seenGoodPosSet.contains(impetus.getBlockPos())) { + // we can't enter from the side the directrix exits from, so this means we couldn't loop back. + // the last item we tried to examine will always be a terminal slate (b/c if it wasn't, + // then the *next* slate would be last qed) + return new Result.Err<>(seenGoodPositions.get(seenGoodPositions.size() - 1)); + } + + var knownPositions = new HashSet<>(seenGoodPositions); + var reachedPositions = new ArrayList<BlockPos>(); + reachedPositions.add(impetus.getBlockPos()); + var start = seenGoodPositions.get(0); + + FrozenPigment colorizer = null; + UUID casterUUID; + if (caster == null) { + casterUUID = null; + } else { + colorizer = HexAPI.instance().getColorizer(caster); + casterUUID = caster.getUUID(); + } + return new Result.Ok<>( + new CircleExecutionState( + impetus.getBlockPos(), + impetus.getStartDirection(), + knownPositions, + reachedPositions, + start, + impetus.getStartDirection(), + new CastingImage(), + casterUUID, + colorizer)); + } + + public CompoundTag save() { + var out = new CompoundTag(); + + out.put(TAG_IMPETUS_POS, NbtUtils.writeBlockPos(this.impetusPos)); + out.putByte(TAG_IMPETUS_DIR, (byte) this.impetusDir.ordinal()); + + var knownTag = new ListTag(); + for (var bp : this.knownPositions) { + knownTag.add(NbtUtils.writeBlockPos(bp)); + } + out.put(TAG_KNOWN_POSITIONS, knownTag); + + var reachedTag = new ListTag(); + for (var bp : this.reachedPositions) { + reachedTag.add(NbtUtils.writeBlockPos(bp)); + } + out.put(TAG_REACHED_POSITIONS, reachedTag); + + out.put(TAG_CURRENT_POS, NbtUtils.writeBlockPos(this.currentPos)); + out.putByte(TAG_ENTERED_FROM, (byte) this.enteredFrom.ordinal()); + out.put(TAG_IMAGE, this.currentImage.serializeToNbt()); + + if (this.caster != null) out.putUUID(TAG_CASTER, this.caster); + + if (this.casterPigment != null) out.put(TAG_PIGMENT, this.casterPigment.serializeToNBT()); + + return out; + } + + public static CircleExecutionState load(CompoundTag nbt, ServerLevel world) { + var startPos = NbtUtils.readBlockPos(nbt.getCompound(TAG_IMPETUS_POS)); + var startDir = Direction.values()[nbt.getByte(TAG_IMPETUS_DIR)]; + + var knownPositions = new HashSet<BlockPos>(); + var knownTag = nbt.getList(TAG_KNOWN_POSITIONS, Tag.TAG_COMPOUND); + for (var tag : knownTag) { + knownPositions.add(NbtUtils.readBlockPos(HexUtils.downcast(tag, CompoundTag.TYPE))); + } + var reachedPositions = new ArrayList<BlockPos>(); + var reachedTag = nbt.getList(TAG_REACHED_POSITIONS, Tag.TAG_COMPOUND); + for (var tag : reachedTag) { + reachedPositions.add(NbtUtils.readBlockPos(HexUtils.downcast(tag, CompoundTag.TYPE))); + } + + var currentPos = NbtUtils.readBlockPos(nbt.getCompound(TAG_CURRENT_POS)); + var enteredFrom = Direction.values()[nbt.getByte(TAG_ENTERED_FROM)]; + var image = CastingImage.loadFromNbt(nbt.getCompound(TAG_IMAGE), world); + + UUID caster = null; + if (nbt.hasUUID(TAG_CASTER)) caster = nbt.getUUID(TAG_CASTER); + + FrozenPigment pigment = null; + if (nbt.contains(TAG_PIGMENT, Tag.TAG_COMPOUND)) + pigment = FrozenPigment.fromNBT(nbt.getCompound(TAG_PIGMENT)); + + return new CircleExecutionState( + startPos, + startDir, + knownPositions, + reachedPositions, + currentPos, + enteredFrom, + image, + caster, + pigment); + } + + /** + * Update this, also mutates the impetus. + * + * <p>Returns whether to continue. + */ + public boolean tick(BlockEntityAbstractImpetus impetus) { + var world = (ServerLevel) impetus.getLevel(); + + if (world == null) return true; // if the world is null, try again next tick. + + var env = new CircleCastEnv(world, this); + + var executorBlockState = world.getBlockState(this.currentPos); + if (!(executorBlockState.getBlock() instanceof ICircleComponent executor)) { + // TODO: notification of the error? + ICircleComponent.sfx( + this.currentPos, + executorBlockState, + world, + Objects.requireNonNull(env.getImpetus()), + false); + return false; + } + + executorBlockState = executor.startEnergized(this.currentPos, executorBlockState, world); + this.reachedPositions.add(this.currentPos); + + // Do the execution! + boolean halt = false; + var ctrl = + executor.acceptControlFlow( + this.currentImage, env, this.enteredFrom, this.currentPos, executorBlockState, world); + + if (env.getImpetus() == null) + return false; // the impetus got removed during the cast and no longer exists in the world. + // stop casting + + if (ctrl instanceof ICircleComponent.ControlFlow.Stop) { + // acceptControlFlow should have already posted the error + halt = true; + } else if (ctrl instanceof ICircleComponent.ControlFlow.Continue cont) { + Pair<BlockPos, Direction> found = null; + + for (var exit : cont.exits) { + var there = world.getBlockState(exit.getFirst()); + if (there.getBlock() instanceof ICircleComponent cc + && cc.canEnterFromDirection(exit.getSecond(), exit.getFirst(), there, world)) { + if (found != null) { + // oh no! + impetus.postDisplay( + Component.translatable( + "hexcasting.tooltip.circle.many_exits", + Component.literal(this.currentPos.toShortString()) + .withStyle(ChatFormatting.RED)), + new ItemStack(Items.COMPASS)); + ICircleComponent.sfx( + this.currentPos, + executorBlockState, + world, + Objects.requireNonNull(env.getImpetus()), + false); + halt = true; + break; + } else { + found = exit; + } + } + } + + if (found == null) { + // will never enter here if there were too many because found will have been set + ICircleComponent.sfx( + this.currentPos, + executorBlockState, + world, + Objects.requireNonNull(env.getImpetus()), + false); + impetus.postNoExits(this.currentPos); + halt = true; + } else { + // A single valid exit position has been found. + ICircleComponent.sfx( + this.currentPos, + executorBlockState, + world, + Objects.requireNonNull(env.getImpetus()), + true); + currentPos = found.getFirst(); + enteredFrom = found.getSecond(); + currentImage = + cont.update.withOverriddenUsedOps( + 0); // reset ops used after each slate finishes executing + } + } + + return !halt; + } + + /** + * How many ticks should pass between activations, given the number of blocks encountered so far. + */ + protected int getTickSpeed() { + return Math.max(2, 10 - (this.reachedPositions.size() - 1) / 3); + } + + public void endExecution(BlockEntityAbstractImpetus impetus) { + var world = (ServerLevel) impetus.getLevel(); + + if (world == null) return; // TODO: error here? + + for (var pos : this.reachedPositions) { + var there = world.getBlockState(pos); + if (there.getBlock() instanceof ICircleComponent cc) { + cc.endEnergized(pos, there, world); + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/ICircleComponent.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/ICircleComponent.java index 66e06b4d0d..f3deda4ded 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/ICircleComponent.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/ICircleComponent.java @@ -11,6 +11,9 @@ import at.petrak.hexcasting.common.lib.HexItems; import at.petrak.hexcasting.common.lib.HexSounds; import com.mojang.datafixers.util.Pair; +import java.util.EnumSet; +import java.util.List; +import java.util.UUID; import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -25,146 +28,165 @@ import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Contract; -import java.util.EnumSet; -import java.util.List; -import java.util.UUID; - /** * Implement this on a block to make circles interact with it. - * <p> - * This is its own interface so you can have your blocks subclass something else, and to avoid enormous - * files. The mod doesn't check for the interface on anything but blocks. + * + * <p>This is its own interface so you can have your blocks subclass something else, and to avoid + * enormous files. The mod doesn't check for the interface on anything but blocks. */ public interface ICircleComponent { - /** - * The heart of the interface! Functionally modify the casting environment. - * <p> - * With the new update you can have the side effects happen inline. In fact, you have to have the side effects - * happen inline. - * <p> - * Also, return a list of directions that the control flow can exit this block in. - * The circle environment will mishap if not exactly 1 of the returned directions can be accepted from. - */ - ControlFlow acceptControlFlow(CastingImage imageIn, CircleCastEnv env, Direction enterDir, BlockPos pos, - BlockState bs, ServerLevel world); - - /** - * Can this component get transferred to from a block coming in from that direction, with the given normal? - */ - @Contract(pure = true) - boolean canEnterFromDirection(Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world); - - /** - * This determines the directions the control flow <em>can</em> exit from. It's called at the beginning of execution - * to see if the circle actually forms a loop. - * <p> - * For most blocks, this should be the same as returned from {@link ICircleComponent#acceptControlFlow} - * Things like directrices might return otherwise. Whatever is returned when controlling flow must be a subset of - * this set. - */ - @Contract(pure = true) - EnumSet<Direction> possibleExitDirections(BlockPos pos, BlockState bs, Level world); - - /** - * Given the current position and a direction, return a pair of the new position after a step - * in that direction, along with the direction (this is a helper function for creating - * {@link ICircleComponent.ControlFlow}s. - */ - @Contract(pure = true) - default Pair<BlockPos, Direction> exitPositionFromDirection(BlockPos pos, Direction dir) { - return Pair.of(pos.offset(dir.getStepX(), dir.getStepY(), dir.getStepZ()), dir); - } - - /** - * Start the {@link ICircleComponent} at the given position glowing. Returns the new state - * of the given block. - * // TODO: determine if this should just be in - * {@link ICircleComponent#acceptControlFlow(CastingImage, CircleCastEnv, Direction, BlockPos, BlockState, ServerLevel)}. - */ - BlockState startEnergized(BlockPos pos, BlockState bs, Level world); - - /** - * Returns whether the {@link ICircleComponent} at the given position is energized. - */ - boolean isEnergized(BlockPos pos, BlockState bs, Level world); - - /** - * End the {@link ICircleComponent} at the given position glowing. Returns the new state of - * the given block. - */ - BlockState endEnergized(BlockPos pos, BlockState bs, Level world); - - static void sfx(BlockPos pos, BlockState bs, Level world, BlockEntityAbstractImpetus impetus, boolean success) { - Vec3 vpos; - Vec3 vecOutDir; - FrozenPigment colorizer; - - UUID activator = Util.NIL_UUID; - if (impetus != null && impetus.getExecutionState() != null && impetus.getExecutionState().caster != null) - activator = impetus.getExecutionState().caster; - - if (impetus == null || impetus.getExecutionState() == null) - colorizer = new FrozenPigment(new ItemStack(HexItems.DYE_PIGMENTS.get(DyeColor.RED)), activator); - else - colorizer = impetus.getPigment(); - - if (bs.getBlock() instanceof BlockCircleComponent bcc) { - var outDir = bcc.normalDir(pos, bs, world); - var height = bcc.particleHeight(pos, bs, world); - vecOutDir = new Vec3(outDir.step()); - vpos = Vec3.atCenterOf(pos).add(vecOutDir.scale(height)); - } else { - // we probably are doing this because it's an error and we removed a block - vpos = Vec3.atCenterOf(pos); - vecOutDir = new Vec3(0, 0, 0); - } - - if (world instanceof ServerLevel serverLevel) { - var spray = new ParticleSpray(vpos, vecOutDir.scale(success ? 1.0 : 1.5), success ? 0.1 : 0.5, - Mth.PI / (success ? 4 : 2), success ? 30 : 100); - spray.sprayParticles(serverLevel, - success ? colorizer : new FrozenPigment(new ItemStack(HexItems.DYE_PIGMENTS.get(DyeColor.RED)), - activator)); - } - - var pitch = 1f; - var sound = HexSounds.SPELL_CIRCLE_FAIL; - if (success && impetus != null) { - sound = HexSounds.SPELL_CIRCLE_FIND_BLOCK; - - var state = impetus.getExecutionState(); - - // This is a good use of my time - var note = state.reachedPositions.size() - 1; - var semitone = impetus.semitoneFromScale(note); - pitch = (float) Math.pow(2.0, (semitone - 8) / 12d); - } - world.playSound(null, vpos.x, vpos.y, vpos.z, sound, SoundSource.BLOCKS, 1f, pitch); - } - - /** - * Helper function to "throw a mishap" - */ - default void fakeThrowMishap(BlockPos pos, BlockState bs, CastingImage image, CircleCastEnv env, Mishap mishap) { - Mishap.Context errorCtx = new Mishap.Context(null, - bs.getBlock().getName().append(" (").append(Component.literal(pos.toShortString())).append(")")); - var sideEffect = new OperatorSideEffect.DoMishap(mishap, errorCtx); - var vm = new CastingVM(image, env); - sideEffect.performEffect(vm); - } - - abstract sealed class ControlFlow { - public static final class Continue extends ControlFlow { - public final CastingImage update; - public final List<Pair<BlockPos, Direction>> exits; - - public Continue(CastingImage update, List<Pair<BlockPos, Direction>> exits) { - this.update = update; - this.exits = exits; - } - } - - public static final class Stop extends ControlFlow { - } - } + /** + * The heart of the interface! Functionally modify the casting environment. + * + * <p>With the new update you can have the side effects happen inline. In fact, you have to have + * the side effects happen inline. + * + * <p>Also, return a list of directions that the control flow can exit this block in. The circle + * environment will mishap if not exactly 1 of the returned directions can be accepted from. + */ + ControlFlow acceptControlFlow( + CastingImage imageIn, + CircleCastEnv env, + Direction enterDir, + BlockPos pos, + BlockState bs, + ServerLevel world); + + /** + * Can this component get transferred to from a block coming in from that direction, with the + * given normal? + */ + @Contract(pure = true) + boolean canEnterFromDirection(Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world); + + /** + * This determines the directions the control flow <em>can</em> exit from. It's called at the + * beginning of execution to see if the circle actually forms a loop. + * + * <p>For most blocks, this should be the same as returned from {@link + * ICircleComponent#acceptControlFlow} Things like directrices might return otherwise. Whatever is + * returned when controlling flow must be a subset of this set. + */ + @Contract(pure = true) + EnumSet<Direction> possibleExitDirections(BlockPos pos, BlockState bs, Level world); + + /** + * Given the current position and a direction, return a pair of the new position after a step in + * that direction, along with the direction (this is a helper function for creating {@link + * ICircleComponent.ControlFlow}s. + */ + @Contract(pure = true) + default Pair<BlockPos, Direction> exitPositionFromDirection(BlockPos pos, Direction dir) { + return Pair.of(pos.offset(dir.getStepX(), dir.getStepY(), dir.getStepZ()), dir); + } + + /** + * Start the {@link ICircleComponent} at the given position glowing. Returns the new state of the + * given block. // TODO: determine if this should just be in {@link + * ICircleComponent#acceptControlFlow(CastingImage, CircleCastEnv, Direction, BlockPos, + * BlockState, ServerLevel)}. + */ + BlockState startEnergized(BlockPos pos, BlockState bs, Level world); + + /** Returns whether the {@link ICircleComponent} at the given position is energized. */ + boolean isEnergized(BlockPos pos, BlockState bs, Level world); + + /** + * End the {@link ICircleComponent} at the given position glowing. Returns the new state of the + * given block. + */ + BlockState endEnergized(BlockPos pos, BlockState bs, Level world); + + static void sfx( + BlockPos pos, + BlockState bs, + Level world, + BlockEntityAbstractImpetus impetus, + boolean success) { + Vec3 vpos; + Vec3 vecOutDir; + FrozenPigment colorizer; + + UUID activator = Util.NIL_UUID; + if (impetus != null + && impetus.getExecutionState() != null + && impetus.getExecutionState().caster != null) + activator = impetus.getExecutionState().caster; + + if (impetus == null || impetus.getExecutionState() == null) + colorizer = + new FrozenPigment(new ItemStack(HexItems.DYE_PIGMENTS.get(DyeColor.RED)), activator); + else colorizer = impetus.getPigment(); + + if (bs.getBlock() instanceof BlockCircleComponent bcc) { + var outDir = bcc.normalDir(pos, bs, world); + var height = bcc.particleHeight(pos, bs, world); + vecOutDir = new Vec3(outDir.step()); + vpos = Vec3.atCenterOf(pos).add(vecOutDir.scale(height)); + } else { + // we probably are doing this because it's an error and we removed a block + vpos = Vec3.atCenterOf(pos); + vecOutDir = new Vec3(0, 0, 0); + } + + if (world instanceof ServerLevel serverLevel) { + var spray = + new ParticleSpray( + vpos, + vecOutDir.scale(success ? 1.0 : 1.5), + success ? 0.1 : 0.5, + Mth.PI / (success ? 4 : 2), + success ? 30 : 100); + spray.sprayParticles( + serverLevel, + success + ? colorizer + : new FrozenPigment( + new ItemStack(HexItems.DYE_PIGMENTS.get(DyeColor.RED)), activator)); + } + + var pitch = 1f; + var sound = HexSounds.SPELL_CIRCLE_FAIL; + if (success && impetus != null) { + sound = HexSounds.SPELL_CIRCLE_FIND_BLOCK; + + var state = impetus.getExecutionState(); + + // This is a good use of my time + var note = state.reachedPositions.size() - 1; + var semitone = impetus.semitoneFromScale(note); + pitch = (float) Math.pow(2.0, (semitone - 8) / 12d); + } + world.playSound(null, vpos.x, vpos.y, vpos.z, sound, SoundSource.BLOCKS, 1f, pitch); + } + + /** Helper function to "throw a mishap" */ + default void fakeThrowMishap( + BlockPos pos, BlockState bs, CastingImage image, CircleCastEnv env, Mishap mishap) { + Mishap.Context errorCtx = + new Mishap.Context( + null, + bs.getBlock() + .getName() + .append(" (") + .append(Component.literal(pos.toShortString())) + .append(")")); + var sideEffect = new OperatorSideEffect.DoMishap(mishap, errorCtx); + var vm = new CastingVM(image, env); + sideEffect.performEffect(vm); + } + + abstract sealed class ControlFlow { + public static final class Continue extends ControlFlow { + public final CastingImage update; + public final List<Pair<BlockPos, Direction>> exits; + + public Continue(CastingImage update, List<Pair<BlockPos, Direction>> exits) { + this.update = update; + this.exits = exits; + } + } + + public static final class Stop extends ControlFlow {} + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastResult.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastResult.kt index c0b4d4442d..8b516c85a7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastResult.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastResult.kt @@ -9,15 +9,15 @@ import at.petrak.hexcasting.api.casting.iota.Iota /** * The result of doing something to a cast harness. * - * Contains the iota that was executed to produce this CastResult, - * the next thing to execute after this is finished, the modified state of the stack, - * and side effects, as well as display information for the client. + * Contains the iota that was executed to produce this CastResult, the next thing to execute after + * this is finished, the modified state of the stack, and side effects, as well as display + * information for the client. */ data class CastResult( - val cast: Iota, - val continuation: SpellContinuation, - val newData: CastingImage?, - val sideEffects: List<OperatorSideEffect>, - val resolutionType: ResolvedPatternType, - val sound: EvalSound, + val cast: Iota, + val continuation: SpellContinuation, + val newData: CastingImage?, + val sideEffects: List<OperatorSideEffect>, + val resolutionType: ResolvedPatternType, + val sound: EvalSound, ) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java index 6eaaf765ec..324ceee4b3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java @@ -1,5 +1,8 @@ package at.petrak.hexcasting.api.casting.eval; +import static at.petrak.hexcasting.api.HexAPI.modLoc; +import static at.petrak.hexcasting.api.casting.eval.CastingEnvironmentComponent.*; + import at.petrak.hexcasting.api.casting.ParticleSpray; import at.petrak.hexcasting.api.casting.PatternShapeMatch; import at.petrak.hexcasting.api.casting.eval.vm.CastingImage; @@ -10,6 +13,13 @@ import at.petrak.hexcasting.api.mod.HexConfig; import at.petrak.hexcasting.api.pigment.FrozenPigment; import at.petrak.hexcasting.api.utils.HexUtils; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Predicate; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -26,572 +36,534 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Predicate; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; -import static at.petrak.hexcasting.api.casting.eval.CastingEnvironmentComponent.*; - /** * Environment within which hexes are cast. - * <p> - * Stuff like "the player with a staff," "the player with a trinket," "spell circles," + * + * <p>Stuff like "the player with a staff," "the player with a trinket," "spell circles," */ public abstract class CastingEnvironment { - /** - * Stores all listeners that should be notified whenever a CastingEnvironment is initialised. - */ - private static final List<BiConsumer<CastingEnvironment, CompoundTag>> createEventListeners = new ArrayList<>(); - - /** - * Add a listener that will be called whenever a new CastingEnvironment is created. - */ - public static void addCreateEventListener(BiConsumer<CastingEnvironment, CompoundTag> listener) { - createEventListeners.add(listener); - } - - /** - * Add a listener that will be called whenever a new CastingEnvironment is created (legacy). - * @deprecated replaced by {@link #addCreateEventListener(BiConsumer)} - */ - @Deprecated(since = "0.11.0-pre-660") - public static void addCreateEventListener(Consumer<CastingEnvironment> listener) { - createEventListeners.add((env, data) -> {listener.accept(env);}); - } - - private boolean createEventTriggered = false; - - public final void triggerCreateEvent(CompoundTag userData) { - if (!createEventTriggered) { - for (var listener : createEventListeners) - listener.accept(this, userData); - createEventTriggered = true; - } - } - - - protected final ServerLevel world; - - protected Map<CastingEnvironmentComponent.Key<?>, @NotNull CastingEnvironmentComponent> componentMap = new HashMap<>(); - private final List<PostExecution> postExecutions = new ArrayList<>(); - - private final List<PostCast> postCasts = new ArrayList<>(); - private final List<ExtractMedia.Pre> preMediaExtract = new ArrayList<>(); - private final List<ExtractMedia.Post> postMediaExtract = new ArrayList<>(); - - private final List<IsVecInRange> isVecInRanges = new ArrayList<>(); - private final List<HasEditPermissionsAt> hasEditPermissionsAts = new ArrayList<>(); - - protected CastingEnvironment(ServerLevel world) { - this.world = world; - } - - public final ServerLevel getWorld() { - return this.world; - } - - public int maxOpCount() { - return HexConfig.server().maxOpCount(); - } - - /** - * Get the caster. Might be null! - * <p> - * Implementations should NOT rely on this in general, use the methods on this class instead. - * This is mostly for spells (flight, etc) - * @deprecated as of build 0.11.1-7-pre-619 you are recommended to use {@link #getCastingEntity} - */ - @Deprecated(since="0.11.1-7-pre-619") - @Nullable - public ServerPlayer getCaster() { - return getCastingEntity() instanceof ServerPlayer sp ? sp : null; - }; - - /** - * Gets the caster. Can be null if {@link #getCaster()} is also null - * @return the entity casting - */ - @Nullable - public abstract LivingEntity getCastingEntity(); - - /** - * Get an interface used to do mishaps - */ - public abstract MishapEnvironment getMishapEnvironment(); - - public <T extends CastingEnvironmentComponent> void addExtension(@NotNull T extension) { - componentMap.put(extension.getKey(), extension); - if (extension instanceof PostExecution postExecution) - postExecutions.add(postExecution); - if (extension instanceof PostCast postCast) - postCasts.add(postCast); - if (extension instanceof ExtractMedia extractMedia) - if (extension instanceof ExtractMedia.Pre pre) { - preMediaExtract.add(pre); - } else if (extension instanceof ExtractMedia.Post post) { - postMediaExtract.add(post); - } - if (extension instanceof IsVecInRange isVecInRange) - isVecInRanges.add(isVecInRange); - if (extension instanceof HasEditPermissionsAt hasEditPermissionsAt) - hasEditPermissionsAts.add(hasEditPermissionsAt); - } - - public void removeExtension(@NotNull CastingEnvironmentComponent.Key<?> key) { - var extension = componentMap.remove(key); - if (extension == null) - return; - - if (extension instanceof PostExecution postExecution) - postExecutions.remove(postExecution); - if (extension instanceof PostCast postCast) - postCasts.remove(postCast); - if (extension instanceof ExtractMedia extractMedia) - if (extension instanceof ExtractMedia.Pre pre) { - preMediaExtract.remove(pre); - } else if (extension instanceof ExtractMedia.Post post) { - postMediaExtract.remove(post); - } - if (extension instanceof IsVecInRange isVecInRange) - isVecInRanges.remove(isVecInRange); - if (extension instanceof HasEditPermissionsAt hasEditPermissionsAt) - hasEditPermissionsAts.remove(hasEditPermissionsAt); - } - - @Nullable - @SuppressWarnings("unchecked") - public <T extends CastingEnvironmentComponent> T getExtension(@NotNull CastingEnvironmentComponent.Key<T> key) { - return (T) componentMap.get(key); - } - - /** - * If something about this ARE itself is invalid, mishap. - * <p> - * This is used for stuff like requiring enlightenment and pattern denylists - */ - public void precheckAction(PatternShapeMatch match) throws Mishap { - // TODO: this doesn't let you select special handlers. - // Might be worth making a "no casting" tag on each thing - ResourceLocation key = actionKey(match); - - if (!HexConfig.server().isActionAllowed(key)) { - throw new MishapDisallowedSpell(); - } - } - - @Nullable - protected ResourceLocation actionKey(PatternShapeMatch match) { - ResourceLocation key; - if (match instanceof PatternShapeMatch.Normal normal) { - key = normal.key.location(); - } else if (match instanceof PatternShapeMatch.PerWorld perWorld) { - key = perWorld.key.location(); - } else if (match instanceof PatternShapeMatch.Special special) { - key = special.key.location(); - } else { - key = null; - } - return key; - } - - /** - * Do whatever you like after a pattern is executed. - */ - public void postExecution(CastResult result) { - for (var postExecutionComponent : postExecutions) - postExecutionComponent.onPostExecution(result); - } - - /** - * Do things after the whole cast is finished (i.e. every pattern to be executed has been executed). - */ - public void postCast(CastingImage image) { - for (var postCastComponent : postCasts) - postCastComponent.onPostCast(image); - } - - public abstract Vec3 mishapSprayPos(); - - /** - * Return whether this env can cast great spells. - */ - public boolean isEnlightened() { - var adv = this.world.getServer().getAdvancements().getAdvancement(modLoc("enlightenment")); - if (adv == null) - return false; - - var caster = this.getCastingEntity(); - if (caster instanceof ServerPlayer player) - return player.getAdvancements().getOrStartProgress(adv).isDone(); - - return false; - } - - /** - * Attempt to extract the given amount of media. Returns the amount of media left in the cost. - * <p> - * If there was enough media found, it will return less or equal to zero; if there wasn't, it will be - * positive. - */ - public long extractMedia(long cost, boolean simulate) { - for (var extractMediaComponent : preMediaExtract) - cost = extractMediaComponent.onExtractMedia(cost, simulate); - cost = extractMediaEnvironment(cost, simulate); - for (var extractMediaComponent : postMediaExtract) - cost = extractMediaComponent.onExtractMedia(cost, simulate); - return cost; - } - - /** - * Attempt to extract the given amount of media. Returns the amount of media left in the cost. - * <p> - * If there was enough media found, it will return less or equal to zero; if there wasn't, it will be - * positive. - */ - protected abstract long extractMediaEnvironment(long cost, boolean simulate); - - /** - * Get if the vec is close enough, to the player or sentinel ... - * <p> - * Doesn't take into account being out of the <em>world</em>. - */ - public boolean isVecInRange(Vec3 vec) { - boolean isInRange = isVecInRangeEnvironment(vec); - for (var isVecInRangeComponent : isVecInRanges) - isInRange = isVecInRangeComponent.onIsVecInRange(vec, isInRange); - return isInRange; - } - - /** - * Get if the vec is close enough, to the player or sentinel ... - * <p> - * Doesn't take into account being out of the <em>world</em>. - */ - protected abstract boolean isVecInRangeEnvironment(Vec3 vec); - - /** - * Return whether the caster can edit blocks at the given permission (i.e. not adventure mode, etc.) - */ - public boolean hasEditPermissionsAt(BlockPos pos) { - boolean hasEditPermissionsAt = hasEditPermissionsAtEnvironment(pos); - for (var hasEditPermissionsAtComponent : hasEditPermissionsAts) - hasEditPermissionsAt = hasEditPermissionsAtComponent.onHasEditPermissionsAt(pos, hasEditPermissionsAt); - return hasEditPermissionsAt; - } - - /** - * Return whether the caster can edit blocks at the given permission (i.e. not adventure mode, etc.) - */ - protected abstract boolean hasEditPermissionsAtEnvironment(BlockPos pos); - - public final boolean isVecInWorld(Vec3 vec) { - return this.world.isInWorldBounds(BlockPos.containing(vec)) - && this.world.getWorldBorder().isWithinBounds(vec.x, vec.z, 0.5); - } - - public final boolean isVecInAmbit(Vec3 vec) { - return this.isVecInRange(vec) && this.isVecInWorld(vec); - } - - public final boolean isEntityInRange(Entity e) { - return (e instanceof Player && HexConfig.server().trueNameHasAmbit()) || (this.isVecInWorld(e.position()) && this.isVecInRange(e.position())); - } - - /** - * Convenience function to throw if the vec is out of the caster's range or the world - */ - public final void assertVecInRange(Vec3 vec) throws MishapBadLocation { - this.assertVecInWorld(vec); - if (!this.isVecInRange(vec)) { - throw new MishapBadLocation(vec, "too_far"); - } - } - - public final void assertPosInRange(BlockPos vec) throws MishapBadLocation { - this.assertVecInRange(new Vec3(vec.getX(), vec.getY(), vec.getZ())); - } - - public final void assertPosInRangeForEditing(BlockPos vec) throws MishapBadLocation { - this.assertVecInRange(new Vec3(vec.getX(), vec.getY(), vec.getZ())); - if (!this.canEditBlockAt(vec)) - throw new MishapBadLocation(Vec3.atCenterOf(vec), "forbidden"); - } - - public final boolean canEditBlockAt(BlockPos vec) { - return this.isVecInRange(Vec3.atCenterOf(vec)) && this.hasEditPermissionsAt(vec); - } - - /** - * Convenience function to throw if the entity is out of the caster's range or the world - */ - public final void assertEntityInRange(Entity e) throws MishapEntityTooFarAway { - if (e instanceof ServerPlayer && HexConfig.server().trueNameHasAmbit()) { - return; - } - if (!this.isVecInWorld(e.position())) { - throw new MishapEntityTooFarAway(e); - } - if (!this.isVecInRange(e.position())) { - throw new MishapEntityTooFarAway(e); - } - } - - /** - * Convenience function to throw if the vec is out of the world (for GTP) - */ - public final void assertVecInWorld(Vec3 vec) throws MishapBadLocation { - if (!this.isVecInWorld(vec)) { - throw new MishapBadLocation(vec, "out_of_world"); - } - } - - public abstract InteractionHand getCastingHand(); - - public InteractionHand getOtherHand() { - return HexUtils.otherHand(this.getCastingHand()); - } - - /** - * Get all the item stacks this env can use. - */ - protected abstract List<ItemStack> getUsableStacks(StackDiscoveryMode mode); - - protected List<ItemStack> getUsableStacksForPlayer(StackDiscoveryMode mode, @Nullable InteractionHand castingHand, ServerPlayer caster) { - return switch (mode) { - case QUERY -> { - var out = new ArrayList<ItemStack>(); - - if (castingHand == null) { - var mainhand = caster.getItemInHand(InteractionHand.MAIN_HAND); - if (!mainhand.isEmpty()) { - out.add(mainhand); - } - - var offhand = caster.getItemInHand(InteractionHand.OFF_HAND); - if (!offhand.isEmpty()) { - out.add(offhand); - } - } else { - var offhand = caster.getItemInHand(HexUtils.otherHand(castingHand)); - if (!offhand.isEmpty()) { - out.add(offhand); - } - } - - // If we're casting from the main hand, try to pick from the slot one to the right of the selected slot - // Otherwise, scan the hotbar left to right - var anchorSlot = castingHand != InteractionHand.OFF_HAND - ? (caster.getInventory().selected + 1) % 9 - : 0; - - - for (int delta = 0; delta < 9; delta++) { - var slot = (anchorSlot + delta) % 9; - out.add(caster.getInventory().getItem(slot)); - } - - yield out; - } - case EXTRACTION -> { - // https://wiki.vg/Inventory is WRONG - // slots 0-8 are the hotbar - // for what purpose i cannot imagine - // http://redditpublic.com/images/b/b2/Items_slot_number.png looks right - // and offhand is 150 Inventory.java:464 - var out = new ArrayList<ItemStack>(); - - // First, the inventory backwards - // We use inv.items here to get the main inventory, but not offhand or armor - Inventory inv = caster.getInventory(); - for (int i = inv.items.size() - 1; i >= 0; i--) { - if (i != inv.selected) { - out.add(inv.items.get(i)); - } - } - - // then the offhand, then the selected hand - out.addAll(inv.offhand); - out.add(inv.getSelected()); - - yield out; - } - }; - } - - /** - * Get the primary/secondary item stacks this env can use (i.e. main hand and offhand for the player). - */ - protected abstract List<HeldItemInfo> getPrimaryStacks(); - - protected List<HeldItemInfo> getPrimaryStacksForPlayer(InteractionHand castingHand, ServerPlayer caster) { - var primaryItem = caster.getItemInHand(castingHand); - - if (primaryItem.isEmpty()) - primaryItem = ItemStack.EMPTY.copy(); - - var secondaryItem = caster.getItemInHand(HexUtils.otherHand(castingHand)); - - if (secondaryItem.isEmpty()) - secondaryItem = ItemStack.EMPTY.copy(); - - return List.of(new HeldItemInfo(secondaryItem, HexUtils.otherHand(castingHand)), new HeldItemInfo(primaryItem, - castingHand)); - } - - /** - * Return the slot from which to take blocks and items. - */ - @Nullable - public ItemStack queryForMatchingStack(Predicate<ItemStack> stackOk) { - var stacks = this.getUsableStacks(StackDiscoveryMode.QUERY); - for (ItemStack stack : stacks) { - if (stackOk.test(stack)) { - return stack; - } - } - - return null; - } - - public record HeldItemInfo(ItemStack stack, @Nullable InteractionHand hand) { - public ItemStack component1() { - return stack; - } - - public @Nullable InteractionHand component2() { - return hand; - } - } - - /** - * Return the slot from which to take blocks and items. - */ - // TODO winfy: resolve the null here - public @Nullable HeldItemInfo getHeldItemToOperateOn(Predicate<ItemStack> stackOk) { - var stacks = this.getPrimaryStacks(); - for (HeldItemInfo stack : stacks) { - if (stackOk.test(stack.stack)) { - return stack; - } - } - - return null; - } - - /** - * Whether to provide infinite items. - */ - protected boolean isCreativeMode() { - return false; - } - - /** - * Attempt to withdraw some number of items from stacks available. - * <p> - * Return whether it was successful. - */ - public boolean withdrawItem(Predicate<ItemStack> stackOk, int count, boolean actuallyRemove) { - if (this.isCreativeMode()) { - return true; - } - - var stacks = this.getUsableStacks(StackDiscoveryMode.EXTRACTION); - - var presentCount = 0; - var matches = new ArrayList<ItemStack>(); - for (ItemStack stack : stacks) { - if (stackOk.test(stack)) { - presentCount += stack.getCount(); - matches.add(stack); - - if (presentCount >= count) - break; - } - } - if (presentCount < count) { - return false; - } - - if (!actuallyRemove) { - return true; - } // Otherwise do the removal - - var remaining = count; - for (ItemStack match : matches) { - var toWithdraw = Math.min(match.getCount(), remaining); - match.shrink(toWithdraw); - - remaining -= toWithdraw; - if (remaining <= 0) { - return true; - } - } - - throw new IllegalStateException("unreachable"); - } - - /** - * Attempt to replace the first stack found which matches the predicate with the stack to replace with. - * @return whether it was successful. - */ - public abstract boolean replaceItem(Predicate<ItemStack> stackOk, ItemStack replaceWith, @Nullable InteractionHand hand); - - - public boolean replaceItemForPlayer(Predicate<ItemStack> stackOk, ItemStack replaceWith, @Nullable InteractionHand hand, ServerPlayer caster) { - if (caster == null) - return false; - - if (hand != null && stackOk.test(caster.getItemInHand(hand))) { - caster.setItemInHand(hand, replaceWith); - return true; - } - - Inventory inv = caster.getInventory(); - for (int i = inv.items.size() - 1; i >= 0; i--) { - if (i != inv.selected) { - if (stackOk.test(inv.items.get(i))) { - inv.setItem(i, replaceWith); - return true; - } - } - } - - if (stackOk.test(caster.getItemInHand(getOtherHand()))) { - caster.setItemInHand(getOtherHand(), replaceWith); - return true; - } - if (stackOk.test(caster.getItemInHand(getCastingHand()))) { - caster.setItemInHand(getCastingHand(), replaceWith); - return true; - } - - return false; - } - - /** - * The order/mode stacks should be discovered in - */ - protected enum StackDiscoveryMode { - /** - * When finding items to pick (hotbar) - */ - QUERY, - /** - * When extracting things - */ - EXTRACTION, - } - - public abstract FrozenPigment getPigment(); - - public abstract @Nullable FrozenPigment setPigment(@Nullable FrozenPigment pigment); - - public abstract void produceParticles(ParticleSpray particles, FrozenPigment colorizer); - - public abstract void printMessage(Component message); + /** Stores all listeners that should be notified whenever a CastingEnvironment is initialised. */ + private static final List<BiConsumer<CastingEnvironment, CompoundTag>> createEventListeners = + new ArrayList<>(); + + /** Add a listener that will be called whenever a new CastingEnvironment is created. */ + public static void addCreateEventListener(BiConsumer<CastingEnvironment, CompoundTag> listener) { + createEventListeners.add(listener); + } + + /** + * Add a listener that will be called whenever a new CastingEnvironment is created (legacy). + * + * @deprecated replaced by {@link #addCreateEventListener(BiConsumer)} + */ + @Deprecated(since = "0.11.0-pre-660") + public static void addCreateEventListener(Consumer<CastingEnvironment> listener) { + createEventListeners.add( + (env, data) -> { + listener.accept(env); + }); + } + + private boolean createEventTriggered = false; + + public final void triggerCreateEvent(CompoundTag userData) { + if (!createEventTriggered) { + for (var listener : createEventListeners) listener.accept(this, userData); + createEventTriggered = true; + } + } + + protected final ServerLevel world; + + protected Map<CastingEnvironmentComponent.Key<?>, @NotNull CastingEnvironmentComponent> + componentMap = new HashMap<>(); + private final List<PostExecution> postExecutions = new ArrayList<>(); + + private final List<PostCast> postCasts = new ArrayList<>(); + private final List<ExtractMedia.Pre> preMediaExtract = new ArrayList<>(); + private final List<ExtractMedia.Post> postMediaExtract = new ArrayList<>(); + + private final List<IsVecInRange> isVecInRanges = new ArrayList<>(); + private final List<HasEditPermissionsAt> hasEditPermissionsAts = new ArrayList<>(); + + protected CastingEnvironment(ServerLevel world) { + this.world = world; + } + + public final ServerLevel getWorld() { + return this.world; + } + + public int maxOpCount() { + return HexConfig.server().maxOpCount(); + } + + /** + * Get the caster. Might be null! + * + * <p>Implementations should NOT rely on this in general, use the methods on this class instead. + * This is mostly for spells (flight, etc) + * + * @deprecated as of build 0.11.1-7-pre-619 you are recommended to use {@link #getCastingEntity} + */ + @Deprecated(since = "0.11.1-7-pre-619") + @Nullable public ServerPlayer getCaster() { + return getCastingEntity() instanceof ServerPlayer sp ? sp : null; + } + ; + + /** + * Gets the caster. Can be null if {@link #getCaster()} is also null + * + * @return the entity casting + */ + @Nullable public abstract LivingEntity getCastingEntity(); + + /** Get an interface used to do mishaps */ + public abstract MishapEnvironment getMishapEnvironment(); + + public <T extends CastingEnvironmentComponent> void addExtension(@NotNull T extension) { + componentMap.put(extension.getKey(), extension); + if (extension instanceof PostExecution postExecution) postExecutions.add(postExecution); + if (extension instanceof PostCast postCast) postCasts.add(postCast); + if (extension instanceof ExtractMedia extractMedia) + if (extension instanceof ExtractMedia.Pre pre) { + preMediaExtract.add(pre); + } else if (extension instanceof ExtractMedia.Post post) { + postMediaExtract.add(post); + } + if (extension instanceof IsVecInRange isVecInRange) isVecInRanges.add(isVecInRange); + if (extension instanceof HasEditPermissionsAt hasEditPermissionsAt) + hasEditPermissionsAts.add(hasEditPermissionsAt); + } + + public void removeExtension(@NotNull CastingEnvironmentComponent.Key<?> key) { + var extension = componentMap.remove(key); + if (extension == null) return; + + if (extension instanceof PostExecution postExecution) postExecutions.remove(postExecution); + if (extension instanceof PostCast postCast) postCasts.remove(postCast); + if (extension instanceof ExtractMedia extractMedia) + if (extension instanceof ExtractMedia.Pre pre) { + preMediaExtract.remove(pre); + } else if (extension instanceof ExtractMedia.Post post) { + postMediaExtract.remove(post); + } + if (extension instanceof IsVecInRange isVecInRange) isVecInRanges.remove(isVecInRange); + if (extension instanceof HasEditPermissionsAt hasEditPermissionsAt) + hasEditPermissionsAts.remove(hasEditPermissionsAt); + } + + @Nullable @SuppressWarnings("unchecked") + public <T extends CastingEnvironmentComponent> T getExtension( + @NotNull CastingEnvironmentComponent.Key<T> key) { + return (T) componentMap.get(key); + } + + /** + * If something about this ARE itself is invalid, mishap. + * + * <p>This is used for stuff like requiring enlightenment and pattern denylists + */ + public void precheckAction(PatternShapeMatch match) throws Mishap { + // TODO: this doesn't let you select special handlers. + // Might be worth making a "no casting" tag on each thing + ResourceLocation key = actionKey(match); + + if (!HexConfig.server().isActionAllowed(key)) { + throw new MishapDisallowedSpell(); + } + } + + @Nullable protected ResourceLocation actionKey(PatternShapeMatch match) { + ResourceLocation key; + if (match instanceof PatternShapeMatch.Normal normal) { + key = normal.key.location(); + } else if (match instanceof PatternShapeMatch.PerWorld perWorld) { + key = perWorld.key.location(); + } else if (match instanceof PatternShapeMatch.Special special) { + key = special.key.location(); + } else { + key = null; + } + return key; + } + + /** Do whatever you like after a pattern is executed. */ + public void postExecution(CastResult result) { + for (var postExecutionComponent : postExecutions) + postExecutionComponent.onPostExecution(result); + } + + /** + * Do things after the whole cast is finished (i.e. every pattern to be executed has been + * executed). + */ + public void postCast(CastingImage image) { + for (var postCastComponent : postCasts) postCastComponent.onPostCast(image); + } + + public abstract Vec3 mishapSprayPos(); + + /** Return whether this env can cast great spells. */ + public boolean isEnlightened() { + var adv = this.world.getServer().getAdvancements().getAdvancement(modLoc("enlightenment")); + if (adv == null) return false; + + var caster = this.getCastingEntity(); + if (caster instanceof ServerPlayer player) + return player.getAdvancements().getOrStartProgress(adv).isDone(); + + return false; + } + + /** + * Attempt to extract the given amount of media. Returns the amount of media left in the cost. + * + * <p>If there was enough media found, it will return less or equal to zero; if there wasn't, it + * will be positive. + */ + public long extractMedia(long cost, boolean simulate) { + for (var extractMediaComponent : preMediaExtract) + cost = extractMediaComponent.onExtractMedia(cost, simulate); + cost = extractMediaEnvironment(cost, simulate); + for (var extractMediaComponent : postMediaExtract) + cost = extractMediaComponent.onExtractMedia(cost, simulate); + return cost; + } + + /** + * Attempt to extract the given amount of media. Returns the amount of media left in the cost. + * + * <p>If there was enough media found, it will return less or equal to zero; if there wasn't, it + * will be positive. + */ + protected abstract long extractMediaEnvironment(long cost, boolean simulate); + + /** + * Get if the vec is close enough, to the player or sentinel ... + * + * <p>Doesn't take into account being out of the <em>world</em>. + */ + public boolean isVecInRange(Vec3 vec) { + boolean isInRange = isVecInRangeEnvironment(vec); + for (var isVecInRangeComponent : isVecInRanges) + isInRange = isVecInRangeComponent.onIsVecInRange(vec, isInRange); + return isInRange; + } + + /** + * Get if the vec is close enough, to the player or sentinel ... + * + * <p>Doesn't take into account being out of the <em>world</em>. + */ + protected abstract boolean isVecInRangeEnvironment(Vec3 vec); + + /** + * Return whether the caster can edit blocks at the given permission (i.e. not adventure mode, + * etc.) + */ + public boolean hasEditPermissionsAt(BlockPos pos) { + boolean hasEditPermissionsAt = hasEditPermissionsAtEnvironment(pos); + for (var hasEditPermissionsAtComponent : hasEditPermissionsAts) + hasEditPermissionsAt = + hasEditPermissionsAtComponent.onHasEditPermissionsAt(pos, hasEditPermissionsAt); + return hasEditPermissionsAt; + } + + /** + * Return whether the caster can edit blocks at the given permission (i.e. not adventure mode, + * etc.) + */ + protected abstract boolean hasEditPermissionsAtEnvironment(BlockPos pos); + + public final boolean isVecInWorld(Vec3 vec) { + return this.world.isInWorldBounds(BlockPos.containing(vec)) + && this.world.getWorldBorder().isWithinBounds(vec.x, vec.z, 0.5); + } + + public final boolean isVecInAmbit(Vec3 vec) { + return this.isVecInRange(vec) && this.isVecInWorld(vec); + } + + public final boolean isEntityInRange(Entity e) { + return (e instanceof Player && HexConfig.server().trueNameHasAmbit()) + || (this.isVecInWorld(e.position()) && this.isVecInRange(e.position())); + } + + /** Convenience function to throw if the vec is out of the caster's range or the world */ + public final void assertVecInRange(Vec3 vec) throws MishapBadLocation { + this.assertVecInWorld(vec); + if (!this.isVecInRange(vec)) { + throw new MishapBadLocation(vec, "too_far"); + } + } + + public final void assertPosInRange(BlockPos vec) throws MishapBadLocation { + this.assertVecInRange(new Vec3(vec.getX(), vec.getY(), vec.getZ())); + } + + public final void assertPosInRangeForEditing(BlockPos vec) throws MishapBadLocation { + this.assertVecInRange(new Vec3(vec.getX(), vec.getY(), vec.getZ())); + if (!this.canEditBlockAt(vec)) throw new MishapBadLocation(Vec3.atCenterOf(vec), "forbidden"); + } + + public final boolean canEditBlockAt(BlockPos vec) { + return this.isVecInRange(Vec3.atCenterOf(vec)) && this.hasEditPermissionsAt(vec); + } + + /** Convenience function to throw if the entity is out of the caster's range or the world */ + public final void assertEntityInRange(Entity e) throws MishapEntityTooFarAway { + if (e instanceof ServerPlayer && HexConfig.server().trueNameHasAmbit()) { + return; + } + if (!this.isVecInWorld(e.position())) { + throw new MishapEntityTooFarAway(e); + } + if (!this.isVecInRange(e.position())) { + throw new MishapEntityTooFarAway(e); + } + } + + /** Convenience function to throw if the vec is out of the world (for GTP) */ + public final void assertVecInWorld(Vec3 vec) throws MishapBadLocation { + if (!this.isVecInWorld(vec)) { + throw new MishapBadLocation(vec, "out_of_world"); + } + } + + public abstract InteractionHand getCastingHand(); + + public InteractionHand getOtherHand() { + return HexUtils.otherHand(this.getCastingHand()); + } + + /** Get all the item stacks this env can use. */ + protected abstract List<ItemStack> getUsableStacks(StackDiscoveryMode mode); + + protected List<ItemStack> getUsableStacksForPlayer( + StackDiscoveryMode mode, @Nullable InteractionHand castingHand, ServerPlayer caster) { + return switch (mode) { + case QUERY -> { + var out = new ArrayList<ItemStack>(); + + if (castingHand == null) { + var mainhand = caster.getItemInHand(InteractionHand.MAIN_HAND); + if (!mainhand.isEmpty()) { + out.add(mainhand); + } + + var offhand = caster.getItemInHand(InteractionHand.OFF_HAND); + if (!offhand.isEmpty()) { + out.add(offhand); + } + } else { + var offhand = caster.getItemInHand(HexUtils.otherHand(castingHand)); + if (!offhand.isEmpty()) { + out.add(offhand); + } + } + + // If we're casting from the main hand, try to pick from the slot one to the right of the + // selected slot + // Otherwise, scan the hotbar left to right + var anchorSlot = + castingHand != InteractionHand.OFF_HAND ? (caster.getInventory().selected + 1) % 9 : 0; + + for (int delta = 0; delta < 9; delta++) { + var slot = (anchorSlot + delta) % 9; + out.add(caster.getInventory().getItem(slot)); + } + + yield out; + } + case EXTRACTION -> { + // https://wiki.vg/Inventory is WRONG + // slots 0-8 are the hotbar + // for what purpose i cannot imagine + // http://redditpublic.com/images/b/b2/Items_slot_number.png looks right + // and offhand is 150 Inventory.java:464 + var out = new ArrayList<ItemStack>(); + + // First, the inventory backwards + // We use inv.items here to get the main inventory, but not offhand or armor + Inventory inv = caster.getInventory(); + for (int i = inv.items.size() - 1; i >= 0; i--) { + if (i != inv.selected) { + out.add(inv.items.get(i)); + } + } + + // then the offhand, then the selected hand + out.addAll(inv.offhand); + out.add(inv.getSelected()); + + yield out; + } + }; + } + + /** + * Get the primary/secondary item stacks this env can use (i.e. main hand and offhand for the + * player). + */ + protected abstract List<HeldItemInfo> getPrimaryStacks(); + + protected List<HeldItemInfo> getPrimaryStacksForPlayer( + InteractionHand castingHand, ServerPlayer caster) { + var primaryItem = caster.getItemInHand(castingHand); + + if (primaryItem.isEmpty()) primaryItem = ItemStack.EMPTY.copy(); + + var secondaryItem = caster.getItemInHand(HexUtils.otherHand(castingHand)); + + if (secondaryItem.isEmpty()) secondaryItem = ItemStack.EMPTY.copy(); + + return List.of( + new HeldItemInfo(secondaryItem, HexUtils.otherHand(castingHand)), + new HeldItemInfo(primaryItem, castingHand)); + } + + /** Return the slot from which to take blocks and items. */ + @Nullable public ItemStack queryForMatchingStack(Predicate<ItemStack> stackOk) { + var stacks = this.getUsableStacks(StackDiscoveryMode.QUERY); + for (ItemStack stack : stacks) { + if (stackOk.test(stack)) { + return stack; + } + } + + return null; + } + + public record HeldItemInfo(ItemStack stack, @Nullable InteractionHand hand) { + public ItemStack component1() { + return stack; + } + + public @Nullable InteractionHand component2() { + return hand; + } + } + + /** Return the slot from which to take blocks and items. */ + // TODO winfy: resolve the null here + public @Nullable HeldItemInfo getHeldItemToOperateOn(Predicate<ItemStack> stackOk) { + var stacks = this.getPrimaryStacks(); + for (HeldItemInfo stack : stacks) { + if (stackOk.test(stack.stack)) { + return stack; + } + } + + return null; + } + + /** Whether to provide infinite items. */ + protected boolean isCreativeMode() { + return false; + } + + /** + * Attempt to withdraw some number of items from stacks available. + * + * <p>Return whether it was successful. + */ + public boolean withdrawItem(Predicate<ItemStack> stackOk, int count, boolean actuallyRemove) { + if (this.isCreativeMode()) { + return true; + } + + var stacks = this.getUsableStacks(StackDiscoveryMode.EXTRACTION); + + var presentCount = 0; + var matches = new ArrayList<ItemStack>(); + for (ItemStack stack : stacks) { + if (stackOk.test(stack)) { + presentCount += stack.getCount(); + matches.add(stack); + + if (presentCount >= count) break; + } + } + if (presentCount < count) { + return false; + } + + if (!actuallyRemove) { + return true; + } // Otherwise do the removal + + var remaining = count; + for (ItemStack match : matches) { + var toWithdraw = Math.min(match.getCount(), remaining); + match.shrink(toWithdraw); + + remaining -= toWithdraw; + if (remaining <= 0) { + return true; + } + } + + throw new IllegalStateException("unreachable"); + } + + /** + * Attempt to replace the first stack found which matches the predicate with the stack to replace + * with. + * + * @return whether it was successful. + */ + public abstract boolean replaceItem( + Predicate<ItemStack> stackOk, ItemStack replaceWith, @Nullable InteractionHand hand); + + public boolean replaceItemForPlayer( + Predicate<ItemStack> stackOk, + ItemStack replaceWith, + @Nullable InteractionHand hand, + ServerPlayer caster) { + if (caster == null) return false; + + if (hand != null && stackOk.test(caster.getItemInHand(hand))) { + caster.setItemInHand(hand, replaceWith); + return true; + } + + Inventory inv = caster.getInventory(); + for (int i = inv.items.size() - 1; i >= 0; i--) { + if (i != inv.selected) { + if (stackOk.test(inv.items.get(i))) { + inv.setItem(i, replaceWith); + return true; + } + } + } + + if (stackOk.test(caster.getItemInHand(getOtherHand()))) { + caster.setItemInHand(getOtherHand(), replaceWith); + return true; + } + if (stackOk.test(caster.getItemInHand(getCastingHand()))) { + caster.setItemInHand(getCastingHand(), replaceWith); + return true; + } + + return false; + } + + /** The order/mode stacks should be discovered in */ + protected enum StackDiscoveryMode { + /** When finding items to pick (hotbar) */ + QUERY, + /** When extracting things */ + EXTRACTION, + } + + public abstract FrozenPigment getPigment(); + + public abstract @Nullable FrozenPigment setPigment(@Nullable FrozenPigment pigment); + + public abstract void produceParticles(ParticleSpray particles, FrozenPigment colorizer); + + public abstract void printMessage(Component message); } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironmentComponent.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironmentComponent.java index 73f7775a44..5558aa8934 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironmentComponent.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironmentComponent.java @@ -5,55 +5,51 @@ import net.minecraft.world.phys.Vec3; public interface CastingEnvironmentComponent { - Key<?> getKey(); - - interface Key<C extends CastingEnvironmentComponent> {} - - interface PostExecution extends CastingEnvironmentComponent { - /** - * Do whatever you like after a pattern is executed. - */ - void onPostExecution(CastResult result); - } - - interface PostCast extends CastingEnvironmentComponent { - /** - * Do things after the whole cast is finished (i.e. every pattern to be executed has been executed). - */ - void onPostCast(CastingImage image); - } - - interface ExtractMedia extends CastingEnvironmentComponent { - /** - * Receives the cost that is being extracted, should return the - * remaining cost after deducting whatever cost source this component - * is responsible for (should be >= 0) - */ - long onExtractMedia(long cost, boolean simulate); - - /** - * ExtractMedia component that extracts media BEFORE the call to {@link CastingEnvironment#extractMediaEnvironment(long, boolean)} - */ - interface Pre extends ExtractMedia {} - - /** - * ExtractMedia component that extracts media AFTER the call to {@link CastingEnvironment#extractMediaEnvironment(long, boolean)} - * if the input is <= 0 you should also probably return 0 (since media cost was already paid off) - */ - interface Post extends ExtractMedia {} - } - - interface IsVecInRange extends CastingEnvironmentComponent { - /** - * Receives the vec, and the current return value, and returns the new return value. - */ - boolean onIsVecInRange(Vec3 vec, boolean current); - } - - interface HasEditPermissionsAt extends CastingEnvironmentComponent { - /** - * Receives the vec, and the current return value, and returns the new return value. - */ - boolean onHasEditPermissionsAt(BlockPos pos, boolean current); - } + Key<?> getKey(); + + interface Key<C extends CastingEnvironmentComponent> {} + + interface PostExecution extends CastingEnvironmentComponent { + /** Do whatever you like after a pattern is executed. */ + void onPostExecution(CastResult result); + } + + interface PostCast extends CastingEnvironmentComponent { + /** + * Do things after the whole cast is finished (i.e. every pattern to be executed has been + * executed). + */ + void onPostCast(CastingImage image); + } + + interface ExtractMedia extends CastingEnvironmentComponent { + /** + * Receives the cost that is being extracted, should return the remaining cost after deducting + * whatever cost source this component is responsible for (should be >= 0) + */ + long onExtractMedia(long cost, boolean simulate); + + /** + * ExtractMedia component that extracts media BEFORE the call to {@link + * CastingEnvironment#extractMediaEnvironment(long, boolean)} + */ + interface Pre extends ExtractMedia {} + + /** + * ExtractMedia component that extracts media AFTER the call to {@link + * CastingEnvironment#extractMediaEnvironment(long, boolean)} if the input is <= 0 you should + * also probably return 0 (since media cost was already paid off) + */ + interface Post extends ExtractMedia {} + } + + interface IsVecInRange extends CastingEnvironmentComponent { + /** Receives the vec, and the current return value, and returns the new return value. */ + boolean onIsVecInRange(Vec3 vec, boolean current); + } + + interface HasEditPermissionsAt extends CastingEnvironmentComponent { + /** Receives the vec, and the current return value, and returns the new return value. */ + boolean onHasEditPermissionsAt(BlockPos pos, boolean current); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ExecutionClientView.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ExecutionClientView.kt index 3fcf1bf766..46e773a46f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ExecutionClientView.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ExecutionClientView.kt @@ -2,16 +2,13 @@ package at.petrak.hexcasting.api.casting.eval import net.minecraft.nbt.CompoundTag -/** - * Information sent back to the client - */ +/** Information sent back to the client */ data class ExecutionClientView( - val isStackClear: Boolean, - val resolutionType: ResolvedPatternType, + val isStackClear: Boolean, + val resolutionType: ResolvedPatternType, - // These must be tags so the wrapping of the text can happen on the client - // otherwise we don't know when to stop rendering - val stackDescs: List<CompoundTag>, - val ravenmind: CompoundTag?, + // These must be tags so the wrapping of the text can happen on the client + // otherwise we don't know when to stop rendering + val stackDescs: List<CompoundTag>, + val ravenmind: CompoundTag?, ) - diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/MishapEnvironment.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/MishapEnvironment.java index 5469914454..4b1125b709 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/MishapEnvironment.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/MishapEnvironment.java @@ -9,42 +9,43 @@ /** * Kinda like {@link CastingEnvironment} but for executing mishaps. - * <p> - * To avoid horrible O(mn) scope problems we offer a set of stock bad effects. - * The player is exposed nullably if you like though. + * + * <p>To avoid horrible O(mn) scope problems we offer a set of stock bad effects. The player is + * exposed nullably if you like though. */ public abstract class MishapEnvironment { - @Nullable - protected final ServerPlayer caster; - protected final ServerLevel world; + @Nullable protected final ServerPlayer caster; + protected final ServerLevel world; - protected MishapEnvironment(ServerLevel world, @Nullable ServerPlayer caster) { - this.caster = caster; - this.world = world; - } + protected MishapEnvironment(ServerLevel world, @Nullable ServerPlayer caster) { + this.caster = caster; + this.world = world; + } - public abstract void yeetHeldItemsTowards(Vec3 targetPos); + public abstract void yeetHeldItemsTowards(Vec3 targetPos); - public abstract void dropHeldItems(); + public abstract void dropHeldItems(); - public abstract void drown(); + public abstract void drown(); - public abstract void damage(float healthProportion); + public abstract void damage(float healthProportion); - public abstract void removeXp(int amount); + public abstract void removeXp(int amount); - public abstract void blind(int ticks); + public abstract void blind(int ticks); - protected void yeetItem(ItemStack stack, Vec3 srcPos, Vec3 delta) { - var entity = new ItemEntity( - this.world, - srcPos.x, srcPos.y, srcPos.z, - stack, - delta.x + (Math.random() - 0.5) * 0.1, - delta.y + (Math.random() - 0.5) * 0.1, - delta.z + (Math.random() - 0.5) * 0.1 - ); - entity.setPickUpDelay(40); - this.world.addWithUUID(entity); - } + protected void yeetItem(ItemStack stack, Vec3 srcPos, Vec3 delta) { + var entity = + new ItemEntity( + this.world, + srcPos.x, + srcPos.y, + srcPos.z, + stack, + delta.x + (Math.random() - 0.5) * 0.1, + delta.y + (Math.random() - 0.5) * 0.1, + delta.z + (Math.random() - 0.5) * 0.1); + entity.setPickUpDelay(40); + this.world.addWithUUID(entity); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/OperationResult.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/OperationResult.kt index 3a0f066fbc..2a5673c0a1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/OperationResult.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/OperationResult.kt @@ -5,12 +5,10 @@ import at.petrak.hexcasting.api.casting.eval.sideeffects.OperatorSideEffect import at.petrak.hexcasting.api.casting.eval.vm.CastingImage import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation -/** - * What happens when an operator is through? - */ +/** What happens when an operator is through? */ data class OperationResult( - val newImage: CastingImage, - val sideEffects: List<OperatorSideEffect>, - val newContinuation: SpellContinuation, - val sound: EvalSound, + val newImage: CastingImage, + val sideEffects: List<OperatorSideEffect>, + val newContinuation: SpellContinuation, + val sound: EvalSound, ) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ResolvedPattern.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ResolvedPattern.kt index 6108850727..035977e253 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ResolvedPattern.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ResolvedPattern.kt @@ -3,25 +3,28 @@ package at.petrak.hexcasting.api.casting.eval import at.petrak.hexcasting.api.casting.math.HexCoord import at.petrak.hexcasting.api.casting.math.HexPattern import at.petrak.hexcasting.api.utils.NBTBuilder -import net.minecraft.nbt.CompoundTag import java.util.* +import net.minecraft.nbt.CompoundTag +data class ResolvedPattern( + val pattern: HexPattern, + val origin: HexCoord, + var type: ResolvedPatternType +) { + fun serializeToNBT() = NBTBuilder { + "Pattern" %= pattern.serializeToNBT() + "OriginQ" %= origin.q + "OriginR" %= origin.r + "Valid" %= type.name.lowercase(Locale.ROOT) + } -data class ResolvedPattern(val pattern: HexPattern, val origin: HexCoord, var type: ResolvedPatternType) { - fun serializeToNBT() = NBTBuilder { - "Pattern" %= pattern.serializeToNBT() - "OriginQ" %= origin.q - "OriginR" %= origin.r - "Valid" %= type.name.lowercase(Locale.ROOT) - } - - companion object { - @JvmStatic - fun fromNBT(tag: CompoundTag): ResolvedPattern { - val pattern = HexPattern.fromNBT(tag.getCompound("Pattern")) - val origin = HexCoord(tag.getInt("OriginQ"), tag.getInt("OriginR")) - val valid = ResolvedPatternType.fromString(tag.getString("Valid")) - return ResolvedPattern(pattern, origin, valid) - } - } + companion object { + @JvmStatic + fun fromNBT(tag: CompoundTag): ResolvedPattern { + val pattern = HexPattern.fromNBT(tag.getCompound("Pattern")) + val origin = HexCoord(tag.getInt("OriginQ"), tag.getInt("OriginR")) + val valid = ResolvedPatternType.fromString(tag.getString("Valid")) + return ResolvedPattern(pattern, origin, valid) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ResolvedPatternType.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ResolvedPatternType.kt index 8e332bb802..433332f7b0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ResolvedPatternType.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ResolvedPatternType.kt @@ -3,17 +3,17 @@ package at.petrak.hexcasting.api.casting.eval import at.petrak.hexcasting.api.utils.getSafe enum class ResolvedPatternType(val color: Int, val fadeColor: Int, val success: Boolean) { - UNRESOLVED(0x7f7f7f, 0xcccccc, false), - EVALUATED(0x7385de, 0xfecbe6, true), - ESCAPED(0xddcc73, 0xfffae5, true), - UNDONE(0xb26b6b, 0xcca88e, true), // TODO: Pick better colours - ERRORED(0xde6262, 0xffc7a0, false), - INVALID(0xb26b6b, 0xcca88e, false); + UNRESOLVED(0x7f7f7f, 0xcccccc, false), + EVALUATED(0x7385de, 0xfecbe6, true), + ESCAPED(0xddcc73, 0xfffae5, true), + UNDONE(0xb26b6b, 0xcca88e, true), // TODO: Pick better colours + ERRORED(0xde6262, 0xffc7a0, false), + INVALID(0xb26b6b, 0xcca88e, false); - companion object { - @JvmStatic - fun fromString(key: String): ResolvedPatternType { - return values().getSafe(key) - } - } + companion object { + @JvmStatic + fun fromString(key: String): ResolvedPatternType { + return values().getSafe(key) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/SpecialPatterns.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/SpecialPatterns.java index f87fcfdfae..75d6a8bd10 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/SpecialPatterns.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/SpecialPatterns.java @@ -4,9 +4,9 @@ import at.petrak.hexcasting.api.casting.math.HexPattern; public final class SpecialPatterns { - public static final HexPattern INTROSPECTION = HexPattern.fromAngles("qqq", HexDir.WEST); - public static final HexPattern RETROSPECTION = HexPattern.fromAngles("eee", HexDir.EAST); - public static final HexPattern CONSIDERATION = HexPattern.fromAngles("qqqaw", HexDir.WEST); + public static final HexPattern INTROSPECTION = HexPattern.fromAngles("qqq", HexDir.WEST); + public static final HexPattern RETROSPECTION = HexPattern.fromAngles("eee", HexDir.EAST); + public static final HexPattern CONSIDERATION = HexPattern.fromAngles("qqqaw", HexDir.WEST); - public static final HexPattern EVANITION = HexPattern.fromAngles("eeedw", HexDir.EAST); + public static final HexPattern EVANITION = HexPattern.fromAngles("eeedw", HexDir.EAST); } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/SpellCircleContext.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/SpellCircleContext.kt index 269d6465c4..eaf7c9771b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/SpellCircleContext.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/SpellCircleContext.kt @@ -5,52 +5,58 @@ import net.minecraft.core.BlockPos import net.minecraft.nbt.CompoundTag import net.minecraft.world.phys.AABB -/** - * Optional field on a [CastingEnvironment] for the spell circle - */ -data class SpellCircleContext(val impetusPos: BlockPos, val aabb: AABB, val activatorAlwaysInRange: Boolean) { - fun serializeToNBT() = NBTBuilder { - TAG_IMPETUS_X %= impetusPos.x - TAG_IMPETUS_Y %= impetusPos.y - TAG_IMPETUS_Z %= impetusPos.z - - TAG_MIN_X %= aabb.minX - TAG_MIN_Y %= aabb.minY - TAG_MIN_Z %= aabb.minZ - TAG_MAX_X %= aabb.maxX - TAG_MAX_Y %= aabb.maxY - TAG_MAX_Z %= aabb.maxZ - - TAG_PLAYER_ALWAYS_IN_RANGE %= activatorAlwaysInRange - } - - companion object { - const val TAG_IMPETUS_X = "impetus_x" - const val TAG_IMPETUS_Y = "impetus_y" - const val TAG_IMPETUS_Z = "impetus_z" - const val TAG_MIN_X = "min_x" - const val TAG_MIN_Y = "min_y" - const val TAG_MIN_Z = "min_z" - const val TAG_MAX_X = "max_x" - const val TAG_MAX_Y = "max_y" - const val TAG_MAX_Z = "max_z" - const val TAG_PLAYER_ALWAYS_IN_RANGE = "player_always_in_range" - - fun fromNBT(tag: CompoundTag): SpellCircleContext { - val impX = tag.getInt(TAG_IMPETUS_X) - val impY = tag.getInt(TAG_IMPETUS_Y) - val impZ = tag.getInt(TAG_IMPETUS_Z) - - val minX = tag.getDouble(TAG_MIN_X) - val minY = tag.getDouble(TAG_MIN_Y) - val minZ = tag.getDouble(TAG_MIN_Z) - val maxX = tag.getDouble(TAG_MAX_X) - val maxY = tag.getDouble(TAG_MAX_Y) - val maxZ = tag.getDouble(TAG_MAX_Z) - - val playerAIR = tag.getBoolean(TAG_PLAYER_ALWAYS_IN_RANGE) - - return SpellCircleContext(BlockPos(impX, impY, impZ), AABB(minX, minY, minZ, maxX, maxY, maxZ), playerAIR) - } - } +/** Optional field on a [CastingEnvironment] for the spell circle */ +data class SpellCircleContext( + val impetusPos: BlockPos, + val aabb: AABB, + val activatorAlwaysInRange: Boolean +) { + fun serializeToNBT() = NBTBuilder { + TAG_IMPETUS_X %= impetusPos.x + TAG_IMPETUS_Y %= impetusPos.y + TAG_IMPETUS_Z %= impetusPos.z + + TAG_MIN_X %= aabb.minX + TAG_MIN_Y %= aabb.minY + TAG_MIN_Z %= aabb.minZ + TAG_MAX_X %= aabb.maxX + TAG_MAX_Y %= aabb.maxY + TAG_MAX_Z %= aabb.maxZ + + TAG_PLAYER_ALWAYS_IN_RANGE %= activatorAlwaysInRange + } + + companion object { + const val TAG_IMPETUS_X = "impetus_x" + const val TAG_IMPETUS_Y = "impetus_y" + const val TAG_IMPETUS_Z = "impetus_z" + const val TAG_MIN_X = "min_x" + const val TAG_MIN_Y = "min_y" + const val TAG_MIN_Z = "min_z" + const val TAG_MAX_X = "max_x" + const val TAG_MAX_Y = "max_y" + const val TAG_MAX_Z = "max_z" + const val TAG_PLAYER_ALWAYS_IN_RANGE = "player_always_in_range" + + fun fromNBT(tag: CompoundTag): SpellCircleContext { + val impX = tag.getInt(TAG_IMPETUS_X) + val impY = tag.getInt(TAG_IMPETUS_Y) + val impZ = tag.getInt(TAG_IMPETUS_Z) + + val minX = tag.getDouble(TAG_MIN_X) + val minY = tag.getDouble(TAG_MIN_Y) + val minZ = tag.getDouble(TAG_MIN_Z) + val maxX = tag.getDouble(TAG_MAX_X) + val maxY = tag.getDouble(TAG_MAX_Y) + val maxZ = tag.getDouble(TAG_MAX_Z) + + val playerAIR = tag.getBoolean(TAG_PLAYER_ALWAYS_IN_RANGE) + + return SpellCircleContext( + BlockPos(impX, impY, impZ), + AABB(minX, minY, minZ, maxX, maxY, maxZ), + playerAIR + ) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/CircleCastEnv.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/CircleCastEnv.java index d1d542780d..230c930b4c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/CircleCastEnv.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/CircleCastEnv.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.api.casting.eval.env; +import static at.petrak.hexcasting.api.casting.eval.env.PlayerBasedCastEnv.SENTINEL_RADIUS; + import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.casting.ParticleSpray; import at.petrak.hexcasting.api.casting.PatternShapeMatch; @@ -13,6 +15,9 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapDisallowedSpell; import at.petrak.hexcasting.api.mod.HexConfig; import at.petrak.hexcasting.api.pigment.FrozenPigment; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; @@ -25,198 +30,186 @@ import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Predicate; - -import static at.petrak.hexcasting.api.casting.eval.env.PlayerBasedCastEnv.SENTINEL_RADIUS; - public class CircleCastEnv extends CastingEnvironment { - protected final CircleExecutionState execState; - - public CircleCastEnv(ServerLevel world, CircleExecutionState execState) { - super(world); - this.execState = execState; - } - - @Override - public @Nullable LivingEntity getCastingEntity() { - return this.execState.getCaster(this.world); - } - - @Override - public @Nullable ServerPlayer getCaster() { - return this.execState.getCaster(this.world); - } - - public @Nullable BlockEntityAbstractImpetus getImpetus() { - var entity = this.world.getBlockEntity(execState.impetusPos); - - if (entity instanceof BlockEntityAbstractImpetus) - return (BlockEntityAbstractImpetus) entity; - return null; - } - - public CircleExecutionState circleState() { - return execState; - } - - @Override - public MishapEnvironment getMishapEnvironment() { - return new CircleMishapEnv(this.world, this.execState); - } - - @Override - public void precheckAction(PatternShapeMatch match) throws Mishap { - super.precheckAction(match); - - ResourceLocation key = actionKey(match); - - if (!HexConfig.server().isActionAllowedInCircles(key)) { - throw new MishapDisallowedSpell("disallowed_circle"); - } - } - - @Override - public void postExecution(CastResult result) { - super.postExecution(result); - - // we always want to play this sound one at a time - var sound = result.getSound().sound(); - if (sound != null) { - var soundPos = this.execState.currentPos; - this.world.playSound(null, soundPos, sound, SoundSource.PLAYERS, 1f, 1f); - } - - // TODO: this is gonna bite us in the bum someday - // we check whether we should cut the execution in BlockSlate, but post the mishap here; - // although everything should be pretty immutable here it's something to keep in mind - // classic time-of-check/time-of-use - var imp = this.getImpetus(); - if (imp != null) { - for (var sideEffect : result.getSideEffects()) { - if (sideEffect instanceof OperatorSideEffect.DoMishap doMishap) { - var msg = doMishap.getMishap().errorMessageWithName(this, doMishap.getErrorCtx()); - if (msg != null) { - imp.postMishap(msg); - } - } - } - } - } - - @Override - public Vec3 mishapSprayPos() { - return Vec3.atCenterOf(this.execState.currentPos); - } - - @Override - public long extractMediaEnvironment(long cost, boolean simulate) { - var entity = this.getImpetus(); - if (entity == null) - return cost; - - var mediaAvailable = entity.getMedia(); - if (mediaAvailable < 0) - return 0; - - long mediaToTake = Math.min(cost, mediaAvailable); - cost -= mediaToTake; - if (!simulate) { - entity.setMedia(mediaAvailable - mediaToTake); - } - - return cost; - } - - @Override - public boolean isVecInRangeEnvironment(Vec3 vec) { - var caster = this.execState.getCaster(this.world); - if (caster != null) { - if (vec.distanceToSqr(caster.position()) <= caster.getBbHeight() * caster.getBbHeight()) { - return true; - } - - var sentinel = HexAPI.instance().getSentinel(caster); - if (sentinel != null - && sentinel.extendsRange() - && caster.level().dimension() == sentinel.dimension() - && vec.distanceToSqr(sentinel.position()) <= SENTINEL_RADIUS * SENTINEL_RADIUS + 0.00000000001 - ) { - return true; - } - } - - return this.execState.bounds.contains(vec); - } - - @Override - public boolean isEnlightened() { - // have unbound circles be enlightened. - if(getCastingEntity() == null) return true; - return super.isEnlightened(); - } - - @Override - public boolean hasEditPermissionsAtEnvironment(BlockPos pos) { - return true; - } - - @Override - public InteractionHand getCastingHand() { - return InteractionHand.MAIN_HAND; - } - - @Override - // TODO: Could do something like get items in inventories adjacent to the circle? - protected List<ItemStack> getUsableStacks(StackDiscoveryMode mode) { - if (this.getCaster() != null) - return getUsableStacksForPlayer(mode, null, this.getCaster()); - return new ArrayList<>(); - } - - @Override - // TODO: Adjacent inv! - protected List<HeldItemInfo> getPrimaryStacks() { - if (this.getCaster() != null) - return getPrimaryStacksForPlayer(InteractionHand.OFF_HAND, this.getCaster()); - return List.of(); - } - - @Override - // TODO: Adjacent inv! - public boolean replaceItem(Predicate<ItemStack> stackOk, ItemStack replaceWith, @Nullable InteractionHand hand) { - if (this.getCaster() != null) - return replaceItemForPlayer(stackOk, replaceWith, hand, this.getCaster()); - return false; - } - - @Override - public FrozenPigment getPigment() { - var impetus = this.getImpetus(); - if (impetus == null) - return FrozenPigment.DEFAULT.get(); - return impetus.getPigment(); - } - - @Override - public @Nullable FrozenPigment setPigment(@Nullable FrozenPigment pigment) { - var impetus = this.getImpetus(); - if (impetus == null) - return null; - return impetus.setPigment(pigment); - } - - @Override - public void produceParticles(ParticleSpray particles, FrozenPigment pigment) { - particles.sprayParticles(this.world, pigment); - } - - @Override - public void printMessage(Component message) { - var impetus = getImpetus(); - if (impetus == null) - return; - impetus.postPrint(message); - } + protected final CircleExecutionState execState; + + public CircleCastEnv(ServerLevel world, CircleExecutionState execState) { + super(world); + this.execState = execState; + } + + @Override + public @Nullable LivingEntity getCastingEntity() { + return this.execState.getCaster(this.world); + } + + @Override + public @Nullable ServerPlayer getCaster() { + return this.execState.getCaster(this.world); + } + + public @Nullable BlockEntityAbstractImpetus getImpetus() { + var entity = this.world.getBlockEntity(execState.impetusPos); + + if (entity instanceof BlockEntityAbstractImpetus) return (BlockEntityAbstractImpetus) entity; + return null; + } + + public CircleExecutionState circleState() { + return execState; + } + + @Override + public MishapEnvironment getMishapEnvironment() { + return new CircleMishapEnv(this.world, this.execState); + } + + @Override + public void precheckAction(PatternShapeMatch match) throws Mishap { + super.precheckAction(match); + + ResourceLocation key = actionKey(match); + + if (!HexConfig.server().isActionAllowedInCircles(key)) { + throw new MishapDisallowedSpell("disallowed_circle"); + } + } + + @Override + public void postExecution(CastResult result) { + super.postExecution(result); + + // we always want to play this sound one at a time + var sound = result.getSound().sound(); + if (sound != null) { + var soundPos = this.execState.currentPos; + this.world.playSound(null, soundPos, sound, SoundSource.PLAYERS, 1f, 1f); + } + + // TODO: this is gonna bite us in the bum someday + // we check whether we should cut the execution in BlockSlate, but post the mishap here; + // although everything should be pretty immutable here it's something to keep in mind + // classic time-of-check/time-of-use + var imp = this.getImpetus(); + if (imp != null) { + for (var sideEffect : result.getSideEffects()) { + if (sideEffect instanceof OperatorSideEffect.DoMishap doMishap) { + var msg = doMishap.getMishap().errorMessageWithName(this, doMishap.getErrorCtx()); + if (msg != null) { + imp.postMishap(msg); + } + } + } + } + } + + @Override + public Vec3 mishapSprayPos() { + return Vec3.atCenterOf(this.execState.currentPos); + } + + @Override + public long extractMediaEnvironment(long cost, boolean simulate) { + var entity = this.getImpetus(); + if (entity == null) return cost; + + var mediaAvailable = entity.getMedia(); + if (mediaAvailable < 0) return 0; + + long mediaToTake = Math.min(cost, mediaAvailable); + cost -= mediaToTake; + if (!simulate) { + entity.setMedia(mediaAvailable - mediaToTake); + } + + return cost; + } + + @Override + public boolean isVecInRangeEnvironment(Vec3 vec) { + var caster = this.execState.getCaster(this.world); + if (caster != null) { + if (vec.distanceToSqr(caster.position()) <= caster.getBbHeight() * caster.getBbHeight()) { + return true; + } + + var sentinel = HexAPI.instance().getSentinel(caster); + if (sentinel != null + && sentinel.extendsRange() + && caster.level().dimension() == sentinel.dimension() + && vec.distanceToSqr(sentinel.position()) + <= SENTINEL_RADIUS * SENTINEL_RADIUS + 0.00000000001) { + return true; + } + } + + return this.execState.bounds.contains(vec); + } + + @Override + public boolean isEnlightened() { + // have unbound circles be enlightened. + if (getCastingEntity() == null) return true; + return super.isEnlightened(); + } + + @Override + public boolean hasEditPermissionsAtEnvironment(BlockPos pos) { + return true; + } + + @Override + public InteractionHand getCastingHand() { + return InteractionHand.MAIN_HAND; + } + + @Override + // TODO: Could do something like get items in inventories adjacent to the circle? + protected List<ItemStack> getUsableStacks(StackDiscoveryMode mode) { + if (this.getCaster() != null) return getUsableStacksForPlayer(mode, null, this.getCaster()); + return new ArrayList<>(); + } + + @Override + // TODO: Adjacent inv! + protected List<HeldItemInfo> getPrimaryStacks() { + if (this.getCaster() != null) + return getPrimaryStacksForPlayer(InteractionHand.OFF_HAND, this.getCaster()); + return List.of(); + } + + @Override + // TODO: Adjacent inv! + public boolean replaceItem( + Predicate<ItemStack> stackOk, ItemStack replaceWith, @Nullable InteractionHand hand) { + if (this.getCaster() != null) + return replaceItemForPlayer(stackOk, replaceWith, hand, this.getCaster()); + return false; + } + + @Override + public FrozenPigment getPigment() { + var impetus = this.getImpetus(); + if (impetus == null) return FrozenPigment.DEFAULT.get(); + return impetus.getPigment(); + } + + @Override + public @Nullable FrozenPigment setPigment(@Nullable FrozenPigment pigment) { + var impetus = this.getImpetus(); + if (impetus == null) return null; + return impetus.setPigment(pigment); + } + + @Override + public void produceParticles(ParticleSpray particles, FrozenPigment pigment) { + particles.sprayParticles(this.world, pigment); + } + + @Override + public void printMessage(Component message) { + var impetus = getImpetus(); + if (impetus == null) return; + impetus.postPrint(message); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/CircleMishapEnv.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/CircleMishapEnv.java index 407f0eb307..17a17066d0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/CircleMishapEnv.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/CircleMishapEnv.java @@ -6,40 +6,28 @@ import net.minecraft.world.phys.Vec3; public class CircleMishapEnv extends MishapEnvironment { - protected final CircleExecutionState execState; + protected final CircleExecutionState execState; - protected CircleMishapEnv(ServerLevel world, CircleExecutionState execState) { - super(world, null); - this.execState = execState; - } + protected CircleMishapEnv(ServerLevel world, CircleExecutionState execState) { + super(world, null); + this.execState = execState; + } - @Override - public void yeetHeldItemsTowards(Vec3 targetPos) { + @Override + public void yeetHeldItemsTowards(Vec3 targetPos) {} - } + @Override + public void dropHeldItems() {} - @Override - public void dropHeldItems() { + @Override + public void drown() {} - } + @Override + public void damage(float healthProportion) {} - @Override - public void drown() { + @Override + public void removeXp(int amount) {} - } - - @Override - public void damage(float healthProportion) { - - } - - @Override - public void removeXp(int amount) { - - } - - @Override - public void blind(int ticks) { - - } + @Override + public void blind(int ticks) {} } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PackagedItemCastEnv.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PackagedItemCastEnv.java index 43d0c67d28..680ca06a2f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PackagedItemCastEnv.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PackagedItemCastEnv.java @@ -7,79 +7,74 @@ import at.petrak.hexcasting.common.lib.hex.HexEvalSounds; import at.petrak.hexcasting.common.msgs.MsgNewSpiralPatternsS2C; import at.petrak.hexcasting.xplat.IXplatAbstractions; +import java.util.List; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; -import java.util.List; - public class PackagedItemCastEnv extends PlayerBasedCastEnv { - protected EvalSound sound = HexEvalSounds.NOTHING; - - public PackagedItemCastEnv(ServerPlayer caster, InteractionHand castingHand) { - super(caster, castingHand); - } - - @Override - public void postExecution(CastResult result) { - super.postExecution(result); - - if (result.component1() instanceof PatternIota patternIota) { - var packet = new MsgNewSpiralPatternsS2C( - this.caster.getUUID(), List.of(patternIota.getPattern()), 140 - ); - IXplatAbstractions.INSTANCE.sendPacketToPlayer(this.caster, packet); - IXplatAbstractions.INSTANCE.sendPacketTracking(this.caster, packet); - } - - // TODO: how do we know when to actually play this sound? - this.sound = this.sound.greaterOf(result.getSound()); - } - - @Override - public long extractMediaEnvironment(long costLeft, boolean simulate) { - if (this.caster.isCreative()) - return 0; - - var casterStack = this.caster.getItemInHand(this.castingHand); - var casterHexHolder = IXplatAbstractions.INSTANCE.findHexHolder(casterStack); - if (casterHexHolder == null) - return costLeft; - var canCastFromInv = casterHexHolder.canDrawMediaFromInventory(); - - var casterMediaHolder = IXplatAbstractions.INSTANCE.findMediaHolder(casterStack); - - // The contracts on the AD and on this function are different. - // ADs return the amount extracted, this wants the amount left - if (casterMediaHolder != null) { - long extracted = casterMediaHolder.withdrawMedia((int) costLeft, simulate); - costLeft -= extracted; - } - if (canCastFromInv && costLeft > 0) { - costLeft = this.extractMediaFromInventory(costLeft, this.canOvercast(), simulate); - } - - return costLeft; - } - - @Override - public InteractionHand getCastingHand() { - return this.castingHand; - } - - @Override - public FrozenPigment getPigment() { - var casterStack = this.caster.getItemInHand(this.castingHand); - var casterHexHolder = IXplatAbstractions.INSTANCE.findHexHolder(casterStack); - if (casterHexHolder == null) - return IXplatAbstractions.INSTANCE.getPigment(this.caster); - var hexHolderPigment = casterHexHolder.getPigment(); - if (hexHolderPigment != null) - return hexHolderPigment; - return IXplatAbstractions.INSTANCE.getPigment(this.caster); - } - - public EvalSound getSound() { - return sound; - } + protected EvalSound sound = HexEvalSounds.NOTHING; + + public PackagedItemCastEnv(ServerPlayer caster, InteractionHand castingHand) { + super(caster, castingHand); + } + + @Override + public void postExecution(CastResult result) { + super.postExecution(result); + + if (result.component1() instanceof PatternIota patternIota) { + var packet = + new MsgNewSpiralPatternsS2C( + this.caster.getUUID(), List.of(patternIota.getPattern()), 140); + IXplatAbstractions.INSTANCE.sendPacketToPlayer(this.caster, packet); + IXplatAbstractions.INSTANCE.sendPacketTracking(this.caster, packet); + } + + // TODO: how do we know when to actually play this sound? + this.sound = this.sound.greaterOf(result.getSound()); + } + + @Override + public long extractMediaEnvironment(long costLeft, boolean simulate) { + if (this.caster.isCreative()) return 0; + + var casterStack = this.caster.getItemInHand(this.castingHand); + var casterHexHolder = IXplatAbstractions.INSTANCE.findHexHolder(casterStack); + if (casterHexHolder == null) return costLeft; + var canCastFromInv = casterHexHolder.canDrawMediaFromInventory(); + + var casterMediaHolder = IXplatAbstractions.INSTANCE.findMediaHolder(casterStack); + + // The contracts on the AD and on this function are different. + // ADs return the amount extracted, this wants the amount left + if (casterMediaHolder != null) { + long extracted = casterMediaHolder.withdrawMedia((int) costLeft, simulate); + costLeft -= extracted; + } + if (canCastFromInv && costLeft > 0) { + costLeft = this.extractMediaFromInventory(costLeft, this.canOvercast(), simulate); + } + + return costLeft; + } + + @Override + public InteractionHand getCastingHand() { + return this.castingHand; + } + + @Override + public FrozenPigment getPigment() { + var casterStack = this.caster.getItemInHand(this.castingHand); + var casterHexHolder = IXplatAbstractions.INSTANCE.findHexHolder(casterStack); + if (casterHexHolder == null) return IXplatAbstractions.INSTANCE.getPigment(this.caster); + var hexHolderPigment = casterHexHolder.getPigment(); + if (hexHolderPigment != null) return hexHolderPigment; + return IXplatAbstractions.INSTANCE.getPigment(this.caster); + } + + public EvalSound getSound() { + return sound; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedCastEnv.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedCastEnv.java index 10ff3b052b..2b258aba7f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedCastEnv.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedCastEnv.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.api.casting.eval.env; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.addldata.ADMediaHolder; import at.petrak.hexcasting.api.advancements.HexAdvancementTriggers; @@ -12,186 +14,182 @@ import at.petrak.hexcasting.api.mod.HexConfig; import at.petrak.hexcasting.api.mod.HexStatistics; import at.petrak.hexcasting.api.pigment.FrozenPigment; -import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.MediaHelper; import at.petrak.hexcasting.common.lib.HexDamageTypes; import at.petrak.hexcasting.xplat.IXplatAbstractions; +import java.util.List; +import java.util.function.Predicate; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.GameType; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Predicate; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public abstract class PlayerBasedCastEnv extends CastingEnvironment { - public static final double AMBIT_RADIUS = 32.0; - public static final double SENTINEL_RADIUS = 16.0; - - protected final ServerPlayer caster; - protected final InteractionHand castingHand; - - protected PlayerBasedCastEnv(ServerPlayer caster, InteractionHand castingHand) { - super(caster.serverLevel()); - this.caster = caster; - this.castingHand = castingHand; - } - - @Override - public LivingEntity getCastingEntity() { - return this.caster; - } - - @Override - public ServerPlayer getCaster() { - return this.caster; - } - - @Override - public void postExecution(CastResult result) { - super.postExecution(result); - - for (var sideEffect : result.getSideEffects()) { - if (sideEffect instanceof OperatorSideEffect.DoMishap doMishap) { - this.sendMishapMsgToPlayer(doMishap); - } - } - } - - @Override - protected List<ItemStack> getUsableStacks(StackDiscoveryMode mode) { - return getUsableStacksForPlayer(mode, castingHand, caster); - } - - @Override - protected List<HeldItemInfo> getPrimaryStacks() { - return getPrimaryStacksForPlayer(this.castingHand, this.caster); - } - - @Override - public boolean replaceItem(Predicate<ItemStack> stackOk, ItemStack replaceWith, @Nullable InteractionHand hand) { - return replaceItemForPlayer(stackOk, replaceWith, hand, this.caster); - } - - @Override - public boolean isVecInRangeEnvironment(Vec3 vec) { - var sentinel = HexAPI.instance().getSentinel(this.caster); - if (sentinel != null - && sentinel.extendsRange() - && this.caster.level().dimension() == sentinel.dimension() - // adding 0.00000000001 to avoid machine precision errors at specific angles - && vec.distanceToSqr(sentinel.position()) <= SENTINEL_RADIUS * SENTINEL_RADIUS + 0.00000000001 - ) { - return true; - } - - return vec.distanceToSqr(this.caster.position()) <= AMBIT_RADIUS * AMBIT_RADIUS + 0.00000000001; - } - - @Override - public boolean hasEditPermissionsAtEnvironment(BlockPos pos) { - return this.caster.gameMode.getGameModeForPlayer() != GameType.ADVENTURE && this.world.mayInteract(this.caster, pos); - } - - /** - * Search the player's inventory for media ADs and use them. - */ - protected long extractMediaFromInventory(long costLeft, boolean allowOvercast, boolean simulate) { - List<ADMediaHolder> sources = MediaHelper.scanPlayerForMediaStuff(this.caster); - - var startCost = costLeft; - - for (var source : sources) { - var found = MediaHelper.extractMedia(source, costLeft, false, simulate); - costLeft -= found; - if (costLeft <= 0) { - break; - } - } - - if (costLeft > 0 && allowOvercast) { - double mediaToHealth = HexConfig.common().mediaToHealthRate(); - double healthToRemove = Math.max(costLeft / mediaToHealth, 0.5); - if (simulate) { - long simulatedRemovedMedia = Mth.ceil(Math.min(this.caster.getHealth(), healthToRemove) * mediaToHealth); - costLeft -= simulatedRemovedMedia; - } else { - var mediaAbleToCastFromHP = this.caster.getHealth() * mediaToHealth; - - Mishap.trulyHurt(this.caster, this.caster.damageSources().source(HexDamageTypes.OVERCAST), (float) healthToRemove); - - var actuallyTaken = Mth.ceil(mediaAbleToCastFromHP - (this.caster.getHealth() * mediaToHealth)); - - HexAdvancementTriggers.OVERCAST_TRIGGER.trigger(this.caster, actuallyTaken); - this.caster.awardStat(HexStatistics.MEDIA_OVERCAST, actuallyTaken); - - costLeft -= actuallyTaken; - } - } - - if (!simulate) { - this.caster.awardStat(HexStatistics.MEDIA_USED, (int) (startCost - costLeft)); - HexAdvancementTriggers.SPEND_MEDIA_TRIGGER.trigger( - this.caster, - startCost - costLeft, - costLeft < 0 ? -costLeft : 0 - ); - } - - return costLeft; - } - - protected boolean canOvercast() { - var adv = this.world.getServer().getAdvancements().getAdvancement(modLoc("y_u_no_cast_angy")); - var advs = this.caster.getAdvancements(); - return advs.getOrStartProgress(adv).isDone(); - } - - @Override - public @Nullable FrozenPigment setPigment(@Nullable FrozenPigment pigment) { - return IXplatAbstractions.INSTANCE.setPigment(caster, pigment); - } - - @Override - public void produceParticles(ParticleSpray particles, FrozenPigment pigment) { - particles.sprayParticles(this.world, pigment); - } - - @Override - public Vec3 mishapSprayPos() { - return this.caster.position(); - } - - @Override - public MishapEnvironment getMishapEnvironment() { - return new PlayerBasedMishapEnv(this.caster); - } - - protected void sendMishapMsgToPlayer(OperatorSideEffect.DoMishap mishap) { - var msg = mishap.getMishap().errorMessageWithName(this, mishap.getErrorCtx()); - if (msg != null) { - this.caster.sendSystemMessage(msg); - } - } - - @Override - protected boolean isCreativeMode() { - // not sure what the diff between this and isCreative() is - return this.caster.getAbilities().instabuild; - } - - @Override - public void printMessage(Component message) { - caster.sendSystemMessage(message); - } + public static final double AMBIT_RADIUS = 32.0; + public static final double SENTINEL_RADIUS = 16.0; + + protected final ServerPlayer caster; + protected final InteractionHand castingHand; + + protected PlayerBasedCastEnv(ServerPlayer caster, InteractionHand castingHand) { + super(caster.serverLevel()); + this.caster = caster; + this.castingHand = castingHand; + } + + @Override + public LivingEntity getCastingEntity() { + return this.caster; + } + + @Override + public ServerPlayer getCaster() { + return this.caster; + } + + @Override + public void postExecution(CastResult result) { + super.postExecution(result); + + for (var sideEffect : result.getSideEffects()) { + if (sideEffect instanceof OperatorSideEffect.DoMishap doMishap) { + this.sendMishapMsgToPlayer(doMishap); + } + } + } + + @Override + protected List<ItemStack> getUsableStacks(StackDiscoveryMode mode) { + return getUsableStacksForPlayer(mode, castingHand, caster); + } + + @Override + protected List<HeldItemInfo> getPrimaryStacks() { + return getPrimaryStacksForPlayer(this.castingHand, this.caster); + } + + @Override + public boolean replaceItem( + Predicate<ItemStack> stackOk, ItemStack replaceWith, @Nullable InteractionHand hand) { + return replaceItemForPlayer(stackOk, replaceWith, hand, this.caster); + } + + @Override + public boolean isVecInRangeEnvironment(Vec3 vec) { + var sentinel = HexAPI.instance().getSentinel(this.caster); + if (sentinel != null + && sentinel.extendsRange() + && this.caster.level().dimension() == sentinel.dimension() + // adding 0.00000000001 to avoid machine precision errors at specific angles + && vec.distanceToSqr(sentinel.position()) + <= SENTINEL_RADIUS * SENTINEL_RADIUS + 0.00000000001) { + return true; + } + + return vec.distanceToSqr(this.caster.position()) <= AMBIT_RADIUS * AMBIT_RADIUS + 0.00000000001; + } + + @Override + public boolean hasEditPermissionsAtEnvironment(BlockPos pos) { + return this.caster.gameMode.getGameModeForPlayer() != GameType.ADVENTURE + && this.world.mayInteract(this.caster, pos); + } + + /** Search the player's inventory for media ADs and use them. */ + protected long extractMediaFromInventory(long costLeft, boolean allowOvercast, boolean simulate) { + List<ADMediaHolder> sources = MediaHelper.scanPlayerForMediaStuff(this.caster); + + var startCost = costLeft; + + for (var source : sources) { + var found = MediaHelper.extractMedia(source, costLeft, false, simulate); + costLeft -= found; + if (costLeft <= 0) { + break; + } + } + + if (costLeft > 0 && allowOvercast) { + double mediaToHealth = HexConfig.common().mediaToHealthRate(); + double healthToRemove = Math.max(costLeft / mediaToHealth, 0.5); + if (simulate) { + long simulatedRemovedMedia = + Mth.ceil(Math.min(this.caster.getHealth(), healthToRemove) * mediaToHealth); + costLeft -= simulatedRemovedMedia; + } else { + var mediaAbleToCastFromHP = this.caster.getHealth() * mediaToHealth; + + Mishap.trulyHurt( + this.caster, + this.caster.damageSources().source(HexDamageTypes.OVERCAST), + (float) healthToRemove); + + var actuallyTaken = + Mth.ceil(mediaAbleToCastFromHP - (this.caster.getHealth() * mediaToHealth)); + + HexAdvancementTriggers.OVERCAST_TRIGGER.trigger(this.caster, actuallyTaken); + this.caster.awardStat(HexStatistics.MEDIA_OVERCAST, actuallyTaken); + + costLeft -= actuallyTaken; + } + } + + if (!simulate) { + this.caster.awardStat(HexStatistics.MEDIA_USED, (int) (startCost - costLeft)); + HexAdvancementTriggers.SPEND_MEDIA_TRIGGER.trigger( + this.caster, startCost - costLeft, costLeft < 0 ? -costLeft : 0); + } + + return costLeft; + } + + protected boolean canOvercast() { + var adv = this.world.getServer().getAdvancements().getAdvancement(modLoc("y_u_no_cast_angy")); + var advs = this.caster.getAdvancements(); + return advs.getOrStartProgress(adv).isDone(); + } + + @Override + public @Nullable FrozenPigment setPigment(@Nullable FrozenPigment pigment) { + return IXplatAbstractions.INSTANCE.setPigment(caster, pigment); + } + + @Override + public void produceParticles(ParticleSpray particles, FrozenPigment pigment) { + particles.sprayParticles(this.world, pigment); + } + + @Override + public Vec3 mishapSprayPos() { + return this.caster.position(); + } + + @Override + public MishapEnvironment getMishapEnvironment() { + return new PlayerBasedMishapEnv(this.caster); + } + + protected void sendMishapMsgToPlayer(OperatorSideEffect.DoMishap mishap) { + var msg = mishap.getMishap().errorMessageWithName(this, mishap.getErrorCtx()); + if (msg != null) { + this.caster.sendSystemMessage(msg); + } + } + + @Override + protected boolean isCreativeMode() { + // not sure what the diff between this and isCreative() is + return this.caster.getAbilities().instabuild; + } + + @Override + public void printMessage(Component message) { + caster.sendSystemMessage(message); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedMishapEnv.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedMishapEnv.java index 370ba5002a..d21c81b3c9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedMishapEnv.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedMishapEnv.java @@ -11,48 +11,51 @@ import net.minecraft.world.phys.Vec3; public class PlayerBasedMishapEnv extends MishapEnvironment { - public PlayerBasedMishapEnv(ServerPlayer player) { - super(player.serverLevel(), player); - } - - @Override - public void yeetHeldItemsTowards(Vec3 targetPos) { - var pos = this.caster.position(); - var delta = targetPos.subtract(pos).normalize().scale(0.5); - - for (var hand : InteractionHand.values()) { - var stack = this.caster.getItemInHand(hand); - this.caster.setItemInHand(hand, ItemStack.EMPTY); - this.yeetItem(stack, pos, delta); - } - } - - @Override - public void dropHeldItems() { - var delta = this.caster.getLookAngle(); - this.yeetHeldItemsTowards(this.caster.position().add(delta)); - } - - @Override - public void damage(float healthProportion) { - Mishap.trulyHurt(this.caster, this.caster.damageSources().source(HexDamageTypes.OVERCAST), this.caster.getHealth() * healthProportion); - } - - @Override - public void drown() { - if (this.caster.getAirSupply() < 200) { - this.caster.hurt(this.caster.damageSources().drown(), 2f); - } - this.caster.setAirSupply(0); - } - - @Override - public void removeXp(int amount) { - this.caster.giveExperiencePoints(-amount); - } - - @Override - public void blind(int ticks) { - this.caster.addEffect(new MobEffectInstance(MobEffects.BLINDNESS, ticks)); - } + public PlayerBasedMishapEnv(ServerPlayer player) { + super(player.serverLevel(), player); + } + + @Override + public void yeetHeldItemsTowards(Vec3 targetPos) { + var pos = this.caster.position(); + var delta = targetPos.subtract(pos).normalize().scale(0.5); + + for (var hand : InteractionHand.values()) { + var stack = this.caster.getItemInHand(hand); + this.caster.setItemInHand(hand, ItemStack.EMPTY); + this.yeetItem(stack, pos, delta); + } + } + + @Override + public void dropHeldItems() { + var delta = this.caster.getLookAngle(); + this.yeetHeldItemsTowards(this.caster.position().add(delta)); + } + + @Override + public void damage(float healthProportion) { + Mishap.trulyHurt( + this.caster, + this.caster.damageSources().source(HexDamageTypes.OVERCAST), + this.caster.getHealth() * healthProportion); + } + + @Override + public void drown() { + if (this.caster.getAirSupply() < 200) { + this.caster.hurt(this.caster.damageSources().drown(), 2f); + } + this.caster.setAirSupply(0); + } + + @Override + public void removeXp(int amount) { + this.caster.giveExperiencePoints(-amount); + } + + @Override + public void blind(int ticks) { + this.caster.addEffect(new MobEffectInstance(MobEffects.BLINDNESS, ticks)); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/StaffCastEnv.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/StaffCastEnv.java index 29e80d3817..3620dc7b33 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/StaffCastEnv.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/StaffCastEnv.java @@ -13,138 +13,136 @@ import at.petrak.hexcasting.api.pigment.FrozenPigment; import at.petrak.hexcasting.common.msgs.*; import at.petrak.hexcasting.xplat.IXplatAbstractions; -import net.minecraft.network.chat.Component; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundSource; import net.minecraft.world.InteractionHand; import net.minecraft.world.phys.Vec3; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - public class StaffCastEnv extends PlayerBasedCastEnv { - private final InteractionHand castingHand; - - private final Set<HexPattern> castPatterns = new HashSet<>(); - private int soundsPlayed = 0; - - - public StaffCastEnv(ServerPlayer caster, InteractionHand castingHand) { - super(caster, castingHand); - - this.castingHand = castingHand; - } - - @Override - public void postExecution(CastResult result) { - super.postExecution(result); - - if (result.component1() instanceof PatternIota patternIota) { - castPatterns.add(patternIota.getPattern()); - } - - // we always want to play this sound one at a time - var sound = result.getSound().sound(); - if (soundsPlayed < 100 && sound != null) { // TODO: Make configurable - var soundPos = this.caster.position(); - this.world.playSound(null, soundPos.x, soundPos.y, soundPos.z, - sound, SoundSource.PLAYERS, 1f, 1f); - soundsPlayed++; - } - } - - @Override - public void postCast(CastingImage image) { - super.postCast(image); - - var packet = new MsgNewSpiralPatternsS2C( - this.caster.getUUID(), castPatterns.stream().toList(), Integer.MAX_VALUE - ); - IXplatAbstractions.INSTANCE.sendPacketToPlayer(this.caster, packet); - IXplatAbstractions.INSTANCE.sendPacketTracking(this.caster, packet); - - castPatterns.clear(); - soundsPlayed = 0; - } - - @Override - public long extractMediaEnvironment(long cost, boolean simulate) { - if (this.caster.isCreative()) - return 0; - - var canOvercast = this.canOvercast(); - return this.extractMediaFromInventory(cost, canOvercast, simulate); - } - - @Override - public InteractionHand getCastingHand() { - return castingHand; - } - - @Override - public FrozenPigment getPigment() { - return HexAPI.instance().getColorizer(this.caster); - } - - public static void handleNewPatternOnServer(ServerPlayer sender, MsgNewSpellPatternC2S msg) { - boolean cheatedPatternOverlap = false; - - List<ResolvedPattern> resolvedPatterns = msg.resolvedPatterns(); - if (!resolvedPatterns.isEmpty()) { - var allPoints = new HashSet<HexCoord>(); - for (int i = 0; i < resolvedPatterns.size() - 1; i++) { - ResolvedPattern pat = resolvedPatterns.get(i); - allPoints.addAll(pat.getPattern().positions(pat.getOrigin())); - } - var currentResolvedPattern = resolvedPatterns.get(resolvedPatterns.size() - 1); - var currentSpellPoints = currentResolvedPattern.getPattern() - .positions(currentResolvedPattern.getOrigin()); - if (currentSpellPoints.stream().anyMatch(allPoints::contains)) { - cheatedPatternOverlap = true; - } - } - - if (cheatedPatternOverlap) { - return; - } - - sender.awardStat(HexStatistics.PATTERNS_DRAWN); - - var vm = IXplatAbstractions.INSTANCE.getStaffcastVM(sender, msg.handUsed()); - - // TODO: do we reset the number of evals run via the staff? because each new pat is a new tick. - - ExecutionClientView clientInfo = vm.queueExecuteAndWrapIota(new PatternIota(msg.pattern()), sender.serverLevel()); - - if (clientInfo.isStackClear()) { - IXplatAbstractions.INSTANCE.setStaffcastImage(sender, null); - IXplatAbstractions.INSTANCE.setPatterns(sender, List.of()); - } else { - IXplatAbstractions.INSTANCE.setStaffcastImage(sender, vm.getImage().withOverriddenUsedOps(0)); - if (!resolvedPatterns.isEmpty()) { - resolvedPatterns.get(resolvedPatterns.size() - 1).setType(clientInfo.getResolutionType()); - } - IXplatAbstractions.INSTANCE.setPatterns(sender, resolvedPatterns); - } - - IXplatAbstractions.INSTANCE.sendPacketToPlayer(sender, - new MsgNewSpellPatternS2C(clientInfo, resolvedPatterns.size() - 1)); - - IMessage packet; - if (clientInfo.isStackClear()) { - packet = new MsgClearSpiralPatternsS2C(sender.getUUID()); - } else { - packet = new MsgNewSpiralPatternsS2C(sender.getUUID(), List.of(msg.pattern()), Integer.MAX_VALUE); - } - IXplatAbstractions.INSTANCE.sendPacketToPlayer(sender, packet); - IXplatAbstractions.INSTANCE.sendPacketTracking(sender, packet); - - if (clientInfo.getResolutionType().getSuccess()) { - // Somehow we lost spraying particles on each new pattern, so do it here - // this also nicely prevents particle spam on trinkets - new ParticleSpray(sender.position(), new Vec3(0.0, 1.5, 0.0), 0.4, Math.PI / 3, 30) - .sprayParticles(sender.serverLevel(), IXplatAbstractions.INSTANCE.getPigment(sender)); - } - } + private final InteractionHand castingHand; + + private final Set<HexPattern> castPatterns = new HashSet<>(); + private int soundsPlayed = 0; + + public StaffCastEnv(ServerPlayer caster, InteractionHand castingHand) { + super(caster, castingHand); + + this.castingHand = castingHand; + } + + @Override + public void postExecution(CastResult result) { + super.postExecution(result); + + if (result.component1() instanceof PatternIota patternIota) { + castPatterns.add(patternIota.getPattern()); + } + + // we always want to play this sound one at a time + var sound = result.getSound().sound(); + if (soundsPlayed < 100 && sound != null) { // TODO: Make configurable + var soundPos = this.caster.position(); + this.world.playSound( + null, soundPos.x, soundPos.y, soundPos.z, sound, SoundSource.PLAYERS, 1f, 1f); + soundsPlayed++; + } + } + + @Override + public void postCast(CastingImage image) { + super.postCast(image); + + var packet = + new MsgNewSpiralPatternsS2C( + this.caster.getUUID(), castPatterns.stream().toList(), Integer.MAX_VALUE); + IXplatAbstractions.INSTANCE.sendPacketToPlayer(this.caster, packet); + IXplatAbstractions.INSTANCE.sendPacketTracking(this.caster, packet); + + castPatterns.clear(); + soundsPlayed = 0; + } + + @Override + public long extractMediaEnvironment(long cost, boolean simulate) { + if (this.caster.isCreative()) return 0; + + var canOvercast = this.canOvercast(); + return this.extractMediaFromInventory(cost, canOvercast, simulate); + } + + @Override + public InteractionHand getCastingHand() { + return castingHand; + } + + @Override + public FrozenPigment getPigment() { + return HexAPI.instance().getColorizer(this.caster); + } + + public static void handleNewPatternOnServer(ServerPlayer sender, MsgNewSpellPatternC2S msg) { + boolean cheatedPatternOverlap = false; + + List<ResolvedPattern> resolvedPatterns = msg.resolvedPatterns(); + if (!resolvedPatterns.isEmpty()) { + var allPoints = new HashSet<HexCoord>(); + for (int i = 0; i < resolvedPatterns.size() - 1; i++) { + ResolvedPattern pat = resolvedPatterns.get(i); + allPoints.addAll(pat.getPattern().positions(pat.getOrigin())); + } + var currentResolvedPattern = resolvedPatterns.get(resolvedPatterns.size() - 1); + var currentSpellPoints = + currentResolvedPattern.getPattern().positions(currentResolvedPattern.getOrigin()); + if (currentSpellPoints.stream().anyMatch(allPoints::contains)) { + cheatedPatternOverlap = true; + } + } + + if (cheatedPatternOverlap) { + return; + } + + sender.awardStat(HexStatistics.PATTERNS_DRAWN); + + var vm = IXplatAbstractions.INSTANCE.getStaffcastVM(sender, msg.handUsed()); + + // TODO: do we reset the number of evals run via the staff? because each new pat is a new tick. + + ExecutionClientView clientInfo = + vm.queueExecuteAndWrapIota(new PatternIota(msg.pattern()), sender.serverLevel()); + + if (clientInfo.isStackClear()) { + IXplatAbstractions.INSTANCE.setStaffcastImage(sender, null); + IXplatAbstractions.INSTANCE.setPatterns(sender, List.of()); + } else { + IXplatAbstractions.INSTANCE.setStaffcastImage(sender, vm.getImage().withOverriddenUsedOps(0)); + if (!resolvedPatterns.isEmpty()) { + resolvedPatterns.get(resolvedPatterns.size() - 1).setType(clientInfo.getResolutionType()); + } + IXplatAbstractions.INSTANCE.setPatterns(sender, resolvedPatterns); + } + + IXplatAbstractions.INSTANCE.sendPacketToPlayer( + sender, new MsgNewSpellPatternS2C(clientInfo, resolvedPatterns.size() - 1)); + + IMessage packet; + if (clientInfo.isStackClear()) { + packet = new MsgClearSpiralPatternsS2C(sender.getUUID()); + } else { + packet = + new MsgNewSpiralPatternsS2C(sender.getUUID(), List.of(msg.pattern()), Integer.MAX_VALUE); + } + IXplatAbstractions.INSTANCE.sendPacketToPlayer(sender, packet); + IXplatAbstractions.INSTANCE.sendPacketTracking(sender, packet); + + if (clientInfo.getResolutionType().getSuccess()) { + // Somehow we lost spraying particles on each new pattern, so do it here + // this also nicely prevents particle spam on trinkets + new ParticleSpray(sender.position(), new Vec3(0.0, 1.5, 0.0), 0.4, Math.PI / 3, 30) + .sprayParticles(sender.serverLevel(), IXplatAbstractions.INSTANCE.getPigment(sender)); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/package-info.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/package-info.java index 036bb48b23..7818f29677 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/package-info.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/package-info.java @@ -2,4 +2,4 @@ * Default impls for some casting and mishap envs for your convenience and also so i can impl * BlockEntityAbstractImpetus in api guilt-free */ -package at.petrak.hexcasting.api.casting.eval.env; \ No newline at end of file +package at.petrak.hexcasting.api.casting.eval.env; diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/sideeffects/EvalSound.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/sideeffects/EvalSound.java index f81a34eb3f..36c3d85200 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/sideeffects/EvalSound.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/sideeffects/EvalSound.java @@ -6,13 +6,12 @@ /** * The kind of sound that plays after a cast. * - * @param sound the actual sound file - * @param priority the priority of this sound. the sound with the highest priority in a given cast will be - * played. - * shortcutMetacasting takes precedence over this. + * @param sound the actual sound file + * @param priority the priority of this sound. the sound with the highest priority in a given cast + * will be played. shortcutMetacasting takes precedence over this. */ public record EvalSound(@Nullable SoundEvent sound, int priority) { - public EvalSound greaterOf(EvalSound that) { - return (this.priority > that.priority) ? this : that; - } + public EvalSound greaterOf(EvalSound that) { + return (this.priority > that.priority) ? this : that; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/sideeffects/OperatorSideEffect.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/sideeffects/OperatorSideEffect.kt index 72226fe291..ac03b1e00c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/sideeffects/OperatorSideEffect.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/sideeffects/OperatorSideEffect.kt @@ -13,60 +13,60 @@ import net.minecraft.server.level.ServerPlayer import net.minecraft.world.item.DyeColor import net.minecraft.world.item.ItemStack -/** - * Things that happen after a spell is cast. - */ +/** Things that happen after a spell is cast. */ sealed class OperatorSideEffect { - /** Return whether to cancel all further [OperatorSideEffect] */ - abstract fun performEffect(harness: CastingVM) + /** Return whether to cancel all further [OperatorSideEffect] */ + abstract fun performEffect(harness: CastingVM) - data class RequiredEnlightenment(val awardStat: Boolean) : OperatorSideEffect() { - override fun performEffect(harness: CastingVM) { - harness.env.castingEntity?.sendSystemMessage("hexcasting.message.cant_great_spell".asTranslatedComponent) - } - } + data class RequiredEnlightenment(val awardStat: Boolean) : OperatorSideEffect() { + override fun performEffect(harness: CastingVM) { + harness.env.castingEntity?.sendSystemMessage( + "hexcasting.message.cant_great_spell".asTranslatedComponent + ) + } + } - /** Try to cast a spell */ - data class AttemptSpell( - val spell: RenderedSpell, - val hasCastingSound: Boolean = true, - val awardStat: Boolean = true - ) : - OperatorSideEffect() { - override fun performEffect(harness: CastingVM) { - this.spell.cast(harness.env, harness.image)?.let { harness.image = it } - if (awardStat) - (harness.env.castingEntity as? ServerPlayer)?.awardStat(HexStatistics.SPELLS_CAST) - } - } + /** Try to cast a spell */ + data class AttemptSpell( + val spell: RenderedSpell, + val hasCastingSound: Boolean = true, + val awardStat: Boolean = true + ) : OperatorSideEffect() { + override fun performEffect(harness: CastingVM) { + this.spell.cast(harness.env, harness.image)?.let { harness.image = it } + if (awardStat) + (harness.env.castingEntity as? ServerPlayer)?.awardStat(HexStatistics.SPELLS_CAST) + } + } - data class ConsumeMedia(val amount: Long) : OperatorSideEffect() { - override fun performEffect(harness: CastingVM) { - harness.env.extractMedia(this.amount, false) - } - } + data class ConsumeMedia(val amount: Long) : OperatorSideEffect() { + override fun performEffect(harness: CastingVM) { + harness.env.extractMedia(this.amount, false) + } + } - data class Particles(val spray: ParticleSpray) : OperatorSideEffect() { - override fun performEffect(harness: CastingVM) { - harness.env.produceParticles(this.spray, harness.env.pigment) -// this.spray.sprayParticles(harness.env.world, harness.env.colorizer) - } - } + data class Particles(val spray: ParticleSpray) : OperatorSideEffect() { + override fun performEffect(harness: CastingVM) { + harness.env.produceParticles(this.spray, harness.env.pigment) + // this.spray.sprayParticles(harness.env.world, harness.env.colorizer) + } + } - data class DoMishap(val mishap: Mishap, val errorCtx: Mishap.Context) : OperatorSideEffect() { - override fun performEffect(harness: CastingVM) { - val spray = mishap.particleSpray(harness.env) - val color = mishap.accentColor(harness.env, errorCtx) - spray.sprayParticles(harness.env.world, color) - spray.sprayParticles( - harness.env.world, - FrozenPigment( - ItemStack(HexItems.DYE_PIGMENTS[DyeColor.RED]!!), - Util.NIL_UUID - ) - ) + data class DoMishap(val mishap: Mishap, val errorCtx: Mishap.Context) : OperatorSideEffect() { + override fun performEffect(harness: CastingVM) { + val spray = mishap.particleSpray(harness.env) + val color = mishap.accentColor(harness.env, errorCtx) + spray.sprayParticles(harness.env.world, color) + spray.sprayParticles( + harness.env.world, + FrozenPigment(ItemStack(HexItems.DYE_PIGMENTS[DyeColor.RED]!!), Util.NIL_UUID) + ) - harness.image = harness.image.copy(stack = mishap.executeReturnStack(harness.env, errorCtx, harness.image.stack.toMutableList())) - } - } + harness.image = + harness.image.copy( + stack = + mishap.executeReturnStack(harness.env, errorCtx, harness.image.stack.toMutableList()) + ) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt index 3ffd771bcd..b73f10e09f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt @@ -13,129 +13,122 @@ import net.minecraft.nbt.Tag import net.minecraft.server.level.ServerLevel import net.minecraft.world.entity.Entity -/** - * The state of a casting VM, containing the stack and all - */ -data class CastingImage private constructor( - val stack: List<Iota>, - - val parenCount: Int, - val parenthesized: List<ParenthesizedIota>, - val escapeNext: Boolean, - val opsConsumed: Long, - - val userData: CompoundTag +/** The state of a casting VM, containing the stack and all */ +data class CastingImage +private constructor( + val stack: List<Iota>, + val parenCount: Int, + val parenthesized: List<ParenthesizedIota>, + val escapeNext: Boolean, + val opsConsumed: Long, + val userData: CompoundTag ) { - constructor() : this(listOf(), 0, listOf(), false, 0, CompoundTag()) - - data class ParenthesizedIota(val iota: Iota, val escaped: Boolean) { - companion object { - const val TAG_IOTAS = "iotas" - const val TAG_ESCAPED = "escaped" - } - } - - /** - * Returns an empty list if it's too complicated. - */ - private fun Iterable<ParenthesizedIota>.serializeToNBT(): CompoundTag { - val tag = CompoundTag() - - if (IotaType.isTooLargeToSerialize(this.map { it.iota })) { - tag.put(TAG_IOTAS, ListTag()) - tag.put(TAG_ESCAPED, ListTag()) - } else { - tag.put(TAG_IOTAS, ListIota(this.map { it.iota }).serialize()) - tag.put(TAG_ESCAPED, this.map { it.escaped }.serializeToNBT()) - } - - return tag - } - - /** - * Return a copy of this with the given number of ops additionally exhausted - */ - fun withUsedOps(count: Long) = this.copy(opsConsumed = this.opsConsumed + count) - - /** - * Return a copy of this with 1 op used - */ - fun withUsedOp() = this.withUsedOps(1) - - /** - * Returns a copy of this with the [opsConsumed] replaced with [count]. - */ - fun withOverriddenUsedOps(count: Long) = this.copy(opsConsumed = count) - - /** - * Returns a copy of this with escape/paren-related fields cleared. - */ - fun withResetEscape() = this.copy(parenCount = 0, parenthesized = listOf(), escapeNext = false) - - fun serializeToNbt() = NBTBuilder { - TAG_STACK %= stack.serializeToNBT() - - TAG_PAREN_COUNT %= parenCount - TAG_ESCAPE_NEXT %= escapeNext - TAG_PARENTHESIZED %= parenthesized.serializeToNBT() - TAG_OPS_CONSUMED %= opsConsumed - - TAG_USERDATA %= userData - } - - companion object { - const val TAG_STACK = "stack" - const val TAG_PAREN_COUNT = "open_parens" - const val TAG_PARENTHESIZED = "parenthesized" - const val TAG_ESCAPE_NEXT = "escape_next" - const val TAG_OPS_CONSUMED = "ops_consumed" - const val TAG_USERDATA = "userdata" - - @JvmStatic - fun loadFromNbt(tag: CompoundTag, world: ServerLevel): CastingImage { - return try { - val stack = mutableListOf<Iota>() - val stackTag = tag.getList(TAG_STACK, Tag.TAG_COMPOUND) - for (subtag in stackTag) { - val datum = IotaType.deserialize(subtag.asCompound, world) - stack.add(datum) - } - - val userData = if (tag.contains(TAG_USERDATA)) { - tag.getCompound(TAG_USERDATA) - } else { - CompoundTag() - } - - val parenthesized = mutableListOf<ParenthesizedIota>() - val parenTag = tag.getCompound(TAG_PARENTHESIZED) - val parenIotasTag = parenTag.getList(TAG_IOTAS, Tag.TAG_COMPOUND) - val parenEscapedTag = parenTag.getByteArray(TAG_ESCAPED) - - for ((subtag, isEscapedByte) in parenIotasTag.zipWithDefault(parenEscapedTag) { _ -> 0 }) { - parenthesized.add(ParenthesizedIota(IotaType.deserialize(subtag.downcast(CompoundTag.TYPE), world), isEscapedByte != 0.toByte())) - } - - val parenCount = tag.getInt(TAG_PAREN_COUNT) - val escapeNext = tag.getBoolean(TAG_ESCAPE_NEXT) - val opsUsed = tag.getLong(TAG_OPS_CONSUMED) - - CastingImage(stack, parenCount, parenthesized, escapeNext, opsUsed, userData) - } catch (exn: Exception) { - HexAPI.LOGGER.warn("error while loading a CastingImage", exn) - CastingImage() - } - } - - @JvmStatic - fun checkAndMarkGivenMotion(userData: CompoundTag, entity: Entity): Boolean { - val marked = userData.getOrCreateCompound(HexAPI.MARKED_MOVED_USERDATA) - return if (marked.contains(entity.stringUUID)) { - true - } else { - marked.putBoolean(entity.stringUUID, true) - false - } - } - } + constructor() : this(listOf(), 0, listOf(), false, 0, CompoundTag()) + + data class ParenthesizedIota(val iota: Iota, val escaped: Boolean) { + companion object { + const val TAG_IOTAS = "iotas" + const val TAG_ESCAPED = "escaped" + } + } + + /** Returns an empty list if it's too complicated. */ + private fun Iterable<ParenthesizedIota>.serializeToNBT(): CompoundTag { + val tag = CompoundTag() + + if (IotaType.isTooLargeToSerialize(this.map { it.iota })) { + tag.put(TAG_IOTAS, ListTag()) + tag.put(TAG_ESCAPED, ListTag()) + } else { + tag.put(TAG_IOTAS, ListIota(this.map { it.iota }).serialize()) + tag.put(TAG_ESCAPED, this.map { it.escaped }.serializeToNBT()) + } + + return tag + } + + /** Return a copy of this with the given number of ops additionally exhausted */ + fun withUsedOps(count: Long) = this.copy(opsConsumed = this.opsConsumed + count) + + /** Return a copy of this with 1 op used */ + fun withUsedOp() = this.withUsedOps(1) + + /** Returns a copy of this with the [opsConsumed] replaced with [count]. */ + fun withOverriddenUsedOps(count: Long) = this.copy(opsConsumed = count) + + /** Returns a copy of this with escape/paren-related fields cleared. */ + fun withResetEscape() = this.copy(parenCount = 0, parenthesized = listOf(), escapeNext = false) + + fun serializeToNbt() = NBTBuilder { + TAG_STACK %= stack.serializeToNBT() + + TAG_PAREN_COUNT %= parenCount + TAG_ESCAPE_NEXT %= escapeNext + TAG_PARENTHESIZED %= parenthesized.serializeToNBT() + TAG_OPS_CONSUMED %= opsConsumed + + TAG_USERDATA %= userData + } + + companion object { + const val TAG_STACK = "stack" + const val TAG_PAREN_COUNT = "open_parens" + const val TAG_PARENTHESIZED = "parenthesized" + const val TAG_ESCAPE_NEXT = "escape_next" + const val TAG_OPS_CONSUMED = "ops_consumed" + const val TAG_USERDATA = "userdata" + + @JvmStatic + fun loadFromNbt(tag: CompoundTag, world: ServerLevel): CastingImage { + return try { + val stack = mutableListOf<Iota>() + val stackTag = tag.getList(TAG_STACK, Tag.TAG_COMPOUND) + for (subtag in stackTag) { + val datum = IotaType.deserialize(subtag.asCompound, world) + stack.add(datum) + } + + val userData = + if (tag.contains(TAG_USERDATA)) { + tag.getCompound(TAG_USERDATA) + } else { + CompoundTag() + } + + val parenthesized = mutableListOf<ParenthesizedIota>() + val parenTag = tag.getCompound(TAG_PARENTHESIZED) + val parenIotasTag = parenTag.getList(TAG_IOTAS, Tag.TAG_COMPOUND) + val parenEscapedTag = parenTag.getByteArray(TAG_ESCAPED) + + for ((subtag, isEscapedByte) in parenIotasTag.zipWithDefault(parenEscapedTag) { _ -> 0 }) { + parenthesized.add( + ParenthesizedIota( + IotaType.deserialize(subtag.downcast(CompoundTag.TYPE), world), + isEscapedByte != 0.toByte() + ) + ) + } + + val parenCount = tag.getInt(TAG_PAREN_COUNT) + val escapeNext = tag.getBoolean(TAG_ESCAPE_NEXT) + val opsUsed = tag.getLong(TAG_OPS_CONSUMED) + + CastingImage(stack, parenCount, parenthesized, escapeNext, opsUsed, userData) + } catch (exn: Exception) { + HexAPI.LOGGER.warn("error while loading a CastingImage", exn) + CastingImage() + } + } + + @JvmStatic + fun checkAndMarkGivenMotion(userData: CompoundTag, entity: Entity): Boolean { + val marked = userData.getOrCreateCompound(HexAPI.MARKED_MOVED_USERDATA) + return if (marked.contains(entity.stringUUID)) { + true + } else { + marked.putBoolean(entity.stringUUID, true) + false + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt index 587500355b..8c4c6277de 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt @@ -19,288 +19,286 @@ import net.minecraft.nbt.CompoundTag import net.minecraft.server.level.ServerLevel /** - * The virtual machine! This is the glue that determines the next iteration of a [CastingImage], using a - * [CastingEnvironment] to affect the world. + * The virtual machine! This is the glue that determines the next iteration of a [CastingImage], + * using a [CastingEnvironment] to affect the world. */ class CastingVM(var image: CastingImage, val env: CastingEnvironment) { - init { - env.triggerCreateEvent(image.userData) - } + init { + env.triggerCreateEvent(image.userData) + } - /** - * Execute a single iota. - */ - fun queueExecuteAndWrapIota(iota: Iota, world: ServerLevel): ExecutionClientView = queueExecuteAndWrapIotas(listOf(iota), world) + /** Execute a single iota. */ + fun queueExecuteAndWrapIota(iota: Iota, world: ServerLevel): ExecutionClientView = + queueExecuteAndWrapIotas(listOf(iota), world) - /** - * The main entrypoint to the VM. Given a list of iotas, execute them in sequence, and return whatever the client - * needs to see. - * - * Mutates this - */ - fun queueExecuteAndWrapIotas(iotas: List<Iota>, world: ServerLevel): ExecutionClientView { - // Initialize the continuation stack to a single top-level eval for all iotas. - var continuation = SpellContinuation.Done.pushFrame(FrameEvaluate(SpellList.LList(0, iotas), false)) - // Begin aggregating info - val info = TempControllerInfo(earlyExit = false) - var lastResolutionType = ResolvedPatternType.UNRESOLVED - while (continuation is SpellContinuation.NotDone && !info.earlyExit) { - // Take the top of the continuation stack... - val next = continuation.frame - // ...and execute it. - // TODO there used to be error checking code here; I'm pretty sure any and all mishaps should already - // get caught and folded into CastResult by evaluate. - val image2 = next.evaluate(continuation.next, world, this).let { result -> - // if stack is unable to be serialized, have the result be an error - if (result.newData != null && IotaType.isTooLargeToSerialize(result.newData.stack)) { - result.copy( - newData = null, - sideEffects = listOf(OperatorSideEffect.DoMishap(MishapStackSize(), Mishap.Context(null, null))), - resolutionType = ResolvedPatternType.ERRORED, - sound = HexEvalSounds.MISHAP, - ) - } else { - result - } - } + /** + * The main entrypoint to the VM. Given a list of iotas, execute them in sequence, and return + * whatever the client needs to see. + * + * Mutates this + */ + fun queueExecuteAndWrapIotas(iotas: List<Iota>, world: ServerLevel): ExecutionClientView { + // Initialize the continuation stack to a single top-level eval for all iotas. + var continuation = + SpellContinuation.Done.pushFrame(FrameEvaluate(SpellList.LList(0, iotas), false)) + // Begin aggregating info + val info = TempControllerInfo(earlyExit = false) + var lastResolutionType = ResolvedPatternType.UNRESOLVED + while (continuation is SpellContinuation.NotDone && !info.earlyExit) { + // Take the top of the continuation stack... + val next = continuation.frame + // ...and execute it. + // TODO there used to be error checking code here; I'm pretty sure any and all mishaps should + // already + // get caught and folded into CastResult by evaluate. + val image2 = + next.evaluate(continuation.next, world, this).let { result -> + // if stack is unable to be serialized, have the result be an error + if (result.newData != null && IotaType.isTooLargeToSerialize(result.newData.stack)) { + result.copy( + newData = null, + sideEffects = + listOf(OperatorSideEffect.DoMishap(MishapStackSize(), Mishap.Context(null, null))), + resolutionType = ResolvedPatternType.ERRORED, + sound = HexEvalSounds.MISHAP, + ) + } else { + result + } + } - // Then write all pertinent data back to the harness for the next iteration. - if (image2.newData != null) { - this.image = image2.newData - } - this.env.postExecution(image2) + // Then write all pertinent data back to the harness for the next iteration. + if (image2.newData != null) { + this.image = image2.newData + } + this.env.postExecution(image2) - continuation = image2.continuation - lastResolutionType = image2.resolutionType - try { - performSideEffects(image2.sideEffects) - } catch (e: Exception) { - e.printStackTrace() - performSideEffects(listOf(OperatorSideEffect.DoMishap(MishapInternalException(e), Mishap.Context(null, null)))) - } - info.earlyExit = info.earlyExit || !lastResolutionType.success - } + continuation = image2.continuation + lastResolutionType = image2.resolutionType + try { + performSideEffects(image2.sideEffects) + } catch (e: Exception) { + e.printStackTrace() + performSideEffects( + listOf( + OperatorSideEffect.DoMishap(MishapInternalException(e), Mishap.Context(null, null)) + ) + ) + } + info.earlyExit = info.earlyExit || !lastResolutionType.success + } - if (continuation is SpellContinuation.NotDone) { - lastResolutionType = - if (lastResolutionType.success) ResolvedPatternType.EVALUATED else ResolvedPatternType.ERRORED - } + if (continuation is SpellContinuation.NotDone) { + lastResolutionType = + if (lastResolutionType.success) ResolvedPatternType.EVALUATED + else ResolvedPatternType.ERRORED + } - val (stackDescs, ravenmind) = generateDescs() + val (stackDescs, ravenmind) = generateDescs() - val isStackClear = image.stack.isEmpty() && image.parenCount == 0 && !image.escapeNext && ravenmind == null + val isStackClear = + image.stack.isEmpty() && image.parenCount == 0 && !image.escapeNext && ravenmind == null - this.env.postCast(image) - return ExecutionClientView(isStackClear, lastResolutionType, stackDescs, ravenmind) - } + this.env.postCast(image) + return ExecutionClientView(isStackClear, lastResolutionType, stackDescs, ravenmind) + } - /** - * this DOES NOT THROW THINGS - */ - @Throws() - fun executeInner(iota: Iota, world: ServerLevel, continuation: SpellContinuation): CastResult { - try { - // TODO we can have a special intro/retro sound - // ALSO TODO need to add reader macro-style things - try { - this.handleParentheses(iota)?.let { (data, resolutionType) -> - return@executeInner CastResult(iota, continuation, data, listOf(), resolutionType, HexEvalSounds.NORMAL_EXECUTE) - } - } catch (e: MishapTooManyCloseParens) { - // This is ridiculous and needs to be fixed - return CastResult( - iota, - continuation, - null, - listOf( - OperatorSideEffect.DoMishap( - e, - Mishap.Context( - (iota as? PatternIota)?.pattern ?: HexPattern(HexDir.WEST), - HexAPI.instance().getRawHookI18n(HexAPI.modLoc("close_paren")) - ) - ) - ), - ResolvedPatternType.ERRORED, - HexEvalSounds.MISHAP - ) - } + /** this DOES NOT THROW THINGS */ + @Throws() + fun executeInner(iota: Iota, world: ServerLevel, continuation: SpellContinuation): CastResult { + try { + // TODO we can have a special intro/retro sound + // ALSO TODO need to add reader macro-style things + try { + this.handleParentheses(iota)?.let { (data, resolutionType) -> + return@executeInner CastResult( + iota, + continuation, + data, + listOf(), + resolutionType, + HexEvalSounds.NORMAL_EXECUTE + ) + } + } catch (e: MishapTooManyCloseParens) { + // This is ridiculous and needs to be fixed + return CastResult( + iota, + continuation, + null, + listOf( + OperatorSideEffect.DoMishap( + e, + Mishap.Context( + (iota as? PatternIota)?.pattern ?: HexPattern(HexDir.WEST), + HexAPI.instance().getRawHookI18n(HexAPI.modLoc("close_paren")) + ) + ) + ), + ResolvedPatternType.ERRORED, + HexEvalSounds.MISHAP + ) + } - return iota.execute(this, world, continuation) - } catch (exception: Exception) { - // This means something very bad has happened - exception.printStackTrace() - return CastResult( - iota, - continuation, - null, - listOf( - OperatorSideEffect.DoMishap( - MishapInternalException(exception), - Mishap.Context( - (iota as? PatternIota)?.pattern ?: HexPattern(HexDir.WEST), - null - ) - ) - ), - ResolvedPatternType.ERRORED, - HexEvalSounds.MISHAP - ) - } - } + return iota.execute(this, world, continuation) + } catch (exception: Exception) { + // This means something very bad has happened + exception.printStackTrace() + return CastResult( + iota, + continuation, + null, + listOf( + OperatorSideEffect.DoMishap( + MishapInternalException(exception), + Mishap.Context((iota as? PatternIota)?.pattern ?: HexPattern(HexDir.WEST), null) + ) + ), + ResolvedPatternType.ERRORED, + HexEvalSounds.MISHAP + ) + } + } - /** - * Execute the side effects of a pattern, updating our aggregated info. - */ - fun performSideEffects(sideEffects: List<OperatorSideEffect>) { - for (haskellProgrammersShakingandCryingRN in sideEffects) { - haskellProgrammersShakingandCryingRN.performEffect(this) - } - } + /** Execute the side effects of a pattern, updating our aggregated info. */ + fun performSideEffects(sideEffects: List<OperatorSideEffect>) { + for (haskellProgrammersShakingandCryingRN in sideEffects) { + haskellProgrammersShakingandCryingRN.performEffect(this) + } + } - fun generateDescs(): Pair<List<CompoundTag>, CompoundTag?> { - val stackDescs = this.image.stack.map { IotaType.serialize(it) } - val ravenmind = if (this.image.userData.contains(HexAPI.RAVENMIND_USERDATA)) { - this.image.userData.getCompound(HexAPI.RAVENMIND_USERDATA) - } else null - return Pair(stackDescs, ravenmind) - } + fun generateDescs(): Pair<List<CompoundTag>, CompoundTag?> { + val stackDescs = this.image.stack.map { IotaType.serialize(it) } + val ravenmind = + if (this.image.userData.contains(HexAPI.RAVENMIND_USERDATA)) { + this.image.userData.getCompound(HexAPI.RAVENMIND_USERDATA) + } else null + return Pair(stackDescs, ravenmind) + } - /** - * Return a non-null value if we handled this in some sort of parenthesey way, - * either escaping it onto the stack or changing the parenthese-handling state. - */ - @Throws(MishapTooManyCloseParens::class) - private fun handleParentheses(iota: Iota): Pair<CastingImage, ResolvedPatternType>? { - val sig = (iota as? PatternIota)?.pattern?.angles + /** + * Return a non-null value if we handled this in some sort of parenthesey way, either escaping it + * onto the stack or changing the parenthese-handling state. + */ + @Throws(MishapTooManyCloseParens::class) + private fun handleParentheses(iota: Iota): Pair<CastingImage, ResolvedPatternType>? { + val sig = (iota as? PatternIota)?.pattern?.angles - var displayDepth = this.image.parenCount + var displayDepth = this.image.parenCount - val out = if (displayDepth > 0) { - if (this.image.escapeNext) { - val newParens = this.image.parenthesized.toMutableList() - newParens.add(ParenthesizedIota(iota, true)) - this.image.copy( - escapeNext = false, - parenthesized = newParens - ) to ResolvedPatternType.ESCAPED - } else { + val out = + if (displayDepth > 0) { + if (this.image.escapeNext) { + val newParens = this.image.parenthesized.toMutableList() + newParens.add(ParenthesizedIota(iota, true)) + this.image.copy(escapeNext = false, parenthesized = newParens) to + ResolvedPatternType.ESCAPED + } else { - when (sig) { - SpecialPatterns.CONSIDERATION.angles -> { - this.image.copy( - escapeNext = true, - ) to ResolvedPatternType.EVALUATED - } + when (sig) { + SpecialPatterns.CONSIDERATION.angles -> { + this.image.copy( + escapeNext = true, + ) to ResolvedPatternType.EVALUATED + } + SpecialPatterns.EVANITION.angles -> { + val newParens = this.image.parenthesized.toMutableList() + val last = newParens.removeLastOrNull() + val newParenCount = + this.image.parenCount + + if (last == null || last.escaped || last.iota !is PatternIota) 0 + else + when (last.iota.pattern) { + SpecialPatterns.INTROSPECTION -> -1 + SpecialPatterns.RETROSPECTION -> 1 + else -> 0 + } + this.image.copy(parenthesized = newParens, parenCount = newParenCount) to + if (last == null) ResolvedPatternType.ERRORED else ResolvedPatternType.UNDONE + } + SpecialPatterns.INTROSPECTION.angles -> { + // we have escaped the parens onto the stack; we just also record our count. + val newParens = this.image.parenthesized.toMutableList() + newParens.add(ParenthesizedIota(iota, false)) + this.image.copy(parenthesized = newParens, parenCount = this.image.parenCount + 1) to + if (this.image.parenCount == 0) ResolvedPatternType.EVALUATED + else ResolvedPatternType.ESCAPED + } + SpecialPatterns.RETROSPECTION.angles -> { + val newParenCount = this.image.parenCount - 1 + displayDepth-- + if (newParenCount == 0) { + val newStack = this.image.stack.toMutableList() + newStack.add(ListIota(this.image.parenthesized.toList().map { it.iota })) + this.image.copy( + stack = newStack, + parenCount = newParenCount, + parenthesized = listOf() + ) to ResolvedPatternType.EVALUATED + } else if (newParenCount < 0) { + throw MishapTooManyCloseParens() + } else { + // we have this situation: "(()" + // we need to add the close paren + val newParens = this.image.parenthesized.toMutableList() + newParens.add(ParenthesizedIota(iota, false)) + this.image.copy(parenCount = newParenCount, parenthesized = newParens) to + ResolvedPatternType.ESCAPED + } + } + else -> { + val newParens = this.image.parenthesized.toMutableList() + newParens.add(ParenthesizedIota(iota, false)) + this.image.copy(parenthesized = newParens) to ResolvedPatternType.ESCAPED + } + } + } + } else if (this.image.escapeNext) { + val newStack = this.image.stack.toMutableList() + newStack.add(iota) + this.image.copy( + stack = newStack, + escapeNext = false, + ) to ResolvedPatternType.ESCAPED + } else { + when (sig) { + SpecialPatterns.CONSIDERATION.angles -> { + this.image.copy(escapeNext = true) to ResolvedPatternType.EVALUATED + } + SpecialPatterns.INTROSPECTION.angles -> { + this.image.copy(parenCount = this.image.parenCount + 1) to ResolvedPatternType.EVALUATED + } + SpecialPatterns.RETROSPECTION.angles -> { + throw MishapTooManyCloseParens() + } + else -> { + null + } + } + } - SpecialPatterns.EVANITION.angles -> { - val newParens = this.image.parenthesized.toMutableList() - val last = newParens.removeLastOrNull() - val newParenCount = this.image.parenCount + if (last == null || last.escaped || last.iota !is PatternIota) 0 else when (last.iota.pattern) { - SpecialPatterns.INTROSPECTION -> -1 - SpecialPatterns.RETROSPECTION -> 1 - else -> 0 - } - this.image.copy(parenthesized = newParens, parenCount = newParenCount) to if (last == null) ResolvedPatternType.ERRORED else ResolvedPatternType.UNDONE - } + // TODO: replace this once we can read things from the client + /* + if (out != null) { + val display = if (iota is PatternIota) { + PatternNameHelper.representationForPattern(iota.pattern) + .copy() + .withStyle(if (out.second == ResolvedPatternType.ESCAPED) ChatFormatting.YELLOW else ChatFormatting.AQUA) + } else iota.display() + displayPatternDebug(this.escapeNext, displayDepth, display) + } + */ + return out + } - SpecialPatterns.INTROSPECTION.angles -> { - // we have escaped the parens onto the stack; we just also record our count. - val newParens = this.image.parenthesized.toMutableList() - newParens.add(ParenthesizedIota(iota, false)) - this.image.copy( - parenthesized = newParens, - parenCount = this.image.parenCount + 1 - ) to if (this.image.parenCount == 0) ResolvedPatternType.EVALUATED else ResolvedPatternType.ESCAPED - } + data class TempControllerInfo( + var earlyExit: Boolean, + ) - SpecialPatterns.RETROSPECTION.angles -> { - val newParenCount = this.image.parenCount - 1 - displayDepth-- - if (newParenCount == 0) { - val newStack = this.image.stack.toMutableList() - newStack.add(ListIota(this.image.parenthesized.toList().map { it.iota })) - this.image.copy( - stack = newStack, - parenCount = newParenCount, - parenthesized = listOf() - ) to ResolvedPatternType.EVALUATED - } else if (newParenCount < 0) { - throw MishapTooManyCloseParens() - } else { - // we have this situation: "(()" - // we need to add the close paren - val newParens = this.image.parenthesized.toMutableList() - newParens.add(ParenthesizedIota(iota, false)) - this.image.copy( - parenCount = newParenCount, - parenthesized = newParens - ) to ResolvedPatternType.ESCAPED - } - } - - else -> { - val newParens = this.image.parenthesized.toMutableList() - newParens.add(ParenthesizedIota(iota, false)) - this.image.copy( - parenthesized = newParens - ) to ResolvedPatternType.ESCAPED - } - } - } - } else if (this.image.escapeNext) { - val newStack = this.image.stack.toMutableList() - newStack.add(iota) - this.image.copy( - stack = newStack, - escapeNext = false, - ) to ResolvedPatternType.ESCAPED - } else { - when (sig) { - SpecialPatterns.CONSIDERATION.angles -> { - this.image.copy( - escapeNext = true - ) to ResolvedPatternType.EVALUATED - } - - SpecialPatterns.INTROSPECTION.angles -> { - this.image.copy( - parenCount = this.image.parenCount + 1 - ) to ResolvedPatternType.EVALUATED - } - - SpecialPatterns.RETROSPECTION.angles -> { - throw MishapTooManyCloseParens() - } - - else -> { - null - } - } - } - - // TODO: replace this once we can read things from the client - /* - if (out != null) { - val display = if (iota is PatternIota) { - PatternNameHelper.representationForPattern(iota.pattern) - .copy() - .withStyle(if (out.second == ResolvedPatternType.ESCAPED) ChatFormatting.YELLOW else ChatFormatting.AQUA) - } else iota.display() - displayPatternDebug(this.escapeNext, displayDepth, display) - } - */ - return out - } - - data class TempControllerInfo( - var earlyExit: Boolean, - ) - - companion object { - @JvmStatic - fun empty(env: CastingEnvironment): CastingVM { - return CastingVM(CastingImage(), env) - } - } + companion object { + @JvmStatic + fun empty(env: CastingEnvironment): CastingVM { + return CastingVM(CastingImage(), env) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt index 8000ec09aa..a3b4cebed9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt @@ -12,97 +12,102 @@ import net.minecraft.server.level.ServerLevel /** * A single frame of evaluation during the execution of a spell. * - * Specifically, an evaluation will keep a stack of these frames. - * An evaluation with no meta-eval will consist of a single [Evaluate(rest of the pats)] at all times. - * When an Eval is invoked, we push Evaluate(pats) to the top of the stack. + * Specifically, an evaluation will keep a stack of these frames. An evaluation with no meta-eval + * will consist of a single [Evaluate(rest of the pats)] at all times. When an Eval is invoked, we + * push Evaluate(pats) to the top of the stack. * * Evaluation is performed by repeatedly popping the top-most (i.e. innermost) frame from the stack, - * then evaluating that frame (and possibly allowing it to push other frames (e.g. if it's a Hermes)). + * then evaluating that frame (and possibly allowing it to push other frames (e.g. if it's a + * Hermes)). * * Once the stack of frames is empty, there are no more computations to run, so we're done. - * */ interface ContinuationFrame { - /** - * Step the evaluation forward once. - * For Evaluate, this consumes one pattern; for ForEach this queues the next iteration of the outer loop. - * @return the result of this pattern step - */ - fun evaluate(continuation: SpellContinuation, level: ServerLevel, harness: CastingVM): CastResult + /** + * Step the evaluation forward once. For Evaluate, this consumes one pattern; for ForEach this + * queues the next iteration of the outer loop. + * + * @return the result of this pattern step + */ + fun evaluate(continuation: SpellContinuation, level: ServerLevel, harness: CastingVM): CastResult - /** - * The OpHalt instruction wants us to "jump to" the END of the nearest meta-eval. - * In other words, we should consume Evaluate frames until we hit a FinishEval or Thoth frame. - * @return whether the break should stop here, alongside the new stack state (e.g. for finalizing a Thoth) - */ - fun breakDownwards(stack: List<Iota>): Pair<Boolean, List<Iota>> + /** + * The OpHalt instruction wants us to "jump to" the END of the nearest meta-eval. In other words, + * we should consume Evaluate frames until we hit a FinishEval or Thoth frame. + * + * @return whether the break should stop here, alongside the new stack state (e.g. for finalizing + * a Thoth) + */ + fun breakDownwards(stack: List<Iota>): Pair<Boolean, List<Iota>> - /** - * Serializes this frame. Used for things like delays, where we pause execution. - */ - fun serializeToNBT(): CompoundTag + /** Serializes this frame. Used for things like delays, where we pause execution. */ + fun serializeToNBT(): CompoundTag - /** - * Return the number of iotas contained inside this frame, used for determining whether it is valid to serialise. - */ - fun size(): Int + /** + * Return the number of iotas contained inside this frame, used for determining whether it is + * valid to serialise. + */ + fun size(): Int - val type: Type<*> + val type: Type<*> - interface Type<U : ContinuationFrame> { - fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): U? - } + interface Type<U : ContinuationFrame> { + fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): U? + } - companion object { - /** - * Takes a tag containing the ContinuationFrame.Type resourcelocation and the serialized continuation frame, and returns - * the deserialized continuation frame. - */ - @JvmStatic - fun fromNBT(tag: CompoundTag, world: ServerLevel): ContinuationFrame { - val type = getTypeFromTag(tag) ?: return FrameEvaluate(SpellList.LList(0, listOf()), false) + companion object { + /** + * Takes a tag containing the ContinuationFrame.Type resourcelocation and the serialized + * continuation frame, and returns the deserialized continuation frame. + */ + @JvmStatic + fun fromNBT(tag: CompoundTag, world: ServerLevel): ContinuationFrame { + val type = getTypeFromTag(tag) ?: return FrameEvaluate(SpellList.LList(0, listOf()), false) - return (tag.get(HexContinuationTypes.KEY_DATA) as? CompoundTag)?.let { type.deserializeFromNBT(it, world) } - ?: FrameEvaluate(SpellList.LList(0, listOf()), false) - } + return (tag.get(HexContinuationTypes.KEY_DATA) as? CompoundTag)?.let { + type.deserializeFromNBT(it, world) + } ?: FrameEvaluate(SpellList.LList(0, listOf()), false) + } - /** - * Takes a continuation frame and serializes it along with its type. - */ - @JvmStatic - fun toNBT(frame: ContinuationFrame): CompoundTag { - val type = frame.type - val typeId = HexContinuationTypes.REGISTRY.getKey(type) - ?: throw IllegalStateException( - "Tried to serialize an unregistered continuation type. Continuation: " + frame - + " ; Type" + type.javaClass.typeName) + /** Takes a continuation frame and serializes it along with its type. */ + @JvmStatic + fun toNBT(frame: ContinuationFrame): CompoundTag { + val type = frame.type + val typeId = + HexContinuationTypes.REGISTRY.getKey(type) + ?: throw IllegalStateException( + "Tried to serialize an unregistered continuation type. Continuation: " + + frame + + " ; Type" + + type.javaClass.typeName + ) - val data = frame.serializeToNBT() + val data = frame.serializeToNBT() - val out = CompoundTag() - out.putString(HexContinuationTypes.KEY_TYPE, typeId.toString()) - out.put(HexContinuationTypes.KEY_DATA, data) - return out - } + val out = CompoundTag() + out.putString(HexContinuationTypes.KEY_TYPE, typeId.toString()) + out.put(HexContinuationTypes.KEY_DATA, data) + return out + } - /** - * This method attempts to find the type from the `type` key. - * See [ContinuationFrame.serializeToNBT] for the storage format. - * - * @return `null` if it cannot get the type. - */ - private fun getTypeFromTag(tag: CompoundTag): Type<*>? { - if (!tag.contains(HexContinuationTypes.KEY_TYPE, Tag.TAG_STRING.toInt())) { - return null - } + /** + * This method attempts to find the type from the `type` key. See + * [ContinuationFrame.serializeToNBT] for the storage format. + * + * @return `null` if it cannot get the type. + */ + private fun getTypeFromTag(tag: CompoundTag): Type<*>? { + if (!tag.contains(HexContinuationTypes.KEY_TYPE, Tag.TAG_STRING.toInt())) { + return null + } - val typeKey = tag.getString(HexContinuationTypes.KEY_TYPE) - if (!ResourceLocation.isValidResourceLocation(typeKey)) { - return null - } + val typeKey = tag.getString(HexContinuationTypes.KEY_TYPE) + if (!ResourceLocation.isValidResourceLocation(typeKey)) { + return null + } - val typeLoc = ResourceLocation(typeKey) - return HexContinuationTypes.REGISTRY[typeLoc] - } - } + val typeLoc = ResourceLocation(typeKey) + return HexContinuationTypes.REGISTRY[typeLoc] + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt index 141148dfdc..174579bab6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt @@ -16,59 +16,66 @@ import net.minecraft.server.level.ServerLevel /** * A list of patterns to be evaluated in sequence. + * * @property list the *remaining* list of patterns to be evaluated * @property isMetacasting only for sound effects, if this is being cast from a hermes / iris */ data class FrameEvaluate(val list: SpellList, val isMetacasting: Boolean) : ContinuationFrame { - // Discard this frame and keep discarding frames. - override fun breakDownwards(stack: List<Iota>) = false to stack + // Discard this frame and keep discarding frames. + override fun breakDownwards(stack: List<Iota>) = false to stack - // Step the list of patterns, evaluating a single one. - override fun evaluate( - continuation: SpellContinuation, - level: ServerLevel, - harness: CastingVM - ): CastResult { - // If there are patterns left... - return if (list.nonEmpty) { - val newCont = if (list.cdr.nonEmpty) { // yay TCO - // ...enqueue the evaluation of the rest of the patterns... - continuation.pushFrame(FrameEvaluate(list.cdr, this.isMetacasting)) - } else continuation - // ...before evaluating the first one in the list. - val update = harness.executeInner(list.car, level, newCont) - if (this.isMetacasting && update.sound != HexEvalSounds.MISHAP) { - update.copy(sound = HexEvalSounds.HERMES) - } else { - update - } - } else { - // If there are no patterns (e.g. empty Hermes), just return OK. - CastResult(ListIota(list), continuation, null, listOf(), ResolvedPatternType.EVALUATED, HexEvalSounds.HERMES) - } - } + // Step the list of patterns, evaluating a single one. + override fun evaluate( + continuation: SpellContinuation, + level: ServerLevel, + harness: CastingVM + ): CastResult { + // If there are patterns left... + return if (list.nonEmpty) { + val newCont = + if (list.cdr.nonEmpty) { // yay TCO + // ...enqueue the evaluation of the rest of the patterns... + continuation.pushFrame(FrameEvaluate(list.cdr, this.isMetacasting)) + } else continuation + // ...before evaluating the first one in the list. + val update = harness.executeInner(list.car, level, newCont) + if (this.isMetacasting && update.sound != HexEvalSounds.MISHAP) { + update.copy(sound = HexEvalSounds.HERMES) + } else { + update + } + } else { + // If there are no patterns (e.g. empty Hermes), just return OK. + CastResult( + ListIota(list), + continuation, + null, + listOf(), + ResolvedPatternType.EVALUATED, + HexEvalSounds.HERMES + ) + } + } - override fun serializeToNBT() = NBTBuilder { - "patterns" %= list.serializeToNBT() - "isMetacasting" %= isMetacasting - } + override fun serializeToNBT() = NBTBuilder { + "patterns" %= list.serializeToNBT() + "isMetacasting" %= isMetacasting + } - override fun size() = list.size() + override fun size() = list.size() - override val type: ContinuationFrame.Type<*> = TYPE + override val type: ContinuationFrame.Type<*> = TYPE - companion object { - @JvmField - val TYPE: ContinuationFrame.Type<FrameEvaluate> = object : ContinuationFrame.Type<FrameEvaluate> { - override fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): FrameEvaluate { - return FrameEvaluate( - HexIotaTypes.LIST.deserialize( - tag.getList("patterns", Tag.TAG_COMPOUND), - world - )!!.list, - tag.getBoolean("isMetacasting")) - } - - } - } -} \ No newline at end of file + companion object { + @JvmField + val TYPE: ContinuationFrame.Type<FrameEvaluate> = + object : ContinuationFrame.Type<FrameEvaluate> { + override fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): FrameEvaluate { + return FrameEvaluate( + HexIotaTypes.LIST.deserialize(tag.getList("patterns", Tag.TAG_COMPOUND), world)!!.list, + tag.getBoolean("isMetacasting") + ) + } + } + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt index 72bbb8c80c..f9c54090fa 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt @@ -4,43 +4,43 @@ import at.petrak.hexcasting.api.casting.eval.CastResult import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.NullIota -import at.petrak.hexcasting.api.utils.NBTBuilder import at.petrak.hexcasting.common.lib.hex.HexEvalSounds import net.minecraft.nbt.CompoundTag import net.minecraft.server.level.ServerLevel /** - * A stack marker representing the end of a Hermes evaluation, - * so that we know when to stop removing frames during a Halt. + * A stack marker representing the end of a Hermes evaluation, so that we know when to stop removing + * frames during a Halt. */ object FrameFinishEval : ContinuationFrame { - // Don't do anything else to the stack, just finish the halt statement. - override fun breakDownwards(stack: List<Iota>) = true to stack + // Don't do anything else to the stack, just finish the halt statement. + override fun breakDownwards(stack: List<Iota>) = true to stack - // Evaluating it does nothing; it's only a boundary condition. - override fun evaluate( - continuation: SpellContinuation, - level: ServerLevel, - harness: CastingVM - ): CastResult { - return CastResult( - NullIota(), - continuation, - null, - listOf(), - ResolvedPatternType.EVALUATED, - HexEvalSounds.NOTHING, - ) - } + // Evaluating it does nothing; it's only a boundary condition. + override fun evaluate( + continuation: SpellContinuation, + level: ServerLevel, + harness: CastingVM + ): CastResult { + return CastResult( + NullIota(), + continuation, + null, + listOf(), + ResolvedPatternType.EVALUATED, + HexEvalSounds.NOTHING, + ) + } - override fun serializeToNBT() = CompoundTag() + override fun serializeToNBT() = CompoundTag() - override fun size() = 0 + override fun size() = 0 - @JvmField - val TYPE: ContinuationFrame.Type<FrameFinishEval> = object : ContinuationFrame.Type<FrameFinishEval> { - override fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel) = FrameFinishEval - } + @JvmField + val TYPE: ContinuationFrame.Type<FrameFinishEval> = + object : ContinuationFrame.Type<FrameFinishEval> { + override fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel) = FrameFinishEval + } - override val type = TYPE + override val type = TYPE } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt index 0221c1f36d..9e8e8e8c31 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt @@ -16,101 +16,107 @@ import net.minecraft.nbt.Tag import net.minecraft.server.level.ServerLevel /** - * A frame representing all the state for a Thoth evaluation. - * Pushed by an OpForEach. - * @property first whether the input stack state is the first one (since we don't want to save the base-stack before any changes are made) + * A frame representing all the state for a Thoth evaluation. Pushed by an OpForEach. + * + * @property first whether the input stack state is the first one (since we don't want to save the + * base-stack before any changes are made) * @property data list of *remaining* datums to ForEach over * @property code code to run per datum * @property baseStack the stack state at Thoth entry * @property acc concatenated list of final stack states after Thoth exit */ data class FrameForEach( - val data: SpellList, - val code: SpellList, - val baseStack: List<Iota>?, - val acc: MutableList<Iota> + val data: SpellList, + val code: SpellList, + val baseStack: List<Iota>?, + val acc: MutableList<Iota> ) : ContinuationFrame { - /** When halting, we add the stack state at halt to the stack accumulator, then return the original pre-Thoth stack, plus the accumulator. */ - override fun breakDownwards(stack: List<Iota>): Pair<Boolean, List<Iota>> { - val newStack = baseStack?.toMutableList() ?: mutableListOf() - acc.addAll(stack) - newStack.add(ListIota(acc)) - return true to newStack - } + /** + * When halting, we add the stack state at halt to the stack accumulator, then return the original + * pre-Thoth stack, plus the accumulator. + */ + override fun breakDownwards(stack: List<Iota>): Pair<Boolean, List<Iota>> { + val newStack = baseStack?.toMutableList() ?: mutableListOf() + acc.addAll(stack) + newStack.add(ListIota(acc)) + return true to newStack + } - /** Step the Thoth computation, enqueueing one code evaluation. */ - override fun evaluate( - continuation: SpellContinuation, - level: ServerLevel, - harness: CastingVM - ): CastResult { - // If this isn't the very first Thoth step (i.e. no Thoth computations run yet)... - val stack = if (baseStack == null) { - // init stack to the harness stack... - harness.image.stack.toList() - } else { - // else save the stack to the accumulator and reuse the saved base stack. - acc.addAll(harness.image.stack) - baseStack - } + /** Step the Thoth computation, enqueueing one code evaluation. */ + override fun evaluate( + continuation: SpellContinuation, + level: ServerLevel, + harness: CastingVM + ): CastResult { + // If this isn't the very first Thoth step (i.e. no Thoth computations run yet)... + val stack = + if (baseStack == null) { + // init stack to the harness stack... + harness.image.stack.toList() + } else { + // else save the stack to the accumulator and reuse the saved base stack. + acc.addAll(harness.image.stack) + baseStack + } - // If we still have data to process... - val (stackTop, newImage, newCont) = if (data.nonEmpty) { - // push the next datum to the top of the stack, - val cont2 = continuation - // put the next Thoth object back on the stack for the next Thoth cycle, - .pushFrame(FrameForEach(data.cdr, code, stack, acc)) - // and prep the Thoth'd code block for evaluation. - .pushFrame(FrameEvaluate(code, true)) - Triple(data.car, harness.image.withUsedOp(), cont2) - } else { - // Else, dump our final list onto the stack. - Triple(ListIota(acc), harness.image, continuation) - } - val tStack = stack.toMutableList() - tStack.add(stackTop) - return CastResult( - ListIota(code), - newCont, - // reset escapes so they don't carry over to other iterations or out of thoth - newImage.withResetEscape().copy(stack = tStack), - listOf(), - ResolvedPatternType.EVALUATED, - HexEvalSounds.THOTH, - ) - } + // If we still have data to process... + val (stackTop, newImage, newCont) = + if (data.nonEmpty) { + // push the next datum to the top of the stack, + val cont2 = + continuation + // put the next Thoth object back on the stack for the next Thoth cycle, + .pushFrame(FrameForEach(data.cdr, code, stack, acc)) + // and prep the Thoth'd code block for evaluation. + .pushFrame(FrameEvaluate(code, true)) + Triple(data.car, harness.image.withUsedOp(), cont2) + } else { + // Else, dump our final list onto the stack. + Triple(ListIota(acc), harness.image, continuation) + } + val tStack = stack.toMutableList() + tStack.add(stackTop) + return CastResult( + ListIota(code), + newCont, + // reset escapes so they don't carry over to other iterations or out of thoth + newImage.withResetEscape().copy(stack = tStack), + listOf(), + ResolvedPatternType.EVALUATED, + HexEvalSounds.THOTH, + ) + } - override fun serializeToNBT() = NBTBuilder { - "data" %= data.serializeToNBT() - "code" %= code.serializeToNBT() - if (baseStack != null) - "base" %= baseStack.serializeToNBT() - "accumulator" %= acc.serializeToNBT() - } + override fun serializeToNBT() = NBTBuilder { + "data" %= data.serializeToNBT() + "code" %= code.serializeToNBT() + if (baseStack != null) "base" %= baseStack.serializeToNBT() + "accumulator" %= acc.serializeToNBT() + } - override fun size() = data.size() + code.size() + acc.size + (baseStack?.size ?: 0) + override fun size() = data.size() + code.size() + acc.size + (baseStack?.size ?: 0) - override val type: ContinuationFrame.Type<*> = TYPE + override val type: ContinuationFrame.Type<*> = TYPE - companion object { - @JvmField - val TYPE: ContinuationFrame.Type<FrameForEach> = object : ContinuationFrame.Type<FrameForEach> { - override fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): FrameForEach { - return FrameForEach( - HexIotaTypes.LIST.deserialize(tag.getList("data", Tag.TAG_COMPOUND), world)!!.list, - HexIotaTypes.LIST.deserialize(tag.getList("code", Tag.TAG_COMPOUND), world)!!.list, - if (tag.hasList("base", Tag.TAG_COMPOUND)) - HexIotaTypes.LIST.deserialize(tag.getList("base", Tag.TAG_COMPOUND), world)!!.list.toList() - else - null, - HexIotaTypes.LIST.deserialize( - tag.getList("accumulator", Tag.TAG_COMPOUND), - world - )!!.list.toMutableList() - ) - } - - } - } + companion object { + @JvmField + val TYPE: ContinuationFrame.Type<FrameForEach> = + object : ContinuationFrame.Type<FrameForEach> { + override fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): FrameForEach { + return FrameForEach( + HexIotaTypes.LIST.deserialize(tag.getList("data", Tag.TAG_COMPOUND), world)!!.list, + HexIotaTypes.LIST.deserialize(tag.getList("code", Tag.TAG_COMPOUND), world)!!.list, + if (tag.hasList("base", Tag.TAG_COMPOUND)) + HexIotaTypes.LIST.deserialize(tag.getList("base", Tag.TAG_COMPOUND), world)!! + .list + .toList() + else null, + HexIotaTypes.LIST.deserialize(tag.getList("accumulator", Tag.TAG_COMPOUND), world)!! + .list + .toMutableList() + ) + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FunctionalData.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FunctionalData.kt index 49f3d149d0..ad6794a2da 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FunctionalData.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FunctionalData.kt @@ -2,14 +2,11 @@ package at.petrak.hexcasting.api.casting.eval.vm import at.petrak.hexcasting.api.casting.iota.Iota -/** - * A change to the data in a CastHarness after a pattern is drawn. - */ +/** A change to the data in a CastHarness after a pattern is drawn. */ data class FunctionalData( - val stack: List<Iota>, - val parenCount: Int, - val parenthesized: List<Iota>, - val escapeNext: Boolean, - val ravenmind: Iota? + val stack: List<Iota>, + val parenCount: Int, + val parenthesized: List<Iota>, + val escapeNext: Boolean, + val ravenmind: Iota? ) - diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/SpellContinuation.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/SpellContinuation.kt index ec706c2858..67a0381d6f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/SpellContinuation.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/SpellContinuation.kt @@ -6,41 +6,39 @@ import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.Tag import net.minecraft.server.level.ServerLevel -/** - * A continuation during the execution of a spell. - */ +/** A continuation during the execution of a spell. */ sealed interface SpellContinuation { - object Done : SpellContinuation - - data class NotDone(val frame: ContinuationFrame, val next: SpellContinuation) : SpellContinuation - - fun pushFrame(frame: ContinuationFrame): SpellContinuation = NotDone(frame, this) - - fun serializeToNBT() = NBTBuilder { - TAG_FRAME %= list(getNBTFrames()) - } - fun getNBTFrames(): List<CompoundTag> { - var self = this - val frames = mutableListOf<CompoundTag>() - while (self is NotDone) { - frames.add(ContinuationFrame.toNBT(self.frame)) - self = self.next - } - return frames - } - companion object { - const val TAG_FRAME = "frame" - - @JvmStatic - fun fromNBT(nbt: CompoundTag, world: ServerLevel): SpellContinuation { - val frames = nbt.getList(TAG_FRAME, Tag.TAG_COMPOUND) - var result: SpellContinuation = Done - for (frame in frames.asReversed()) { - if (frame is CompoundTag) { - result = result.pushFrame(ContinuationFrame.fromNBT(frame, world)) - } - } - return result - } - } + object Done : SpellContinuation + + data class NotDone(val frame: ContinuationFrame, val next: SpellContinuation) : SpellContinuation + + fun pushFrame(frame: ContinuationFrame): SpellContinuation = NotDone(frame, this) + + fun serializeToNBT() = NBTBuilder { TAG_FRAME %= list(getNBTFrames()) } + + fun getNBTFrames(): List<CompoundTag> { + var self = this + val frames = mutableListOf<CompoundTag>() + while (self is NotDone) { + frames.add(ContinuationFrame.toNBT(self.frame)) + self = self.next + } + return frames + } + + companion object { + const val TAG_FRAME = "frame" + + @JvmStatic + fun fromNBT(nbt: CompoundTag, world: ServerLevel): SpellContinuation { + val frames = nbt.getList(TAG_FRAME, Tag.TAG_COMPOUND) + var result: SpellContinuation = Done + for (frame in frames.asReversed()) { + if (frame is CompoundTag) { + result = result.pushFrame(ContinuationFrame.fromNBT(frame, world)) + } + } + return result + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/BooleanIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/BooleanIota.java index 91cf0b339d..8f875593f8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/BooleanIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/BooleanIota.java @@ -11,58 +11,57 @@ import org.jetbrains.annotations.Nullable; public class BooleanIota extends Iota { - public BooleanIota(boolean d) { - super(HexIotaTypes.BOOLEAN, d); - } + public BooleanIota(boolean d) { + super(HexIotaTypes.BOOLEAN, d); + } - public boolean getBool() { - return (boolean) this.payload; - } + public boolean getBool() { + return (boolean) this.payload; + } - @Override - public boolean isTruthy() { - return this.getBool(); - } + @Override + public boolean isTruthy() { + return this.getBool(); + } - @Override - public boolean toleratesOther(Iota that) { - return typesMatch(this, that) - && that instanceof BooleanIota b - && this.getBool() == b.getBool(); - } + @Override + public boolean toleratesOther(Iota that) { + return typesMatch(this, that) && that instanceof BooleanIota b && this.getBool() == b.getBool(); + } - @Override - public @NotNull Tag serialize() { - // there is no boolean tag :( - return ByteTag.valueOf(this.getBool()); - } + @Override + public @NotNull Tag serialize() { + // there is no boolean tag :( + return ByteTag.valueOf(this.getBool()); + } - public static IotaType<BooleanIota> TYPE = new IotaType<>() { - @Nullable - @Override - public BooleanIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return BooleanIota.deserialize(tag); - } + public static IotaType<BooleanIota> TYPE = + new IotaType<>() { + @Nullable @Override + public BooleanIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { + return BooleanIota.deserialize(tag); + } - @Override - public Component display(Tag tag) { - return BooleanIota.display(BooleanIota.deserialize(tag).getBool()); - } + @Override + public Component display(Tag tag) { + return BooleanIota.display(BooleanIota.deserialize(tag).getBool()); + } - @Override - public int color() { - // We can't set red or green ... so do yellow, I guess - return 0xff_ffff55; - } - }; + @Override + public int color() { + // We can't set red or green ... so do yellow, I guess + return 0xff_ffff55; + } + }; - public static BooleanIota deserialize(Tag tag) throws IllegalArgumentException { - var dtag = HexUtils.downcast(tag, ByteTag.TYPE); - return new BooleanIota(dtag.getAsByte() != 0); - } + public static BooleanIota deserialize(Tag tag) throws IllegalArgumentException { + var dtag = HexUtils.downcast(tag, ByteTag.TYPE); + return new BooleanIota(dtag.getAsByte() != 0); + } - public static Component display(boolean b) { - return Component.translatable(b ? "hexcasting.tooltip.boolean_true" : "hexcasting.tooltip.boolean_false") - .withStyle(b ? ChatFormatting.DARK_GREEN : ChatFormatting.DARK_RED); - } + public static Component display(boolean b) { + return Component.translatable( + b ? "hexcasting.tooltip.boolean_true" : "hexcasting.tooltip.boolean_false") + .withStyle(b ? ChatFormatting.DARK_GREEN : ChatFormatting.DARK_RED); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ContinuationIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ContinuationIota.java index 13764c4675..cd1ba9458f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ContinuationIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ContinuationIota.java @@ -7,6 +7,7 @@ import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexEvalSounds; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import java.util.List; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; @@ -14,76 +15,83 @@ import net.minecraft.server.level.ServerLevel; import org.jetbrains.annotations.NotNull; -import java.util.List; - -/** - * An iota storing a continuation (in essence an execution state). - */ +/** An iota storing a continuation (in essence an execution state). */ public class ContinuationIota extends Iota { - public static final Component DISPLAY = Component.translatable("hexcasting.tooltip.jump_iota").withStyle(ChatFormatting.RED); + public static final Component DISPLAY = + Component.translatable("hexcasting.tooltip.jump_iota").withStyle(ChatFormatting.RED); - public ContinuationIota(SpellContinuation cont) { - super(HexIotaTypes.CONTINUATION, cont); - } + public ContinuationIota(SpellContinuation cont) { + super(HexIotaTypes.CONTINUATION, cont); + } - public SpellContinuation getContinuation() { - return (SpellContinuation) this.payload; - } + public SpellContinuation getContinuation() { + return (SpellContinuation) this.payload; + } - @Override - public boolean isTruthy() { - return true; - } + @Override + public boolean isTruthy() { + return true; + } - @Override - public boolean toleratesOther(Iota that) { - return typesMatch(this, that) && that instanceof ContinuationIota cont && cont.getContinuation().equals(getContinuation()); - } + @Override + public boolean toleratesOther(Iota that) { + return typesMatch(this, that) + && that instanceof ContinuationIota cont + && cont.getContinuation().equals(getContinuation()); + } - @Override - public @NotNull - Tag serialize() { - return getContinuation().serializeToNBT(); - } + @Override + public @NotNull Tag serialize() { + return getContinuation().serializeToNBT(); + } - @Override - public @NotNull CastResult execute(CastingVM vm, ServerLevel world, SpellContinuation continuation) { - return new CastResult(this, this.getContinuation(), vm.getImage(), List.of(), ResolvedPatternType.EVALUATED, HexEvalSounds.HERMES); - } + @Override + public @NotNull CastResult execute( + CastingVM vm, ServerLevel world, SpellContinuation continuation) { + return new CastResult( + this, + this.getContinuation(), + vm.getImage(), + List.of(), + ResolvedPatternType.EVALUATED, + HexEvalSounds.HERMES); + } - @Override - public boolean executable() { - return true; - } + @Override + public boolean executable() { + return true; + } - @Override - public int size() { - var continuation = this.getContinuation(); - var size = 0; - while (continuation instanceof SpellContinuation.NotDone notDone) { - size += 1; - size += notDone.component1().size(); - continuation = notDone.component2(); - } + @Override + public int size() { + var continuation = this.getContinuation(); + var size = 0; + while (continuation instanceof SpellContinuation.NotDone notDone) { + size += 1; + size += notDone.component1().size(); + continuation = notDone.component2(); + } - return Math.min(size, 1); - } + return Math.min(size, 1); + } - public static IotaType<ContinuationIota> TYPE = new IotaType<>() { - @Override - public @NotNull ContinuationIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - var compoundTag = HexUtils.downcast(tag, CompoundTag.TYPE); - return new ContinuationIota(SpellContinuation.fromNBT(compoundTag, world)); - } + public static IotaType<ContinuationIota> TYPE = + new IotaType<>() { + @Override + public @NotNull ContinuationIota deserialize(Tag tag, ServerLevel world) + throws IllegalArgumentException { + var compoundTag = HexUtils.downcast(tag, CompoundTag.TYPE); + return new ContinuationIota(SpellContinuation.fromNBT(compoundTag, world)); + } - @Override - public Component display(Tag tag) { - return DISPLAY; - } + @Override + public Component display(Tag tag) { + return DISPLAY; + } - @Override - public int color() { - return 0xff_cc0000; - } - }; + @Override + public int color() { + return 0xff_cc0000; + } + }; } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/DoubleIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/DoubleIota.java index e9ff20f57c..43e6831cb7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/DoubleIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/DoubleIota.java @@ -11,61 +11,61 @@ import org.jetbrains.annotations.Nullable; public class DoubleIota extends Iota { - public static final double TOLERANCE = 0.0001; + public static final double TOLERANCE = 0.0001; - public DoubleIota(double d) { - super(HexIotaTypes.DOUBLE, d); - } + public DoubleIota(double d) { + super(HexIotaTypes.DOUBLE, d); + } - public double getDouble() { - return HexUtils.fixNAN((Double) this.payload); - } + public double getDouble() { + return HexUtils.fixNAN((Double) this.payload); + } - @Override - public boolean isTruthy() { - return this.getDouble() != 0.0; - } + @Override + public boolean isTruthy() { + return this.getDouble() != 0.0; + } - @Override - public boolean toleratesOther(Iota that) { - return typesMatch(this, that) - && that instanceof DoubleIota dd - && tolerates(this.getDouble(), dd.getDouble()); - } + @Override + public boolean toleratesOther(Iota that) { + return typesMatch(this, that) + && that instanceof DoubleIota dd + && tolerates(this.getDouble(), dd.getDouble()); + } - public static boolean tolerates(double a, double b) { - return Math.abs(a - b) < TOLERANCE; - } + public static boolean tolerates(double a, double b) { + return Math.abs(a - b) < TOLERANCE; + } - @Override - public @NotNull Tag serialize() { - return DoubleTag.valueOf(this.getDouble()); - } + @Override + public @NotNull Tag serialize() { + return DoubleTag.valueOf(this.getDouble()); + } - public static IotaType<DoubleIota> TYPE = new IotaType<>() { - @Nullable - @Override - public DoubleIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return DoubleIota.deserialize(tag); - } + public static IotaType<DoubleIota> TYPE = + new IotaType<>() { + @Nullable @Override + public DoubleIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { + return DoubleIota.deserialize(tag); + } - @Override - public Component display(Tag tag) { - return DoubleIota.display(DoubleIota.deserialize(tag).getDouble()); - } + @Override + public Component display(Tag tag) { + return DoubleIota.display(DoubleIota.deserialize(tag).getDouble()); + } - @Override - public int color() { - return 0xff_55ff55; - } - }; + @Override + public int color() { + return 0xff_55ff55; + } + }; - public static DoubleIota deserialize(Tag tag) throws IllegalArgumentException { - var dtag = HexUtils.downcast(tag, DoubleTag.TYPE); - return new DoubleIota(dtag.getAsDouble()); - } + public static DoubleIota deserialize(Tag tag) throws IllegalArgumentException { + var dtag = HexUtils.downcast(tag, DoubleTag.TYPE); + return new DoubleIota(dtag.getAsDouble()); + } - public static Component display(double d) { - return Component.literal(String.format("%.2f", d)).withStyle(ChatFormatting.GREEN); - } + public static Component display(double d) { + return Component.literal(String.format("%.2f", d)).withStyle(ChatFormatting.GREEN); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/EntityIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/EntityIota.java index 2a8023cf01..1680081206 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/EntityIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/EntityIota.java @@ -18,89 +18,91 @@ import org.jetbrains.annotations.Nullable; public class EntityIota extends Iota { - public EntityIota(@NotNull Entity e) { - super(HexIotaTypes.ENTITY, e); - } + public EntityIota(@NotNull Entity e) { + super(HexIotaTypes.ENTITY, e); + } - public Entity getEntity() { - return (Entity) this.payload; - } + public Entity getEntity() { + return (Entity) this.payload; + } - @Override - public boolean toleratesOther(Iota that) { - return typesMatch(this, that) - && that instanceof EntityIota dent - && this.getEntity() == dent.getEntity(); - } + @Override + public boolean toleratesOther(Iota that) { + return typesMatch(this, that) + && that instanceof EntityIota dent + && this.getEntity() == dent.getEntity(); + } - @Override - public boolean isTruthy() { - return true; - } + @Override + public boolean isTruthy() { + return true; + } - @Override - public @NotNull - Tag serialize() { - var out = new CompoundTag(); - out.putUUID("uuid", this.getEntity().getUUID()); - out.putString("name", Component.Serializer.toJson(getEntityNameWithInline(true))); - return out; - } + @Override + public @NotNull Tag serialize() { + var out = new CompoundTag(); + out.putUUID("uuid", this.getEntity().getUUID()); + out.putString("name", Component.Serializer.toJson(getEntityNameWithInline(true))); + return out; + } - @Override - public Component display() { - return getEntityNameWithInline(false).copy().withStyle(ChatFormatting.AQUA); - } + @Override + public Component display() { + return getEntityNameWithInline(false).copy().withStyle(ChatFormatting.AQUA); + } - private Component getEntityNameWithInline(boolean fearSerializer){ - MutableComponent baseName = this.getEntity().getName().copy(); - Component inlineEnt = null; - if(this.getEntity() instanceof Player player){ - inlineEnt = new PlayerHeadData(player.getGameProfile()).asText(!fearSerializer); - inlineEnt = inlineEnt.plainCopy().withStyle(InlineAPI.INSTANCE.withSizeModifier(inlineEnt.getStyle(), 1.5)); - } else{ - if(fearSerializer){ // we don't want to have to serialize an entity just to display it - inlineEnt = EntityInlineData.fromType(this.getEntity().getType()).asText(!fearSerializer); - } else { - inlineEnt = EntityInlineData.fromEntity(this.getEntity()).asText(!fearSerializer); - } - } - return baseName.append(Component.literal(": ")).append(inlineEnt); - } + private Component getEntityNameWithInline(boolean fearSerializer) { + MutableComponent baseName = this.getEntity().getName().copy(); + Component inlineEnt = null; + if (this.getEntity() instanceof Player player) { + inlineEnt = new PlayerHeadData(player.getGameProfile()).asText(!fearSerializer); + inlineEnt = + inlineEnt + .plainCopy() + .withStyle(InlineAPI.INSTANCE.withSizeModifier(inlineEnt.getStyle(), 1.5)); + } else { + if (fearSerializer) { // we don't want to have to serialize an entity just to display it + inlineEnt = EntityInlineData.fromType(this.getEntity().getType()).asText(!fearSerializer); + } else { + inlineEnt = EntityInlineData.fromEntity(this.getEntity()).asText(!fearSerializer); + } + } + return baseName.append(Component.literal(": ")).append(inlineEnt); + } - public static IotaType<EntityIota> TYPE = new IotaType<>() { - @Nullable - @Override - public EntityIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - var ctag = HexUtils.downcast(tag, CompoundTag.TYPE); - Tag uuidTag = ctag.get("uuid"); - if (uuidTag == null) { - return null; - } - var uuid = NbtUtils.loadUUID(uuidTag); - var entity = world.getEntity(uuid); - if (entity == null) { - return null; - } - return new EntityIota(entity); - } + public static IotaType<EntityIota> TYPE = + new IotaType<>() { + @Nullable @Override + public EntityIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { + var ctag = HexUtils.downcast(tag, CompoundTag.TYPE); + Tag uuidTag = ctag.get("uuid"); + if (uuidTag == null) { + return null; + } + var uuid = NbtUtils.loadUUID(uuidTag); + var entity = world.getEntity(uuid); + if (entity == null) { + return null; + } + return new EntityIota(entity); + } - @Override - public Component display(Tag tag) { - if (!(tag instanceof CompoundTag ctag)) { - return Component.translatable("hexcasting.spelldata.entity.whoknows"); - } - if (!ctag.contains("name", Tag.TAG_STRING)) { - return Component.translatable("hexcasting.spelldata.entity.whoknows"); - } - var nameJson = ctag.getString("name"); -// return Component.literal(nameJson); - return Component.Serializer.fromJsonLenient(nameJson).withStyle(ChatFormatting.AQUA); - } + @Override + public Component display(Tag tag) { + if (!(tag instanceof CompoundTag ctag)) { + return Component.translatable("hexcasting.spelldata.entity.whoknows"); + } + if (!ctag.contains("name", Tag.TAG_STRING)) { + return Component.translatable("hexcasting.spelldata.entity.whoknows"); + } + var nameJson = ctag.getString("name"); + // return Component.literal(nameJson); + return Component.Serializer.fromJsonLenient(nameJson).withStyle(ChatFormatting.AQUA); + } - @Override - public int color() { - return 0xff_55ffff; - } - }; + @Override + public int color() { + return 0xff_55ffff; + } + }; } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/GarbageIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/GarbageIota.java index 0824985852..2cc9d2cb43 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/GarbageIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/GarbageIota.java @@ -1,6 +1,7 @@ package at.petrak.hexcasting.api.casting.iota; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import java.util.Random; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; @@ -9,55 +10,55 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Random; - /** - * this is LITERALLY a copy of NullIota but I can't see how to do it any better, i hate java generics + * this is LITERALLY a copy of NullIota but I can't see how to do it any better, i hate java + * generics */ public class GarbageIota extends Iota { - private static final Object NULL_SUBSTITUTE = new Object(); - - public static final Component DISPLAY = Component.literal("arimfexendrapuse") - .withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.OBFUSCATED); - - private static final Random RANDOM = new Random(); - - public GarbageIota() { - // We have to pass *something* here, but there's nothing that actually needs to go there, - // so we just do this i guess - super(HexIotaTypes.GARBAGE, NULL_SUBSTITUTE); - } - - @Override - public boolean isTruthy() { - return false; - } - - @Override - public boolean toleratesOther(Iota that) { - return typesMatch(this, that); - } - - @Override - public @NotNull Tag serialize() { - return new CompoundTag(); - } - - public static IotaType<GarbageIota> TYPE = new IotaType<>() { - @Nullable - @Override - public GarbageIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return new GarbageIota(); - } - - @Override - public Component display(Tag tag) { - return DISPLAY; - } - - @Override - public int color() { - return 0xff_505050; - } - }; + private static final Object NULL_SUBSTITUTE = new Object(); + + public static final Component DISPLAY = + Component.literal("arimfexendrapuse") + .withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.OBFUSCATED); + + private static final Random RANDOM = new Random(); + + public GarbageIota() { + // We have to pass *something* here, but there's nothing that actually needs to go there, + // so we just do this i guess + super(HexIotaTypes.GARBAGE, NULL_SUBSTITUTE); + } + + @Override + public boolean isTruthy() { + return false; + } + + @Override + public boolean toleratesOther(Iota that) { + return typesMatch(this, that); + } + + @Override + public @NotNull Tag serialize() { + return new CompoundTag(); + } + + public static IotaType<GarbageIota> TYPE = + new IotaType<>() { + @Nullable @Override + public GarbageIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { + return new GarbageIota(); + } + + @Override + public Component display(Tag tag) { + return DISPLAY; + } + + @Override + public int color() { + return 0xff_505050; + } + }; } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Iota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Iota.java index 7f024abc94..68732125ab 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Iota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Iota.java @@ -11,113 +11,105 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapUnescapedValue; import at.petrak.hexcasting.common.lib.hex.HexEvalSounds; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import java.util.List; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; - public abstract class Iota { - @NotNull - protected final Object payload; - @NotNull - protected final IotaType<?> type; - - protected Iota(@NotNull IotaType<?> type, @NotNull Object payload) { - this.type = type; - this.payload = payload; - } - - public @NotNull IotaType<?> getType() { - return this.type; - } - - abstract public boolean isTruthy(); - - /** - * Compare this to another object, within a tolerance. - */ - abstract protected boolean toleratesOther(Iota that); - - /** - * Serialize this under the {@code data} tag. - * <p> - * You probably don't want to call this directly; use {@link IotaType#serialize}. - */ - abstract public @NotNull Tag serialize(); - - /** - * This method is called when this iota is executed (i.e. Hermes is run on a list containing it, unescaped). - * By default it will return a {@link CastResult} indicating an error has occurred. - */ - public @NotNull CastResult execute(CastingVM vm, ServerLevel world, SpellContinuation continuation) { - return new CastResult( - this, - continuation, - null, // Should never matter - List.of( - new OperatorSideEffect.DoMishap( - new MishapUnescapedValue(this), - new Mishap.Context(new HexPattern(HexDir.WEST, List.of()), null) - ) - ), - ResolvedPatternType.INVALID, - HexEvalSounds.MISHAP); - } - - /** - * Returns whether this iota is possible to execute (i.e. whether {@link Iota#execute} has been overridden. - */ - public boolean executable() { - return false; - } - - /** - * This method is called to determine whether the iota is above the max serialisation depth/serialisation count - * limits. It should return every "iota" that is a subelement of this iota. - * For example, if you implemented a Map<Iota, Iota>, then it should be an iterable over the keys *and* - * values of the map. If you implemented a typed List<Double> iota for some reason, you should instead override - * {@link Iota#size}. - */ - public @Nullable Iterable<Iota> subIotas() { - return null; - } - - /** - * This method is called to determine whether the iota is above the max serialisation depth/serialisation count limits. - * This is an alternative to deriving subIotas for if your Iota is a datastructure of variable size over something that - * doesn't make sense to convert to an Iota iterable, such as {@link ContinuationIota}, or a typed List<Double>. - * It should return "1" per "iota sized" unit of memory that it would occupy. Easy option, return the element count of - * your data structure. - */ - public int size() { - return 1; - } - - public Component display() { - return this.type.display(this.serialize()); - } - - /** - * Helper method to see if two iotas have the same type. - */ - public static boolean typesMatch(Iota a, Iota b) { - var resA = HexIotaTypes.REGISTRY.getKey(a.getType()); - var resB = HexIotaTypes.REGISTRY.getKey(b.getType()); - return resA != null && resA.equals(resB); - } - - /** - * Helper method to see if either iota tolerates the other. - */ - public static boolean tolerates(Iota a, Iota b) { - return a.toleratesOther(b) || b.toleratesOther(a); - } - - @Override - public int hashCode() { - return payload.hashCode(); - } + @NotNull protected final Object payload; + @NotNull protected final IotaType<?> type; + + protected Iota(@NotNull IotaType<?> type, @NotNull Object payload) { + this.type = type; + this.payload = payload; + } + + public @NotNull IotaType<?> getType() { + return this.type; + } + + public abstract boolean isTruthy(); + + /** Compare this to another object, within a tolerance. */ + protected abstract boolean toleratesOther(Iota that); + + /** + * Serialize this under the {@code data} tag. + * + * <p>You probably don't want to call this directly; use {@link IotaType#serialize}. + */ + public abstract @NotNull Tag serialize(); + + /** + * This method is called when this iota is executed (i.e. Hermes is run on a list containing it, + * unescaped). By default it will return a {@link CastResult} indicating an error has occurred. + */ + public @NotNull CastResult execute( + CastingVM vm, ServerLevel world, SpellContinuation continuation) { + return new CastResult( + this, + continuation, + null, // Should never matter + List.of( + new OperatorSideEffect.DoMishap( + new MishapUnescapedValue(this), + new Mishap.Context(new HexPattern(HexDir.WEST, List.of()), null))), + ResolvedPatternType.INVALID, + HexEvalSounds.MISHAP); + } + + /** + * Returns whether this iota is possible to execute (i.e. whether {@link Iota#execute} has been + * overridden. + */ + public boolean executable() { + return false; + } + + /** + * This method is called to determine whether the iota is above the max serialisation + * depth/serialisation count limits. It should return every "iota" that is a subelement of this + * iota. For example, if you implemented a Map<Iota, Iota>, then it should be an iterable + * over the keys *and* values of the map. If you implemented a typed List<Double> iota for + * some reason, you should instead override {@link Iota#size}. + */ + public @Nullable Iterable<Iota> subIotas() { + return null; + } + + /** + * This method is called to determine whether the iota is above the max serialisation + * depth/serialisation count limits. This is an alternative to deriving subIotas for if your Iota + * is a datastructure of variable size over something that doesn't make sense to convert to an + * Iota iterable, such as {@link ContinuationIota}, or a typed List<Double>. It should + * return "1" per "iota sized" unit of memory that it would occupy. Easy option, return the + * element count of your data structure. + */ + public int size() { + return 1; + } + + public Component display() { + return this.type.display(this.serialize()); + } + + /** Helper method to see if two iotas have the same type. */ + public static boolean typesMatch(Iota a, Iota b) { + var resA = HexIotaTypes.REGISTRY.getKey(a.getType()); + var resB = HexIotaTypes.REGISTRY.getKey(b.getType()); + return resA != null && resA.equals(resB); + } + + /** Helper method to see if either iota tolerates the other. */ + public static boolean tolerates(Iota a, Iota b) { + return a.toleratesOther(b) || b.toleratesOther(a); + } + + @Override + public int hashCode() { + return payload.hashCode(); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/IotaType.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/IotaType.java index 4bcf9b4b1f..c8b3b165de 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/IotaType.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/IotaType.java @@ -4,6 +4,11 @@ import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import com.mojang.datafixers.util.Pair; +import java.util.ArrayDeque; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import javax.annotation.Nullable; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.Font; import net.minecraft.nbt.CompoundTag; @@ -14,195 +19,182 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.util.FormattedCharSequence; -import javax.annotation.Nullable; -import java.util.ArrayDeque; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - // Take notes from ForgeRegistryEntry public abstract class IotaType<T extends Iota> { - /** - * Spell datums are stored as such: {@code { "type": "modid:type", "datum": a_tag }}. - * <p> - * The {@code type} key is given when registering the spell datum type; this method - * deserializes the tag associated with {@code "datum"}. - * <p> - * Returning {@code null} makes the resulting datum be {@link NullIota}. - * Throwing an exception raises a mishap. - */ - @Nullable - public abstract T deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException; - - /** - * Get a display of this datum from the {@code data} tag, <i>without</i> the world. - * This is for use on the client. - */ - public abstract Component display(Tag tag); - - /** - * Get the color associated with this datum type. - */ - public abstract int color(); - - /** - * Get a display component that's the name of this iota type. - */ - public Component typeName() { - var key = HexIotaTypes.REGISTRY.getKey(this); - return Component.translatable("hexcasting.iota." + key) - .withStyle(style -> style.withColor(TextColor.fromRgb(color()))); - } - - public static CompoundTag serialize(Iota iota) { - var type = iota.getType(); - var typeId = HexIotaTypes.REGISTRY.getKey(type); - if (typeId == null) { - throw new IllegalStateException( - "Tried to serialize an unregistered iota type. Iota: " + iota - + " ; Type" + type.getClass().getTypeName()); - } - - // We check if it's too big on serialization; if it is we just return a garbage. - if (isTooLargeToSerialize(List.of(iota), 0)) { - // Garbage will never be too large so we just recurse - return serialize(new GarbageIota()); - } - var dataTag = iota.serialize(); - var out = new CompoundTag(); - out.putString(HexIotaTypes.KEY_TYPE, typeId.toString()); - out.put(HexIotaTypes.KEY_DATA, dataTag); - return out; - } - - public static boolean isTooLargeToSerialize(Iterable<Iota> examinee) { - return isTooLargeToSerialize(examinee, 1); - } - - private static boolean isTooLargeToSerialize(Iterable<Iota> examinee, int startingCount) { - // We don't recurse here, just a work queue (or work stack, if we liked.) - // Each element is a found sub-iota, and how deep it is. - // - // TODO: is it worth trying to cache the depth and size statically on a SpellList. - var listsToExamine = new ArrayDeque<>(Collections.singleton(new Pair<>(examinee, 0))); - int totalEltsFound = startingCount; // count the first list - while (!listsToExamine.isEmpty()) { - var iotaPair = listsToExamine.removeFirst(); - var sublist = iotaPair.getFirst(); - int depth = iotaPair.getSecond(); - for (var iota : sublist) { - totalEltsFound += iota.size(); - if (totalEltsFound >= HexIotaTypes.MAX_SERIALIZATION_TOTAL) { - return true; // too bad - } - var subIotas = iota.subIotas(); - if (subIotas != null) { - if (depth + 1 >= HexIotaTypes.MAX_SERIALIZATION_DEPTH) { - return true; - } - - listsToExamine.addLast(new Pair<>(subIotas, depth + 1)); - } - } - } - // we made it! - return false; - } - - /** - * This method attempts to find the type from the {@code type} key. - * See {@link IotaType#serialize(Iota)} for the storage format. - * - * @return {@code null} if it cannot get the type. - */ - @org.jetbrains.annotations.Nullable - public static IotaType<?> getTypeFromTag(CompoundTag tag) { - if (!tag.contains(HexIotaTypes.KEY_TYPE, Tag.TAG_STRING)) { - return null; - } - var typeKey = tag.getString(HexIotaTypes.KEY_TYPE); - if (!ResourceLocation.isValidResourceLocation(typeKey)) { - return null; - } - var typeLoc = new ResourceLocation(typeKey); - return HexIotaTypes.REGISTRY.get(typeLoc); - } - - /** - * Attempt to deserialize an iota from a tag. - * <br> - * Iotas are saved as such: - * <code> - * { - * "type": "hexcasting:atype", - * "data": {...} - * } - * </code> - */ - public static Iota deserialize(CompoundTag tag, ServerLevel world) { - var type = getTypeFromTag(tag); - if (type == null) { - return new GarbageIota(); - } - var data = tag.get(HexIotaTypes.KEY_DATA); - if (data == null) { - return new GarbageIota(); - } - Iota deserialized; - try { - deserialized = Objects.requireNonNullElse(type.deserialize(data, world), new NullIota()); - } catch (IllegalArgumentException exn) { - HexAPI.LOGGER.warn("Caught an exception deserializing an iota", exn); - deserialized = new GarbageIota(); - } - return deserialized; - } - - private static Component brokenIota() { - return Component.translatable("hexcasting.spelldata.unknown") - .withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC); - } - - public static Component getDisplay(CompoundTag tag) { - var type = getTypeFromTag(tag); - if (type == null) { - return brokenIota(); - } - var data = tag.get(HexIotaTypes.KEY_DATA); - if (data == null) { - return brokenIota(); - } - return type.display(data); - } - - public static FormattedCharSequence getDisplayWithMaxWidth(CompoundTag tag, int maxWidth, Font font) { - var type = getTypeFromTag(tag); - if (type == null) { - return brokenIota().getVisualOrderText(); - } - var data = tag.get(HexIotaTypes.KEY_DATA); - if (data == null) { - return brokenIota().getVisualOrderText(); - } - var display = type.display(data); - var splitted = font.split(display, maxWidth - font.width("...")); - if (splitted.isEmpty()) - return FormattedCharSequence.EMPTY; - else if (splitted.size() == 1) - return splitted.get(0); - else { - var first = splitted.get(0); - return FormattedCharSequence.fromPair(first, - Component.literal("...").withStyle(ChatFormatting.GRAY).getVisualOrderText()); - } - } - - public static int getColor(CompoundTag tag) { - var type = getTypeFromTag(tag); - if (type == null) { - return HexUtils.ERROR_COLOR; - } - return type.color(); - } + /** + * Spell datums are stored as such: {@code { "type": "modid:type", "datum": a_tag }}. + * + * <p>The {@code type} key is given when registering the spell datum type; this method + * deserializes the tag associated with {@code "datum"}. + * + * <p>Returning {@code null} makes the resulting datum be {@link NullIota}. Throwing an exception + * raises a mishap. + */ + @Nullable public abstract T deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException; + + /** + * Get a display of this datum from the {@code data} tag, <i>without</i> the world. This is for + * use on the client. + */ + public abstract Component display(Tag tag); + + /** Get the color associated with this datum type. */ + public abstract int color(); + + /** Get a display component that's the name of this iota type. */ + public Component typeName() { + var key = HexIotaTypes.REGISTRY.getKey(this); + return Component.translatable("hexcasting.iota." + key) + .withStyle(style -> style.withColor(TextColor.fromRgb(color()))); + } + + public static CompoundTag serialize(Iota iota) { + var type = iota.getType(); + var typeId = HexIotaTypes.REGISTRY.getKey(type); + if (typeId == null) { + throw new IllegalStateException( + "Tried to serialize an unregistered iota type. Iota: " + + iota + + " ; Type" + + type.getClass().getTypeName()); + } + + // We check if it's too big on serialization; if it is we just return a garbage. + if (isTooLargeToSerialize(List.of(iota), 0)) { + // Garbage will never be too large so we just recurse + return serialize(new GarbageIota()); + } + var dataTag = iota.serialize(); + var out = new CompoundTag(); + out.putString(HexIotaTypes.KEY_TYPE, typeId.toString()); + out.put(HexIotaTypes.KEY_DATA, dataTag); + return out; + } + + public static boolean isTooLargeToSerialize(Iterable<Iota> examinee) { + return isTooLargeToSerialize(examinee, 1); + } + + private static boolean isTooLargeToSerialize(Iterable<Iota> examinee, int startingCount) { + // We don't recurse here, just a work queue (or work stack, if we liked.) + // Each element is a found sub-iota, and how deep it is. + // + // TODO: is it worth trying to cache the depth and size statically on a SpellList. + var listsToExamine = new ArrayDeque<>(Collections.singleton(new Pair<>(examinee, 0))); + int totalEltsFound = startingCount; // count the first list + while (!listsToExamine.isEmpty()) { + var iotaPair = listsToExamine.removeFirst(); + var sublist = iotaPair.getFirst(); + int depth = iotaPair.getSecond(); + for (var iota : sublist) { + totalEltsFound += iota.size(); + if (totalEltsFound >= HexIotaTypes.MAX_SERIALIZATION_TOTAL) { + return true; // too bad + } + var subIotas = iota.subIotas(); + if (subIotas != null) { + if (depth + 1 >= HexIotaTypes.MAX_SERIALIZATION_DEPTH) { + return true; + } + + listsToExamine.addLast(new Pair<>(subIotas, depth + 1)); + } + } + } + // we made it! + return false; + } + + /** + * This method attempts to find the type from the {@code type} key. See {@link + * IotaType#serialize(Iota)} for the storage format. + * + * @return {@code null} if it cannot get the type. + */ + @org.jetbrains.annotations.Nullable public static IotaType<?> getTypeFromTag(CompoundTag tag) { + if (!tag.contains(HexIotaTypes.KEY_TYPE, Tag.TAG_STRING)) { + return null; + } + var typeKey = tag.getString(HexIotaTypes.KEY_TYPE); + if (!ResourceLocation.isValidResourceLocation(typeKey)) { + return null; + } + var typeLoc = new ResourceLocation(typeKey); + return HexIotaTypes.REGISTRY.get(typeLoc); + } + + /** + * Attempt to deserialize an iota from a tag. <br> + * Iotas are saved as such: <code> + * { + * "type": "hexcasting:atype", + * "data": {...} + * } + * </code> + */ + public static Iota deserialize(CompoundTag tag, ServerLevel world) { + var type = getTypeFromTag(tag); + if (type == null) { + return new GarbageIota(); + } + var data = tag.get(HexIotaTypes.KEY_DATA); + if (data == null) { + return new GarbageIota(); + } + Iota deserialized; + try { + deserialized = Objects.requireNonNullElse(type.deserialize(data, world), new NullIota()); + } catch (IllegalArgumentException exn) { + HexAPI.LOGGER.warn("Caught an exception deserializing an iota", exn); + deserialized = new GarbageIota(); + } + return deserialized; + } + + private static Component brokenIota() { + return Component.translatable("hexcasting.spelldata.unknown") + .withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC); + } + + public static Component getDisplay(CompoundTag tag) { + var type = getTypeFromTag(tag); + if (type == null) { + return brokenIota(); + } + var data = tag.get(HexIotaTypes.KEY_DATA); + if (data == null) { + return brokenIota(); + } + return type.display(data); + } + + public static FormattedCharSequence getDisplayWithMaxWidth( + CompoundTag tag, int maxWidth, Font font) { + var type = getTypeFromTag(tag); + if (type == null) { + return brokenIota().getVisualOrderText(); + } + var data = tag.get(HexIotaTypes.KEY_DATA); + if (data == null) { + return brokenIota().getVisualOrderText(); + } + var display = type.display(data); + var splitted = font.split(display, maxWidth - font.width("...")); + if (splitted.isEmpty()) return FormattedCharSequence.EMPTY; + else if (splitted.size() == 1) return splitted.get(0); + else { + var first = splitted.get(0); + return FormattedCharSequence.fromPair( + first, Component.literal("...").withStyle(ChatFormatting.GRAY).getVisualOrderText()); + } + } + + public static int getColor(CompoundTag tag) { + var type = getTypeFromTag(tag); + if (type == null) { + return HexUtils.ERROR_COLOR; + } + return type.color(); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ListIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ListIota.java index 251c4e161d..9b24e45beb 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ListIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ListIota.java @@ -3,6 +3,8 @@ import at.petrak.hexcasting.api.casting.SpellList; import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import java.util.ArrayList; +import java.util.List; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; @@ -12,114 +14,113 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; - -/** - * This is a <i>wrapper</i> for {@link SpellList}. - */ +/** This is a <i>wrapper</i> for {@link SpellList}. */ public class ListIota extends Iota { - public ListIota(@NotNull SpellList list) { - super(HexIotaTypes.LIST, list); - } - - public ListIota(@NotNull List<Iota> list) { - this(new SpellList.LList(list)); - } - - public SpellList getList() { - return (SpellList) this.payload; - } - - @Override - public boolean isTruthy() { - return this.getList().getNonEmpty(); - } - - @Override - public boolean toleratesOther(Iota that) { - if (!typesMatch(this, that)) { - return false; - } - var a = this.getList(); - if (!(that instanceof ListIota list)) { - return false; - } - var b = list.getList(); - - SpellList.SpellListIterator aIter = a.iterator(), bIter = b.iterator(); - for (; ; ) { - if (!aIter.hasNext() && !bIter.hasNext()) { - // we ran out together! - return true; - } - if (aIter.hasNext() != bIter.hasNext()) { - // one remains full before the other - return false; - } - Iota x = aIter.next(), y = bIter.next(); - if (!Iota.tolerates(x, y)) { - return false; - } - } - } - - @Override - public @NotNull Tag serialize() { - var out = new ListTag(); - for (var subdatum : this.getList()) { - out.add(IotaType.serialize(subdatum)); - } - return out; - } - - @Override - public @Nullable Iterable<Iota> subIotas() { - return this.getList(); - } - - public static IotaType<ListIota> TYPE = new IotaType<>() { - @Nullable - @Override - public ListIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - var listTag = HexUtils.downcast(tag, ListTag.TYPE); - var out = new ArrayList<Iota>(listTag.size()); - - for (var sub : listTag) { - var csub = HexUtils.downcast(sub, CompoundTag.TYPE); - var subiota = IotaType.deserialize(csub, world); - if (subiota == null) { - return null; - } - out.add(subiota); - } - - return new ListIota(out); - } - - @Override - public Component display(Tag tag) { - var out = Component.empty(); - var list = HexUtils.downcast(tag, ListTag.TYPE); - for (int i = 0; i < list.size(); i++) { - Tag sub = list.get(i); - var csub = HexUtils.downcast(sub, CompoundTag.TYPE); - - out.append(IotaType.getDisplay(csub)); - - // only add a comma between 2 non-patterns (commas don't look good with Inline patterns) - // TODO: maybe add a config? maybe add a method on IotaType to allow it to opt out of commas - if (i < list.size() - 1 && (IotaType.getTypeFromTag(csub) != PatternIota.TYPE - || IotaType.getTypeFromTag(HexUtils.downcast(list.get(i+1), CompoundTag.TYPE)) != PatternIota.TYPE)) { - out.append(", "); - } - } - return Component.translatable("hexcasting.tooltip.list_contents", out).withStyle(ChatFormatting.DARK_PURPLE); - } - - @Override - public int color() { - return 0xff_aa00aa; - } - }; + public ListIota(@NotNull SpellList list) { + super(HexIotaTypes.LIST, list); + } + + public ListIota(@NotNull List<Iota> list) { + this(new SpellList.LList(list)); + } + + public SpellList getList() { + return (SpellList) this.payload; + } + + @Override + public boolean isTruthy() { + return this.getList().getNonEmpty(); + } + + @Override + public boolean toleratesOther(Iota that) { + if (!typesMatch(this, that)) { + return false; + } + var a = this.getList(); + if (!(that instanceof ListIota list)) { + return false; + } + var b = list.getList(); + + SpellList.SpellListIterator aIter = a.iterator(), bIter = b.iterator(); + for (; ; ) { + if (!aIter.hasNext() && !bIter.hasNext()) { + // we ran out together! + return true; + } + if (aIter.hasNext() != bIter.hasNext()) { + // one remains full before the other + return false; + } + Iota x = aIter.next(), y = bIter.next(); + if (!Iota.tolerates(x, y)) { + return false; + } + } + } + + @Override + public @NotNull Tag serialize() { + var out = new ListTag(); + for (var subdatum : this.getList()) { + out.add(IotaType.serialize(subdatum)); + } + return out; + } + + @Override + public @Nullable Iterable<Iota> subIotas() { + return this.getList(); + } + + public static IotaType<ListIota> TYPE = + new IotaType<>() { + @Nullable @Override + public ListIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { + var listTag = HexUtils.downcast(tag, ListTag.TYPE); + var out = new ArrayList<Iota>(listTag.size()); + + for (var sub : listTag) { + var csub = HexUtils.downcast(sub, CompoundTag.TYPE); + var subiota = IotaType.deserialize(csub, world); + if (subiota == null) { + return null; + } + out.add(subiota); + } + + return new ListIota(out); + } + + @Override + public Component display(Tag tag) { + var out = Component.empty(); + var list = HexUtils.downcast(tag, ListTag.TYPE); + for (int i = 0; i < list.size(); i++) { + Tag sub = list.get(i); + var csub = HexUtils.downcast(sub, CompoundTag.TYPE); + + out.append(IotaType.getDisplay(csub)); + + // only add a comma between 2 non-patterns (commas don't look good with Inline patterns) + // TODO: maybe add a config? maybe add a method on IotaType to allow it to opt out of + // commas + if (i < list.size() - 1 + && (IotaType.getTypeFromTag(csub) != PatternIota.TYPE + || IotaType.getTypeFromTag(HexUtils.downcast(list.get(i + 1), CompoundTag.TYPE)) + != PatternIota.TYPE)) { + out.append(", "); + } + } + return Component.translatable("hexcasting.tooltip.list_contents", out) + .withStyle(ChatFormatting.DARK_PURPLE); + } + + @Override + public int color() { + return 0xff_aa00aa; + } + }; } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/NullIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/NullIota.java index 525e6b22a9..581b248521 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/NullIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/NullIota.java @@ -9,51 +9,49 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -/** - * An iota with no data associated with it. - */ +/** An iota with no data associated with it. */ public class NullIota extends Iota { - private static final Object NULL_SUBSTITUTE = new Object(); - - public static final Component DISPLAY = - Component.translatable("hexcasting.tooltip.null_iota").withStyle(ChatFormatting.GRAY); - - public NullIota() { - // We have to pass *something* here, but there's nothing that actually needs to go there, - // so we just do this i guess - super(HexIotaTypes.NULL, NULL_SUBSTITUTE); - } - - @Override - public boolean isTruthy() { - return false; - } - - @Override - public boolean toleratesOther(Iota that) { - return typesMatch(this, that); - } - - @Override - public @NotNull Tag serialize() { - return new CompoundTag(); - } - - public static IotaType<NullIota> TYPE = new IotaType<>() { - @Nullable - @Override - public NullIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return new NullIota(); - } - - @Override - public Component display(Tag tag) { - return DISPLAY; - } - - @Override - public int color() { - return 0xff_aaaaaa; - } - }; + private static final Object NULL_SUBSTITUTE = new Object(); + + public static final Component DISPLAY = + Component.translatable("hexcasting.tooltip.null_iota").withStyle(ChatFormatting.GRAY); + + public NullIota() { + // We have to pass *something* here, but there's nothing that actually needs to go there, + // so we just do this i guess + super(HexIotaTypes.NULL, NULL_SUBSTITUTE); + } + + @Override + public boolean isTruthy() { + return false; + } + + @Override + public boolean toleratesOther(Iota that) { + return typesMatch(this, that); + } + + @Override + public @NotNull Tag serialize() { + return new CompoundTag(); + } + + public static IotaType<NullIota> TYPE = + new IotaType<>() { + @Nullable @Override + public NullIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { + return new NullIota(); + } + + @Override + public Component display(Tag tag) { + return DISPLAY; + } + + @Override + public int color() { + return 0xff_aaaaaa; + } + }; } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java index b86e8541ce..47cf64f1fa 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.api.casting.iota; +import static at.petrak.hexcasting.api.utils.HexUtils.isOfTag; + import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.casting.ActionRegistryEntry; import at.petrak.hexcasting.api.casting.PatternShapeMatch; @@ -21,6 +23,9 @@ import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import at.petrak.hexcasting.interop.inline.InlinePatternData; import at.petrak.hexcasting.xplat.IXplatAbstractions; +import java.util.List; +import java.util.Objects; +import java.util.function.Supplier; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; @@ -31,155 +36,157 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; -import java.util.Objects; -import java.util.function.Supplier; - -import static at.petrak.hexcasting.api.utils.HexUtils.isOfTag; - public class PatternIota extends Iota { - public PatternIota(@NotNull HexPattern pattern) { - super(HexIotaTypes.PATTERN, pattern); - } - - public HexPattern getPattern() { - return (HexPattern) this.payload; - } - - protected PatternIota(@NotNull IotaType<?> type, @NotNull Object payload) { - super(type, payload); - } - - @Override - public boolean isTruthy() { - return true; - } - - @Override - public boolean toleratesOther(Iota that) { - return typesMatch(this, that) - && that instanceof PatternIota piota - && this.getPattern().getAngles().equals(piota.getPattern().getAngles()); - } - - @Override - public @NotNull Tag serialize() { - return this.getPattern().serializeToNBT(); - } - - @Override - public @NotNull CastResult execute(CastingVM vm, ServerLevel world, SpellContinuation continuation) { - Supplier<@Nullable Component> castedName = () -> null; - try { - var lookup = PatternRegistryManifest.matchPattern(this.getPattern(), vm.getEnv(), false); - vm.getEnv().precheckAction(lookup); - - Action action; - if (lookup instanceof PatternShapeMatch.Normal || lookup instanceof PatternShapeMatch.PerWorld) { - ResourceKey<ActionRegistryEntry> key; - if (lookup instanceof PatternShapeMatch.Normal normal) { - key = normal.key; - } else { - PatternShapeMatch.PerWorld perWorld = (PatternShapeMatch.PerWorld) lookup; - key = perWorld.key; - } - - var reqsEnlightenment = isOfTag(IXplatAbstractions.INSTANCE.getActionRegistry(), key, - HexTags.Actions.REQUIRES_ENLIGHTENMENT); - - castedName = () -> HexAPI.instance().getActionI18n(key, reqsEnlightenment); - action = Objects.requireNonNull(IXplatAbstractions.INSTANCE.getActionRegistry().get(key)).action(); - - if (reqsEnlightenment && !vm.getEnv().isEnlightened()) { - // this gets caught down below - throw new MishapUnenlightened(); - } - } else if (lookup instanceof PatternShapeMatch.Special special) { - castedName = special.handler::getName; - action = special.handler.act(); - } else if (lookup instanceof PatternShapeMatch.Nothing) { - throw new MishapInvalidPattern(); - } else throw new IllegalStateException(); - - // do the actual calculation!! - var result = action.operate( - vm.getEnv(), - vm.getImage(), - continuation - ); - - if (result.getNewImage().getOpsConsumed() > vm.getEnv().maxOpCount()) { - throw new MishapEvalTooMuch(); - } - - var cont2 = result.getNewContinuation(); - // TODO parens also break prescience - var sideEffects = result.getSideEffects(); - - return new CastResult( - this, - cont2, - result.getNewImage(), - sideEffects, - ResolvedPatternType.EVALUATED, - result.getSound()); - - } catch (Mishap mishap) { - return new CastResult( - this, - continuation, - null, - List.of(new OperatorSideEffect.DoMishap(mishap, new Mishap.Context(this.getPattern(), castedName.get()))), - mishap.resolutionType(vm.getEnv()), - HexEvalSounds.MISHAP); - } - } - - @Override - public boolean executable() { - return true; - } - - public static IotaType<PatternIota> TYPE = new IotaType<>() { - @Override - public PatternIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return PatternIota.deserialize(tag); - } - - @Override - public Component display(Tag tag) { - return PatternIota.display(PatternIota.deserialize(tag).getPattern()); - } - - @Override - public int color() { - return 0xff_ffaa00; - } - }; - - public static PatternIota deserialize(Tag tag) throws IllegalArgumentException { - var patTag = HexUtils.downcast(tag, CompoundTag.TYPE); - HexPattern pat = HexPattern.fromNBT(patTag); - return new PatternIota(pat); - } - - public static Component display(HexPattern pat) { - Component text = (new InlinePatternData(pat)).asText(true); - return text.copy().withStyle(text.getStyle().applyTo(Style.EMPTY.withColor(ChatFormatting.WHITE))); - } - - // keep around just in case it's needed. - public static Component displayNonInline(HexPattern pat){ - var bob = new StringBuilder(); - bob.append(pat.getStartDir()); - - var sig = pat.anglesSignature(); - if (!sig.isEmpty()) { - bob.append(" "); - bob.append(sig); - } - return Component.translatable("hexcasting.tooltip.pattern_iota", - Component.literal(bob.toString()).withStyle(ChatFormatting.WHITE)) - .withStyle(ChatFormatting.GOLD); - } + public PatternIota(@NotNull HexPattern pattern) { + super(HexIotaTypes.PATTERN, pattern); + } + + public HexPattern getPattern() { + return (HexPattern) this.payload; + } + + protected PatternIota(@NotNull IotaType<?> type, @NotNull Object payload) { + super(type, payload); + } + + @Override + public boolean isTruthy() { + return true; + } + + @Override + public boolean toleratesOther(Iota that) { + return typesMatch(this, that) + && that instanceof PatternIota piota + && this.getPattern().getAngles().equals(piota.getPattern().getAngles()); + } + + @Override + public @NotNull Tag serialize() { + return this.getPattern().serializeToNBT(); + } + + @Override + public @NotNull CastResult execute( + CastingVM vm, ServerLevel world, SpellContinuation continuation) { + Supplier<@Nullable Component> castedName = () -> null; + try { + var lookup = PatternRegistryManifest.matchPattern(this.getPattern(), vm.getEnv(), false); + vm.getEnv().precheckAction(lookup); + + Action action; + if (lookup instanceof PatternShapeMatch.Normal + || lookup instanceof PatternShapeMatch.PerWorld) { + ResourceKey<ActionRegistryEntry> key; + if (lookup instanceof PatternShapeMatch.Normal normal) { + key = normal.key; + } else { + PatternShapeMatch.PerWorld perWorld = (PatternShapeMatch.PerWorld) lookup; + key = perWorld.key; + } + + var reqsEnlightenment = + isOfTag( + IXplatAbstractions.INSTANCE.getActionRegistry(), + key, + HexTags.Actions.REQUIRES_ENLIGHTENMENT); + + castedName = () -> HexAPI.instance().getActionI18n(key, reqsEnlightenment); + action = + Objects.requireNonNull(IXplatAbstractions.INSTANCE.getActionRegistry().get(key)) + .action(); + + if (reqsEnlightenment && !vm.getEnv().isEnlightened()) { + // this gets caught down below + throw new MishapUnenlightened(); + } + } else if (lookup instanceof PatternShapeMatch.Special special) { + castedName = special.handler::getName; + action = special.handler.act(); + } else if (lookup instanceof PatternShapeMatch.Nothing) { + throw new MishapInvalidPattern(); + } else throw new IllegalStateException(); + + // do the actual calculation!! + var result = action.operate(vm.getEnv(), vm.getImage(), continuation); + + if (result.getNewImage().getOpsConsumed() > vm.getEnv().maxOpCount()) { + throw new MishapEvalTooMuch(); + } + + var cont2 = result.getNewContinuation(); + // TODO parens also break prescience + var sideEffects = result.getSideEffects(); + + return new CastResult( + this, + cont2, + result.getNewImage(), + sideEffects, + ResolvedPatternType.EVALUATED, + result.getSound()); + + } catch (Mishap mishap) { + return new CastResult( + this, + continuation, + null, + List.of( + new OperatorSideEffect.DoMishap( + mishap, new Mishap.Context(this.getPattern(), castedName.get()))), + mishap.resolutionType(vm.getEnv()), + HexEvalSounds.MISHAP); + } + } + + @Override + public boolean executable() { + return true; + } + + public static IotaType<PatternIota> TYPE = + new IotaType<>() { + @Override + public PatternIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { + return PatternIota.deserialize(tag); + } + + @Override + public Component display(Tag tag) { + return PatternIota.display(PatternIota.deserialize(tag).getPattern()); + } + + @Override + public int color() { + return 0xff_ffaa00; + } + }; + + public static PatternIota deserialize(Tag tag) throws IllegalArgumentException { + var patTag = HexUtils.downcast(tag, CompoundTag.TYPE); + HexPattern pat = HexPattern.fromNBT(patTag); + return new PatternIota(pat); + } + + public static Component display(HexPattern pat) { + Component text = (new InlinePatternData(pat)).asText(true); + return text.copy() + .withStyle(text.getStyle().applyTo(Style.EMPTY.withColor(ChatFormatting.WHITE))); + } + + // keep around just in case it's needed. + public static Component displayNonInline(HexPattern pat) { + var bob = new StringBuilder(); + bob.append(pat.getStartDir()); + + var sig = pat.anglesSignature(); + if (!sig.isEmpty()) { + bob.append(" "); + bob.append(sig); + } + return Component.translatable( + "hexcasting.tooltip.pattern_iota", + Component.literal(bob.toString()).withStyle(ChatFormatting.WHITE)) + .withStyle(ChatFormatting.GOLD); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Vec3Iota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Vec3Iota.java index 9d9d7fbf67..b9cb2756e1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Vec3Iota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Vec3Iota.java @@ -13,71 +13,67 @@ import org.jetbrains.annotations.Nullable; public class Vec3Iota extends Iota { - public Vec3Iota(@NotNull Vec3 datum) { - super(HexIotaTypes.VEC3, datum); - } + public Vec3Iota(@NotNull Vec3 datum) { + super(HexIotaTypes.VEC3, datum); + } - public Vec3 getVec3() { - var v = (Vec3) this.payload; - return new Vec3( - HexUtils.fixNAN(v.x), - HexUtils.fixNAN(v.y), - HexUtils.fixNAN(v.z) - ); - } + public Vec3 getVec3() { + var v = (Vec3) this.payload; + return new Vec3(HexUtils.fixNAN(v.x), HexUtils.fixNAN(v.y), HexUtils.fixNAN(v.z)); + } - @Override - public boolean isTruthy() { - var v = this.getVec3(); - return !(v.x == 0.0 && v.y == 0.0 && v.z == 0.0); - } + @Override + public boolean isTruthy() { + var v = this.getVec3(); + return !(v.x == 0.0 && v.y == 0.0 && v.z == 0.0); + } - @Override - public boolean toleratesOther(Iota that) { - return typesMatch(this, that) - && that instanceof Vec3Iota viota - && this.getVec3().distanceToSqr(viota.getVec3()) < DoubleIota.TOLERANCE * DoubleIota.TOLERANCE; - } + @Override + public boolean toleratesOther(Iota that) { + return typesMatch(this, that) + && that instanceof Vec3Iota viota + && this.getVec3().distanceToSqr(viota.getVec3()) + < DoubleIota.TOLERANCE * DoubleIota.TOLERANCE; + } - @Override - public @NotNull Tag serialize() { - return HexUtils.serializeToNBT(this.getVec3()); - } + @Override + public @NotNull Tag serialize() { + return HexUtils.serializeToNBT(this.getVec3()); + } - public static IotaType<Vec3Iota> TYPE = new IotaType<>() { - @Nullable - @Override - public Vec3Iota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return Vec3Iota.deserialize(tag); - } + public static IotaType<Vec3Iota> TYPE = + new IotaType<>() { + @Nullable @Override + public Vec3Iota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { + return Vec3Iota.deserialize(tag); + } - @Override - public Component display(Tag tag) { - return Vec3Iota.display(Vec3Iota.deserialize(tag).getVec3()); - } + @Override + public Component display(Tag tag) { + return Vec3Iota.display(Vec3Iota.deserialize(tag).getVec3()); + } - @Override - public int color() { - return 0xff_ff3030; - } - }; + @Override + public int color() { + return 0xff_ff3030; + } + }; - public static Vec3Iota deserialize(Tag tag) throws IllegalArgumentException { - Vec3 vec; - if (tag.getType() == LongArrayTag.TYPE) { - var lat = HexUtils.downcast(tag, LongArrayTag.TYPE); - vec = HexUtils.vecFromNBT(lat.getAsLongArray()); - } else - vec = HexUtils.vecFromNBT(HexUtils.downcast(tag, CompoundTag.TYPE)); - return new Vec3Iota(vec); - } + public static Vec3Iota deserialize(Tag tag) throws IllegalArgumentException { + Vec3 vec; + if (tag.getType() == LongArrayTag.TYPE) { + var lat = HexUtils.downcast(tag, LongArrayTag.TYPE); + vec = HexUtils.vecFromNBT(lat.getAsLongArray()); + } else vec = HexUtils.vecFromNBT(HexUtils.downcast(tag, CompoundTag.TYPE)); + return new Vec3Iota(vec); + } - public static Component display(double x, double y, double z) { - return Component.literal(String.format("(%.2f, %.2f, %.2f)", x, y, z)) - .withStyle(ChatFormatting.RED); - } + public static Component display(double x, double y, double z) { + return Component.literal(String.format("(%.2f, %.2f, %.2f)", x, y, z)) + .withStyle(ChatFormatting.RED); + } - public static Component display(Vec3 v) { - return display(v.x, v.y, v.z); - } + public static Component display(Vec3 v) { + return display(v.x, v.y, v.z); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/EulerPathFinder.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/EulerPathFinder.kt index d79ff002b8..cd74c0e493 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/EulerPathFinder.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/EulerPathFinder.kt @@ -5,84 +5,91 @@ import java.util.* import kotlin.random.Random object EulerPathFinder { - /** - * Find an alternative way to draw the given pattern, based on a random seed. - */ - @JvmStatic - @JvmOverloads - fun findAltDrawing(original: HexPattern, seed: Long, rule: (HexPattern) -> Boolean = { true }): HexPattern { - // http://www.graph-magics.com/articles/euler.php + /** Find an alternative way to draw the given pattern, based on a random seed. */ + @JvmStatic + @JvmOverloads + fun findAltDrawing( + original: HexPattern, + seed: Long, + rule: (HexPattern) -> Boolean = { true } + ): HexPattern { + // http://www.graph-magics.com/articles/euler.php - val rand = Random(seed) + val rand = Random(seed) - // Don't try for too long, in case all paths are exhausted. - // Unlikely to ever actually reach this limit, and can only happen if the same pattern - // is registered both as a Great Pattern and as a special handler or regular pattern, - // or if the random seed has some sort of strange repeating property to it. - var iterationsLeft = 100 - var path: HexPattern - while (iterationsLeft > 0) { - iterationsLeft-- - path = walkPath(original, rand) - if (rule(path)) { - return path - } - } + // Don't try for too long, in case all paths are exhausted. + // Unlikely to ever actually reach this limit, and can only happen if the same pattern + // is registered both as a Great Pattern and as a special handler or regular pattern, + // or if the random seed has some sort of strange repeating property to it. + var iterationsLeft = 100 + var path: HexPattern + while (iterationsLeft > 0) { + iterationsLeft-- + path = walkPath(original, rand) + if (rule(path)) { + return path + } + } - HexAPI.LOGGER.warn("Didn't find alternate path for {} in time", original) - return original - } + HexAPI.LOGGER.warn("Didn't find alternate path for {} in time", original) + return original + } - private fun walkPath(original: HexPattern, rand: Random): HexPattern { - val graph = toGraph(original) - val oddNodes = graph.filter { (_, dirs) -> dirs.size % 2 == 1 } - var current: HexCoord = when (oddNodes.size) { - // An euler-walkable graph must have 0 odd nodes and start anywhere... - 0 -> graph.keys.random(rand) - // or two, and start at one of them - 2 -> oddNodes.keys.random(rand) - else -> throw IllegalStateException() - } + private fun walkPath(original: HexPattern, rand: Random): HexPattern { + val graph = toGraph(original) + val oddNodes = graph.filter { (_, dirs) -> dirs.size % 2 == 1 } + var current: HexCoord = + when (oddNodes.size) { + // An euler-walkable graph must have 0 odd nodes and start anywhere... + 0 -> graph.keys.random(rand) + // or two, and start at one of them + 2 -> oddNodes.keys.random(rand) + else -> throw IllegalStateException() + } - val stack = Stack<HexCoord>() - val out = mutableListOf<HexCoord>() - do { - val exits = graph[current]!! - if (exits.isEmpty()) { - out.add(current) - current = stack.pop() - } else { - stack.push(current) - // This is where the random part happens, mostly - val burnDir = exits.random(rand) - exits.remove(burnDir) - graph[current + burnDir]?.remove(burnDir * HexAngle.BACK) - current += burnDir - } - } while (graph[current]?.isNotEmpty() == true || stack.isNotEmpty()) - out.add(current) + val stack = Stack<HexCoord>() + val out = mutableListOf<HexCoord>() + do { + val exits = graph[current]!! + if (exits.isEmpty()) { + out.add(current) + current = stack.pop() + } else { + stack.push(current) + // This is where the random part happens, mostly + val burnDir = exits.random(rand) + exits.remove(burnDir) + graph[current + burnDir]?.remove(burnDir * HexAngle.BACK) + current += burnDir + } + } while (graph[current]?.isNotEmpty() == true || stack.isNotEmpty()) + out.add(current) - val dirs = out.zipWithNext { a, b -> a.immediateDelta(b)!! } - val angles = dirs.zipWithNext { a, b -> b.angleFrom(a) } - return HexPattern(dirs[0], angles.toMutableList()) - } + val dirs = out.zipWithNext { a, b -> a.immediateDelta(b)!! } + val angles = dirs.zipWithNext { a, b -> b.angleFrom(a) } + return HexPattern(dirs[0], angles.toMutableList()) + } - private fun toGraph(pat: HexPattern): HashMap<HexCoord, EnumSet<HexDir>> { - val graph = HashMap<HexCoord, EnumSet<HexDir>>() + private fun toGraph(pat: HexPattern): HashMap<HexCoord, EnumSet<HexDir>> { + val graph = HashMap<HexCoord, EnumSet<HexDir>>() - var compass: HexDir = pat.startDir - var cursor = HexCoord.Origin - for (a in pat.angles) { - // i hate kotlin - graph.getOrPut(cursor) { EnumSet.noneOf(HexDir::class.java) }.add(compass) - graph.getOrPut(cursor + compass) { EnumSet.noneOf(HexDir::class.java) }.add(compass * HexAngle.BACK) + var compass: HexDir = pat.startDir + var cursor = HexCoord.Origin + for (a in pat.angles) { + // i hate kotlin + graph.getOrPut(cursor) { EnumSet.noneOf(HexDir::class.java) }.add(compass) + graph + .getOrPut(cursor + compass) { EnumSet.noneOf(HexDir::class.java) } + .add(compass * HexAngle.BACK) - cursor += compass - compass *= a - } - graph.getOrPut(cursor) { EnumSet.noneOf(HexDir::class.java) }.add(compass) - graph.getOrPut(cursor + compass) { EnumSet.noneOf(HexDir::class.java) }.add(compass * HexAngle.BACK) + cursor += compass + compass *= a + } + graph.getOrPut(cursor) { EnumSet.noneOf(HexDir::class.java) }.add(compass) + graph + .getOrPut(cursor + compass) { EnumSet.noneOf(HexDir::class.java) } + .add(compass * HexAngle.BACK) - return graph - } + return graph + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexAngle.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexAngle.kt index bca8b0b94b..0d9fc999d0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexAngle.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexAngle.kt @@ -1,8 +1,14 @@ package at.petrak.hexcasting.api.casting.math enum class HexAngle { - FORWARD, RIGHT, RIGHT_BACK, BACK, LEFT_BACK, LEFT; + FORWARD, + RIGHT, + RIGHT_BACK, + BACK, + LEFT_BACK, + LEFT; - fun rotatedBy(a: HexAngle) = values()[(this.ordinal + a.ordinal) % values().size] - operator fun times(a: HexAngle) = this.rotatedBy(a) + fun rotatedBy(a: HexAngle) = values()[(this.ordinal + a.ordinal) % values().size] + + operator fun times(a: HexAngle) = this.rotatedBy(a) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexCoord.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexCoord.kt index 7102bdcce0..5737838b77 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexCoord.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexCoord.kt @@ -4,59 +4,58 @@ import kotlin.math.abs import kotlin.math.max import kotlin.math.min -/** - * Uses axial coordinates as per https://www.redblobgames.com/grids/hexagons/ - */ +/** Uses axial coordinates as per https://www.redblobgames.com/grids/hexagons/ */ data class HexCoord(val q: Int, val r: Int) { - fun s(): Int = -this.q - this.r - - fun shiftedBy(x: HexCoord): HexCoord = HexCoord(this.q + x.q, this.r + x.r) - - fun shiftedBy(d: HexDir) = this.shiftedBy(d.asDelta()) - - fun delta(x: HexCoord): HexCoord = HexCoord(this.q - x.q, this.r - x.r) - - operator fun plus(x: HexCoord) = this.shiftedBy(x) - operator fun plus(d: HexDir) = this.shiftedBy(d) - operator fun minus(x: HexCoord) = this.delta(x) - - fun distanceTo(x: HexCoord) = - (abs(this.q - x.q) + abs(this.q + this.r - x.q - x.r) + abs(this.r - x.r)) / 2 - - fun rangeAround(radius: Int): Iterator<HexCoord> = RingIter(this, radius) - - /** Get the direction that would bring you from this to its neighbor */ - fun immediateDelta(neighbor: HexCoord): HexDir? = - when (neighbor - this) { - HexCoord(1, 0) -> HexDir.EAST - HexCoord(0, 1) -> HexDir.SOUTH_EAST - HexCoord(-1, 1) -> HexDir.SOUTH_WEST - HexCoord(-1, 0) -> HexDir.WEST - HexCoord(0, -1) -> HexDir.NORTH_WEST - HexCoord(1, -1) -> HexDir.NORTH_EAST - else -> null - } - - // https://docs.rs/hex2d/1.1.0/src/hex2d/lib.rs.html#785 - private class RingIter(val center: HexCoord, val radius: Int) : Iterator<HexCoord> { - var q: Int = -radius - var r: Int = max(-radius, 0) - - override fun hasNext(): Boolean = r <= radius + min(0, -q) || q < radius - - override fun next(): HexCoord { - if (r > radius + min(0, -q)) { - q++ - r = -radius + max(0, -q) - } - val out = HexCoord(center.q + q, center.r + r) - r++ - return out - } - } - - companion object { - @JvmStatic - val Origin = HexCoord(0, 0) - } + fun s(): Int = -this.q - this.r + + fun shiftedBy(x: HexCoord): HexCoord = HexCoord(this.q + x.q, this.r + x.r) + + fun shiftedBy(d: HexDir) = this.shiftedBy(d.asDelta()) + + fun delta(x: HexCoord): HexCoord = HexCoord(this.q - x.q, this.r - x.r) + + operator fun plus(x: HexCoord) = this.shiftedBy(x) + + operator fun plus(d: HexDir) = this.shiftedBy(d) + + operator fun minus(x: HexCoord) = this.delta(x) + + fun distanceTo(x: HexCoord) = + (abs(this.q - x.q) + abs(this.q + this.r - x.q - x.r) + abs(this.r - x.r)) / 2 + + fun rangeAround(radius: Int): Iterator<HexCoord> = RingIter(this, radius) + + /** Get the direction that would bring you from this to its neighbor */ + fun immediateDelta(neighbor: HexCoord): HexDir? = + when (neighbor - this) { + HexCoord(1, 0) -> HexDir.EAST + HexCoord(0, 1) -> HexDir.SOUTH_EAST + HexCoord(-1, 1) -> HexDir.SOUTH_WEST + HexCoord(-1, 0) -> HexDir.WEST + HexCoord(0, -1) -> HexDir.NORTH_WEST + HexCoord(1, -1) -> HexDir.NORTH_EAST + else -> null + } + + // https://docs.rs/hex2d/1.1.0/src/hex2d/lib.rs.html#785 + private class RingIter(val center: HexCoord, val radius: Int) : Iterator<HexCoord> { + var q: Int = -radius + var r: Int = max(-radius, 0) + + override fun hasNext(): Boolean = r <= radius + min(0, -q) || q < radius + + override fun next(): HexCoord { + if (r > radius + min(0, -q)) { + q++ + r = -radius + max(0, -q) + } + val out = HexCoord(center.q + q, center.r + r) + r++ + return out + } + } + + companion object { + @JvmStatic val Origin = HexCoord(0, 0) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexDir.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexDir.kt index 03f4ca5a56..786500b167 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexDir.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexDir.kt @@ -4,37 +4,38 @@ import at.petrak.hexcasting.api.utils.getSafe import com.mojang.serialization.Codec enum class HexDir { - NORTH_EAST, EAST, SOUTH_EAST, SOUTH_WEST, WEST, NORTH_WEST; - - fun rotatedBy(a: HexAngle): HexDir = - values()[(this.ordinal + a.ordinal).mod(values().size)] - - operator fun times(a: HexAngle) = this.rotatedBy(a) - - fun angleFrom(other: HexDir): HexAngle = - HexAngle.values()[(this.ordinal - other.ordinal).mod(HexAngle.values().size)] - - operator fun minus(other: HexDir) = this.angleFrom(other) - - fun asDelta(): HexCoord = - when (this) { - NORTH_EAST -> HexCoord(1, -1) - EAST -> HexCoord(1, 0) - SOUTH_EAST -> HexCoord(0, 1) - SOUTH_WEST -> HexCoord(-1, 1) - WEST -> HexCoord(-1, 0) - NORTH_WEST -> HexCoord(0, -1) - } - - companion object { - val CODEC: Codec<HexDir> = Codec.STRING.xmap( - HexDir::fromString, - HexDir::name - ) - - @JvmStatic - fun fromString(key: String): HexDir { - return values().getSafe(key, WEST) - } - } + NORTH_EAST, + EAST, + SOUTH_EAST, + SOUTH_WEST, + WEST, + NORTH_WEST; + + fun rotatedBy(a: HexAngle): HexDir = values()[(this.ordinal + a.ordinal).mod(values().size)] + + operator fun times(a: HexAngle) = this.rotatedBy(a) + + fun angleFrom(other: HexDir): HexAngle = + HexAngle.values()[(this.ordinal - other.ordinal).mod(HexAngle.values().size)] + + operator fun minus(other: HexDir) = this.angleFrom(other) + + fun asDelta(): HexCoord = + when (this) { + NORTH_EAST -> HexCoord(1, -1) + EAST -> HexCoord(1, 0) + SOUTH_EAST -> HexCoord(0, 1) + SOUTH_WEST -> HexCoord(-1, 1) + WEST -> HexCoord(-1, 0) + NORTH_WEST -> HexCoord(0, -1) + } + + companion object { + val CODEC: Codec<HexDir> = Codec.STRING.xmap(HexDir::fromString, HexDir::name) + + @JvmStatic + fun fromString(key: String): HexDir { + return values().getSafe(key, WEST) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexPattern.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexPattern.kt index 001cfdeab4..643ad9cbf3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexPattern.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexPattern.kt @@ -10,169 +10,166 @@ import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.Tag import net.minecraft.world.phys.Vec2 -/** - * Sequence of angles to define a pattern traced. - */ +/** Sequence of angles to define a pattern traced. */ data class HexPattern(val startDir: HexDir, val angles: MutableList<HexAngle> = arrayListOf()) { - /** - * @return True if it successfully appended, false if not. - */ - fun tryAppendDir(newDir: HexDir): Boolean { - // Two restrictions: - // - No adding a pos/dir pair we previously added - // - No backtracking - val linesSeen = mutableSetOf<Pair<HexCoord, HexDir>>() - - var compass = this.startDir - var cursor = HexCoord.Origin - for (a in this.angles) { - linesSeen.add(cursor to compass) - // Line from here to there also blocks there to here - linesSeen.add(cursor + compass to compass.rotatedBy(HexAngle.BACK)) - cursor += compass - compass *= a - } - cursor += compass - - val potentialNewLine = cursor to newDir - if (potentialNewLine in linesSeen) return false - val nextAngle = newDir - compass - if (nextAngle == HexAngle.BACK) return false - - this.angles.add(nextAngle) - return true - } - - @JvmOverloads - fun positions(start: HexCoord = HexCoord.Origin): List<HexCoord> { - val out: ArrayList<HexCoord> = ArrayList(this.angles.size + 2) - out.add(start) - var compass: HexDir = this.startDir - var cursor = start - for (a in this.angles) { - cursor += compass - out.add(cursor) - compass *= a - } - out.add(cursor + compass) - return out - } - - fun directions(): List<HexDir> { - val out = ArrayList<HexDir>(this.angles.size + 1) - out.add(this.startDir) - - var compass: HexDir = this.startDir - for (a in this.angles) { - compass *= a - out.add(compass) - } - return out - } - - fun finalDir(): HexDir = - this.angles.fold(this.startDir) { acc, angle -> acc * angle } - - - fun serializeToNBT() = NBTBuilder { - TAG_START_DIR %= byte(startDir.ordinal) - TAG_ANGLES %= byteArray(angles.map(HexAngle::ordinal)) - } - - // Terrible shorthand method for easy matching - fun anglesSignature(): String { - return buildString { - for (a in this@HexPattern.angles) { - append( - when (a) { - HexAngle.FORWARD -> "w" - HexAngle.RIGHT -> "e" - HexAngle.RIGHT_BACK -> "d" - HexAngle.BACK -> "s" - HexAngle.LEFT_BACK -> "a" - HexAngle.LEFT -> "q" - } - ) - } - } - } - - /** - * Return the "center of mass" of the pattern. - * Drawing the pattern with the returned vector as the origin will center the pattern around it. - */ - @JvmOverloads - fun getCenter(hexRadius: Float, origin: HexCoord = HexCoord.Origin): Vec2 { - val originPx = coordToPx(origin, hexRadius, Vec2.ZERO) - val points = this.toLines(hexRadius, originPx) - return findCenter(points) - } - - - /** - * Convert a hex pattern into a sequence of straight linePoints spanning its points. - */ - fun toLines(hexSize: Float, origin: Vec2): List<Vec2> = - this.positions().map { coordToPx(it, hexSize, origin) } - - fun sigsEqual(that: HexPattern) = this.angles == that.angles - - override fun toString(): String = buildString { - append("HexPattern[") - append(this@HexPattern.startDir) - append(", ") - append(this@HexPattern.anglesSignature()) - append("]") - } - - companion object { - const val TAG_START_DIR = "start_dir" - const val TAG_ANGLES = "angles" - - @JvmField - val CODEC: Codec<HexPattern> = RecordCodecBuilder.create({instance -> instance.group( - Codec.STRING.fieldOf(TAG_START_DIR).forGetter(HexPattern::anglesSignature), - HexDir.CODEC.fieldOf(TAG_ANGLES).forGetter(HexPattern::startDir) - ).apply(instance, HexPattern::fromAngles) - }) - - @JvmStatic - fun isPattern(tag: CompoundTag): Boolean { - return tag.contains(TAG_START_DIR, Tag.TAG_ANY_NUMERIC.toInt()) - && tag.contains(TAG_ANGLES, Tag.TAG_BYTE_ARRAY.toInt()) - } - - @JvmStatic - fun fromNBT(tag: CompoundTag): HexPattern { - val startDir = HexDir.values().getSafe(tag.getByte(TAG_START_DIR)) - val angles = tag.getByteArray(TAG_ANGLES).map(HexAngle.values()::getSafe) - return HexPattern(startDir, angles.toMutableList()) - } - - @JvmStatic - fun fromAngles(signature: String, startDir: HexDir): HexPattern { - val out = HexPattern(startDir) - var compass = startDir - - for ((idx, c) in signature.withIndex()) { - val angle = when (c) { - 'w' -> HexAngle.FORWARD - 'e' -> HexAngle.RIGHT - 'd' -> HexAngle.RIGHT_BACK - // for completeness ... - 's' -> HexAngle.BACK - 'a' -> HexAngle.LEFT_BACK - 'q' -> HexAngle.LEFT - else -> throw IllegalArgumentException("Cannot match $c at idx $idx to a direction") - } - compass *= angle - val success = out.tryAppendDir(compass) - if (!success) { - throw IllegalStateException("Adding the angle $c at index $idx made the pattern invalid by looping back on itself") - } - } - return out - } - - } + /** @return True if it successfully appended, false if not. */ + fun tryAppendDir(newDir: HexDir): Boolean { + // Two restrictions: + // - No adding a pos/dir pair we previously added + // - No backtracking + val linesSeen = mutableSetOf<Pair<HexCoord, HexDir>>() + + var compass = this.startDir + var cursor = HexCoord.Origin + for (a in this.angles) { + linesSeen.add(cursor to compass) + // Line from here to there also blocks there to here + linesSeen.add(cursor + compass to compass.rotatedBy(HexAngle.BACK)) + cursor += compass + compass *= a + } + cursor += compass + + val potentialNewLine = cursor to newDir + if (potentialNewLine in linesSeen) return false + val nextAngle = newDir - compass + if (nextAngle == HexAngle.BACK) return false + + this.angles.add(nextAngle) + return true + } + + @JvmOverloads + fun positions(start: HexCoord = HexCoord.Origin): List<HexCoord> { + val out: ArrayList<HexCoord> = ArrayList(this.angles.size + 2) + out.add(start) + var compass: HexDir = this.startDir + var cursor = start + for (a in this.angles) { + cursor += compass + out.add(cursor) + compass *= a + } + out.add(cursor + compass) + return out + } + + fun directions(): List<HexDir> { + val out = ArrayList<HexDir>(this.angles.size + 1) + out.add(this.startDir) + + var compass: HexDir = this.startDir + for (a in this.angles) { + compass *= a + out.add(compass) + } + return out + } + + fun finalDir(): HexDir = this.angles.fold(this.startDir) { acc, angle -> acc * angle } + + fun serializeToNBT() = NBTBuilder { + TAG_START_DIR %= byte(startDir.ordinal) + TAG_ANGLES %= byteArray(angles.map(HexAngle::ordinal)) + } + + // Terrible shorthand method for easy matching + fun anglesSignature(): String { + return buildString { + for (a in this@HexPattern.angles) { + append( + when (a) { + HexAngle.FORWARD -> "w" + HexAngle.RIGHT -> "e" + HexAngle.RIGHT_BACK -> "d" + HexAngle.BACK -> "s" + HexAngle.LEFT_BACK -> "a" + HexAngle.LEFT -> "q" + } + ) + } + } + } + + /** + * Return the "center of mass" of the pattern. Drawing the pattern with the returned vector as the + * origin will center the pattern around it. + */ + @JvmOverloads + fun getCenter(hexRadius: Float, origin: HexCoord = HexCoord.Origin): Vec2 { + val originPx = coordToPx(origin, hexRadius, Vec2.ZERO) + val points = this.toLines(hexRadius, originPx) + return findCenter(points) + } + + /** Convert a hex pattern into a sequence of straight linePoints spanning its points. */ + fun toLines(hexSize: Float, origin: Vec2): List<Vec2> = + this.positions().map { coordToPx(it, hexSize, origin) } + + fun sigsEqual(that: HexPattern) = this.angles == that.angles + + override fun toString(): String = buildString { + append("HexPattern[") + append(this@HexPattern.startDir) + append(", ") + append(this@HexPattern.anglesSignature()) + append("]") + } + + companion object { + const val TAG_START_DIR = "start_dir" + const val TAG_ANGLES = "angles" + + @JvmField + val CODEC: Codec<HexPattern> = + RecordCodecBuilder.create({ instance -> + instance + .group( + Codec.STRING.fieldOf(TAG_START_DIR).forGetter(HexPattern::anglesSignature), + HexDir.CODEC.fieldOf(TAG_ANGLES).forGetter(HexPattern::startDir) + ) + .apply(instance, HexPattern::fromAngles) + }) + + @JvmStatic + fun isPattern(tag: CompoundTag): Boolean { + return tag.contains(TAG_START_DIR, Tag.TAG_ANY_NUMERIC.toInt()) && + tag.contains(TAG_ANGLES, Tag.TAG_BYTE_ARRAY.toInt()) + } + + @JvmStatic + fun fromNBT(tag: CompoundTag): HexPattern { + val startDir = HexDir.values().getSafe(tag.getByte(TAG_START_DIR)) + val angles = tag.getByteArray(TAG_ANGLES).map(HexAngle.values()::getSafe) + return HexPattern(startDir, angles.toMutableList()) + } + + @JvmStatic + fun fromAngles(signature: String, startDir: HexDir): HexPattern { + val out = HexPattern(startDir) + var compass = startDir + + for ((idx, c) in signature.withIndex()) { + val angle = + when (c) { + 'w' -> HexAngle.FORWARD + 'e' -> HexAngle.RIGHT + 'd' -> HexAngle.RIGHT_BACK + // for completeness ... + 's' -> HexAngle.BACK + 'a' -> HexAngle.LEFT_BACK + 'q' -> HexAngle.LEFT + else -> throw IllegalArgumentException("Cannot match $c at idx $idx to a direction") + } + compass *= angle + val success = out.tryAppendDir(compass) + if (!success) { + throw IllegalStateException( + "Adding the angle $c at index $idx made the pattern invalid by looping back on itself" + ) + } + } + return out + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/Mishap.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/Mishap.kt index b9462fdda9..9facc058f4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/Mishap.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/Mishap.kt @@ -20,98 +20,100 @@ import net.minecraft.world.item.ItemStack import net.minecraft.world.phys.Vec3 abstract class Mishap : Throwable() { - /** Mishaps spray half-red, half-this-color. */ - abstract fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment - - open fun particleSpray(ctx: CastingEnvironment): ParticleSpray { - return ParticleSpray( - ctx.mishapSprayPos().add(0.0, 0.2, 0.0), - Vec3(0.0, 2.0, 0.0), - 0.2, Math.PI / 4, 40) - } - - open fun resolutionType(ctx: CastingEnvironment): ResolvedPatternType = ResolvedPatternType.ERRORED - - /** - * Execute the actual effect, not any sfx. - * - * You can also mess up the stack with this. - */ - abstract fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) - - protected abstract fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component? - - fun executeReturnStack(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>): List<Iota> { - execute(ctx, errorCtx, stack) - return stack - } - - /** - * Every error message should be prefixed with the name of the action... - */ - fun errorMessageWithName(ctx: CastingEnvironment, errorCtx: Context): Component? { - return if (errorCtx.name != null) { - "hexcasting.mishap".asTranslatedComponent(errorCtx.name, this.errorMessage(ctx, errorCtx) ?: return null) - } else { - this.errorMessage(ctx, errorCtx) - } - } - - // Useful helper functions - - protected fun dyeColor(color: DyeColor): FrozenPigment = - FrozenPigment( - ItemStack(HexItems.DYE_PIGMENTS[color]!!), - Util.NIL_UUID - ) - - protected fun error(stub: String, vararg args: Any): Component = - "hexcasting.mishap.$stub".asTranslatedComponent(*args) - - protected fun actionName(name: Component?): Component = - name ?: "hexcasting.spell.null".asTranslatedComponent.lightPurple - - protected fun blockAtPos(ctx: CastingEnvironment, pos: BlockPos): Component { - return ctx.world.getBlockState(pos).block.name - } - - data class Context(val pattern: HexPattern?, val name: Component?) - - companion object { - @JvmStatic - fun trulyHurt(entity: LivingEntity, source: DamageSource, amount: Float) { - entity.setHurtWithStamp(source, entity.level().gameTime) - - val targetHealth = entity.health - amount - if (entity.invulnerableTime > 10) { - val lastHurt = entity.lastHurt - if (lastHurt < amount) - entity.invulnerableTime = 0 - else - entity.lastHurt -= amount - } - if (!entity.hurt(source, amount) && - !entity.isInvulnerableTo(source) && - !entity.level().isClientSide && - !entity.isDeadOrDying - ) { - - // Ok, if you REALLY don't want to play nice... - entity.health = targetHealth - entity.markHurt() - - if (entity.isDeadOrDying) { - if (!entity.checkTotemDeathProtection(source)) { - val sound = entity.deathSoundAccessor - if (sound != null) { - entity.playSound(sound, entity.soundVolumeAccessor, entity.voicePitch) - } - entity.die(source) - } - } else { - entity.playHurtSound(source) - } - } - } - } + /** Mishaps spray half-red, half-this-color. */ + abstract fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment + + open fun particleSpray(ctx: CastingEnvironment): ParticleSpray { + return ParticleSpray( + ctx.mishapSprayPos().add(0.0, 0.2, 0.0), + Vec3(0.0, 2.0, 0.0), + 0.2, + Math.PI / 4, + 40 + ) + } + + open fun resolutionType(ctx: CastingEnvironment): ResolvedPatternType = + ResolvedPatternType.ERRORED + + /** + * Execute the actual effect, not any sfx. + * + * You can also mess up the stack with this. + */ + abstract fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) + + protected abstract fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component? + + fun executeReturnStack( + ctx: CastingEnvironment, + errorCtx: Context, + stack: MutableList<Iota> + ): List<Iota> { + execute(ctx, errorCtx, stack) + return stack + } + + /** Every error message should be prefixed with the name of the action... */ + fun errorMessageWithName(ctx: CastingEnvironment, errorCtx: Context): Component? { + return if (errorCtx.name != null) { + "hexcasting.mishap" + .asTranslatedComponent(errorCtx.name, this.errorMessage(ctx, errorCtx) ?: return null) + } else { + this.errorMessage(ctx, errorCtx) + } + } + + // Useful helper functions + + protected fun dyeColor(color: DyeColor): FrozenPigment = + FrozenPigment(ItemStack(HexItems.DYE_PIGMENTS[color]!!), Util.NIL_UUID) + + protected fun error(stub: String, vararg args: Any): Component = + "hexcasting.mishap.$stub".asTranslatedComponent(*args) + + protected fun actionName(name: Component?): Component = + name ?: "hexcasting.spell.null".asTranslatedComponent.lightPurple + + protected fun blockAtPos(ctx: CastingEnvironment, pos: BlockPos): Component { + return ctx.world.getBlockState(pos).block.name + } + + data class Context(val pattern: HexPattern?, val name: Component?) + + companion object { + @JvmStatic + fun trulyHurt(entity: LivingEntity, source: DamageSource, amount: Float) { + entity.setHurtWithStamp(source, entity.level().gameTime) + + val targetHealth = entity.health - amount + if (entity.invulnerableTime > 10) { + val lastHurt = entity.lastHurt + if (lastHurt < amount) entity.invulnerableTime = 0 else entity.lastHurt -= amount + } + if ( + !entity.hurt(source, amount) && + !entity.isInvulnerableTo(source) && + !entity.level().isClientSide && + !entity.isDeadOrDying + ) { + + // Ok, if you REALLY don't want to play nice... + entity.health = targetHealth + entity.markHurt() + + if (entity.isDeadOrDying) { + if (!entity.checkTotemDeathProtection(source)) { + val sound = entity.deathSoundAccessor + if (sound != null) { + entity.playSound(sound, entity.soundVolumeAccessor, entity.voicePitch) + } + entity.die(source) + } + } else { + entity.playHurtSound(source) + } + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapAlreadyBrainswept.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapAlreadyBrainswept.kt index fcfe86b2d7..8d602d911f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapAlreadyBrainswept.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapAlreadyBrainswept.kt @@ -9,17 +9,15 @@ import net.minecraft.world.entity.Mob import net.minecraft.world.item.DyeColor class MishapAlreadyBrainswept(val mob: Mob) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.GREEN) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.GREEN) - override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - mob.hurt(mob.damageSources().source(HexDamageTypes.OVERCAST, ctx.castingEntity), mob.health) - } + override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + mob.hurt(mob.damageSources().source(HexDamageTypes.OVERCAST, ctx.castingEntity), mob.health) + } - override fun particleSpray(ctx: CastingEnvironment) = - ParticleSpray.burst(mob.eyePosition, 1.0) - - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("already_brainswept") + override fun particleSpray(ctx: CastingEnvironment) = ParticleSpray.burst(mob.eyePosition, 1.0) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error("already_brainswept") } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBlock.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBlock.kt index b97a1b72f6..3e1848f19a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBlock.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBlock.kt @@ -8,28 +8,34 @@ import at.petrak.hexcasting.api.utils.asTranslatedComponent import net.minecraft.core.BlockPos import net.minecraft.network.chat.Component import net.minecraft.world.item.DyeColor -import net.minecraft.world.level.Explosion import net.minecraft.world.level.Level import net.minecraft.world.phys.Vec3 class MishapBadBlock(val pos: BlockPos, val expected: Component) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.LIME) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.LIME) - override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - ctx.world.explode(null, pos.x + 0.5, pos.y + 0.5, pos.z + 0.5, 0.25f, Level.ExplosionInteraction.NONE) - } + override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + ctx.world.explode( + null, + pos.x + 0.5, + pos.y + 0.5, + pos.z + 0.5, + 0.25f, + Level.ExplosionInteraction.NONE + ) + } - override fun particleSpray(ctx: CastingEnvironment) = - ParticleSpray.burst(Vec3.atCenterOf(pos), 1.0) + override fun particleSpray(ctx: CastingEnvironment) = + ParticleSpray.burst(Vec3.atCenterOf(pos), 1.0) - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("bad_block", expected, this.pos.toShortString(), blockAtPos(ctx, this.pos)) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error("bad_block", expected, this.pos.toShortString(), blockAtPos(ctx, this.pos)) - companion object { - @JvmStatic - fun of(pos: BlockPos, stub: String): MishapBadBlock { - return MishapBadBlock(pos, "hexcasting.mishap.bad_block.$stub".asTranslatedComponent) - } - } + companion object { + @JvmStatic + fun of(pos: BlockPos, stub: String): MishapBadBlock { + return MishapBadBlock(pos, "hexcasting.mishap.bad_block.$stub".asTranslatedComponent) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBrainsweep.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBrainsweep.kt index 601273fbb0..e3ead09400 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBrainsweep.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBrainsweep.kt @@ -11,17 +11,17 @@ import net.minecraft.world.item.DyeColor import net.minecraft.world.phys.Vec3 class MishapBadBrainsweep(val mob: Mob, val pos: BlockPos) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.GREEN) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.GREEN) - override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - trulyHurt(mob, mob.damageSources().source(HexDamageTypes.OVERCAST, ctx.castingEntity), 1f) - } + override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + trulyHurt(mob, mob.damageSources().source(HexDamageTypes.OVERCAST, ctx.castingEntity), 1f) + } - override fun particleSpray(ctx: CastingEnvironment): ParticleSpray { - return ParticleSpray.burst(Vec3.atCenterOf(pos), 1.0) - } + override fun particleSpray(ctx: CastingEnvironment): ParticleSpray { + return ParticleSpray.burst(Vec3.atCenterOf(pos), 1.0) + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("bad_brainsweep", blockAtPos(ctx, this.pos)) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error("bad_brainsweep", blockAtPos(ctx, this.pos)) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadCaster.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadCaster.kt index 99199f9561..3e39650b32 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadCaster.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadCaster.kt @@ -5,13 +5,11 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment import net.minecraft.world.item.DyeColor -class MishapBadCaster: Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.RED) +class MishapBadCaster : Mishap() { + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.RED) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) {} - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("bad_caster") -} \ No newline at end of file + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = error("bad_caster") +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadEntity.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadEntity.kt index 336a4fa18e..0adfe3aa31 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadEntity.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadEntity.kt @@ -11,23 +11,22 @@ import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.item.DyeColor class MishapBadEntity(val entity: Entity, val wanted: Component) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.BROWN) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.BROWN) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - env.mishapEnvironment.yeetHeldItemsTowards(entity.position()) - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + env.mishapEnvironment.yeetHeldItemsTowards(entity.position()) + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("bad_entity", wanted, entity.displayName.plainCopy().aqua) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error("bad_entity", wanted, entity.displayName.plainCopy().aqua) - companion object { - @JvmStatic - fun of(entity: Entity, stub: String): Mishap { - val component = "hexcasting.mishap.bad_item.$stub".asTranslatedComponent - if (entity is ItemEntity) - return MishapBadItem(entity, component) - return MishapBadEntity(entity, component) - } - } + companion object { + @JvmStatic + fun of(entity: Entity, stub: String): Mishap { + val component = "hexcasting.mishap.bad_item.$stub".asTranslatedComponent + if (entity is ItemEntity) return MishapBadItem(entity, component) + return MishapBadEntity(entity, component) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadItem.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadItem.kt index d41cc88f32..42fdfac933 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadItem.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadItem.kt @@ -9,22 +9,22 @@ import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.item.DyeColor class MishapBadItem(val item: ItemEntity, val wanted: Component) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.BROWN) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.BROWN) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - item.deltaMovement = item.deltaMovement.add((Math.random() - 0.5) * 0.05, 0.75, (Math.random() - 0.5) * 0.05) - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + item.deltaMovement = + item.deltaMovement.add((Math.random() - 0.5) * 0.05, 0.75, (Math.random() - 0.5) * 0.05) + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = if (item.item.isEmpty) - error("no_item", wanted) - else - error("bad_item", wanted, item.item.count, item.item.displayName) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + if (item.item.isEmpty) error("no_item", wanted) + else error("bad_item", wanted, item.item.count, item.item.displayName) - companion object { - @JvmStatic - fun of(item: ItemEntity, stub: String): MishapBadItem { - return MishapBadItem(item, "hexcasting.mishap.bad_item.$stub".asTranslatedComponent) - } - } + companion object { + @JvmStatic + fun of(item: ItemEntity, stub: String): MishapBadItem { + return MishapBadItem(item, "hexcasting.mishap.bad_item.$stub".asTranslatedComponent) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadLocation.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadLocation.kt index 06955885a0..a15f7bfb17 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadLocation.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadLocation.kt @@ -9,13 +9,13 @@ import net.minecraft.world.item.DyeColor import net.minecraft.world.phys.Vec3 class MishapBadLocation(val location: Vec3, val type: String = "too_far") : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.MAGENTA) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.MAGENTA) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - env.mishapEnvironment.yeetHeldItemsTowards(this.location) - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + env.mishapEnvironment.yeetHeldItemsTowards(this.location) + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = - error("location_$type", Vec3Iota.display(location)) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = + error("location_$type", Vec3Iota.display(location)) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt index d35104dab4..5557b0edc2 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt @@ -5,27 +5,28 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment import at.petrak.hexcasting.api.utils.asTranslatedComponent import net.minecraft.network.chat.Component -import net.minecraft.world.InteractionHand import net.minecraft.world.item.DyeColor import net.minecraft.world.item.ItemStack class MishapBadOffhandItem(val item: ItemStack?, val wanted: Component) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.BROWN) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.BROWN) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - env.mishapEnvironment.dropHeldItems() - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + env.mishapEnvironment.dropHeldItems() + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = if (item?.isEmpty == false) - error("bad_item.offhand", wanted, item.count, item.displayName) - else - error("no_item.offhand", wanted) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + if (item?.isEmpty == false) error("bad_item.offhand", wanted, item.count, item.displayName) + else error("no_item.offhand", wanted) - companion object { - @JvmStatic - fun of(item: ItemStack?, stub: String, vararg args: Any): MishapBadOffhandItem { - return MishapBadOffhandItem(item, "hexcasting.mishap.bad_item.$stub".asTranslatedComponent(*args)) - } - } + companion object { + @JvmStatic + fun of(item: ItemStack?, stub: String, vararg args: Any): MishapBadOffhandItem { + return MishapBadOffhandItem( + item, + "hexcasting.mishap.bad_item.$stub".asTranslatedComponent(*args) + ) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDisallowedSpell.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDisallowedSpell.kt index d3118e5590..25c682f5d3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDisallowedSpell.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDisallowedSpell.kt @@ -7,15 +7,14 @@ import at.petrak.hexcasting.api.pigment.FrozenPigment import net.minecraft.world.item.DyeColor class MishapDisallowedSpell(val type: String = "disallowed") : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.BLACK) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.BLACK) - override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.INVALID + override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.INVALID - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - // NO-OP - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + // NO-OP + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error(type) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = error(type) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDivideByZero.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDivideByZero.kt index 98050ee244..4aedbb5cc5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDivideByZero.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDivideByZero.kt @@ -11,80 +11,93 @@ import net.minecraft.network.chat.Component import net.minecraft.world.item.DyeColor import net.minecraft.world.phys.Vec3 -class MishapDivideByZero(val operand1: Component, val operand2: Component, val suffix: String = "divide") : Mishap() { - - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.RED) - - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - stack.add(GarbageIota()) - env.mishapEnvironment.damage(0.5f) - } - - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("divide_by_zero.$suffix", operand1, operand2) - - companion object { - private const val PREFIX = "hexcasting.mishap.divide_by_zero" - - @JvmStatic - fun of(operand1: Double, operand2: Double, suffix: String = "divide"): MishapDivideByZero { - if (suffix == "exponent") - return MishapDivideByZero(translate(DoubleIota(operand1)), powerOf(DoubleIota(operand2)), suffix) - return MishapDivideByZero(translate(DoubleIota(operand1)), translate(DoubleIota(operand2)), suffix) - } - - @JvmStatic - fun of(operand1: Iota, operand2: Iota, suffix: String = "divide"): MishapDivideByZero { - if (suffix == "exponent") - return MishapDivideByZero(translate(operand1), powerOf(operand2), suffix) - return MishapDivideByZero(translate(operand1), translate(operand2), suffix) - } - - @JvmStatic - fun tan(angle: Double): MishapDivideByZero { - val translatedAngle = translate(DoubleIota(angle)) - return MishapDivideByZero( - "$PREFIX.sin".asTranslatedComponent(translatedAngle), - "$PREFIX.cos".asTranslatedComponent(translatedAngle) - ) - } - - @JvmStatic - fun tan(angle: DoubleIota): MishapDivideByZero { - val translatedAngle = translate(angle) - return MishapDivideByZero( - "$PREFIX.sin".asTranslatedComponent(translatedAngle), - "$PREFIX.cos".asTranslatedComponent(translatedAngle) - ) - } - - @JvmStatic - val zero - get() = "$PREFIX.zero".asTranslatedComponent - - @JvmStatic - val zerothPower - get() = "$PREFIX.zero.power".asTranslatedComponent - - @JvmStatic - val zeroVector - get() = "$PREFIX.zero.vec".asTranslatedComponent - - @JvmStatic - fun powerOf(power: Component) = "$PREFIX.power".asTranslatedComponent(power) - - @JvmStatic - fun powerOf(datum: Iota): Component = when { - datum is DoubleIota && datum.double == 0.0 -> zerothPower - else -> datum.display() - } - - @JvmStatic - fun translate(datum: Iota): Component = when { - datum is DoubleIota && datum.double == 0.0 -> zero - datum is Vec3Iota && datum.vec3 == Vec3.ZERO -> zeroVector - else -> datum.display() - } - } +class MishapDivideByZero( + val operand1: Component, + val operand2: Component, + val suffix: String = "divide" +) : Mishap() { + + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.RED) + + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + stack.add(GarbageIota()) + env.mishapEnvironment.damage(0.5f) + } + + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error("divide_by_zero.$suffix", operand1, operand2) + + companion object { + private const val PREFIX = "hexcasting.mishap.divide_by_zero" + + @JvmStatic + fun of(operand1: Double, operand2: Double, suffix: String = "divide"): MishapDivideByZero { + if (suffix == "exponent") + return MishapDivideByZero( + translate(DoubleIota(operand1)), + powerOf(DoubleIota(operand2)), + suffix + ) + return MishapDivideByZero( + translate(DoubleIota(operand1)), + translate(DoubleIota(operand2)), + suffix + ) + } + + @JvmStatic + fun of(operand1: Iota, operand2: Iota, suffix: String = "divide"): MishapDivideByZero { + if (suffix == "exponent") + return MishapDivideByZero(translate(operand1), powerOf(operand2), suffix) + return MishapDivideByZero(translate(operand1), translate(operand2), suffix) + } + + @JvmStatic + fun tan(angle: Double): MishapDivideByZero { + val translatedAngle = translate(DoubleIota(angle)) + return MishapDivideByZero( + "$PREFIX.sin".asTranslatedComponent(translatedAngle), + "$PREFIX.cos".asTranslatedComponent(translatedAngle) + ) + } + + @JvmStatic + fun tan(angle: DoubleIota): MishapDivideByZero { + val translatedAngle = translate(angle) + return MishapDivideByZero( + "$PREFIX.sin".asTranslatedComponent(translatedAngle), + "$PREFIX.cos".asTranslatedComponent(translatedAngle) + ) + } + + @JvmStatic + val zero + get() = "$PREFIX.zero".asTranslatedComponent + + @JvmStatic + val zerothPower + get() = "$PREFIX.zero.power".asTranslatedComponent + + @JvmStatic + val zeroVector + get() = "$PREFIX.zero.vec".asTranslatedComponent + + @JvmStatic fun powerOf(power: Component) = "$PREFIX.power".asTranslatedComponent(power) + + @JvmStatic + fun powerOf(datum: Iota): Component = + when { + datum is DoubleIota && datum.double == 0.0 -> zerothPower + else -> datum.display() + } + + @JvmStatic + fun translate(datum: Iota): Component = + when { + datum is DoubleIota && datum.double == 0.0 -> zero + datum is Vec3Iota && datum.vec3 == Vec3.ZERO -> zeroVector + else -> datum.display() + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityTooFarAway.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityTooFarAway.kt index 41671a219c..7ba9b0fdf0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityTooFarAway.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityTooFarAway.kt @@ -8,13 +8,13 @@ import net.minecraft.world.entity.Entity import net.minecraft.world.item.DyeColor class MishapEntityTooFarAway(val entity: Entity) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.PINK) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.PINK) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - env.mishapEnvironment.yeetHeldItemsTowards(entity.position()) - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + env.mishapEnvironment.yeetHeldItemsTowards(entity.position()) + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = - error("entity_too_far", entity.displayName) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = + error("entity_too_far", entity.displayName) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEvalTooMuch.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEvalTooMuch.kt index 24ecda81e8..90882770f6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEvalTooMuch.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEvalTooMuch.kt @@ -6,13 +6,12 @@ import at.petrak.hexcasting.api.pigment.FrozenPigment import net.minecraft.world.item.DyeColor class MishapEvalTooMuch : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.BLUE) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.BLUE) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - env.mishapEnvironment.drown() - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + env.mishapEnvironment.drown() + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("eval_too_deep") + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = error("eval_too_deep") } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapImmuneEntity.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapImmuneEntity.kt index a722efb2ec..cf09d200ee 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapImmuneEntity.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapImmuneEntity.kt @@ -8,13 +8,13 @@ import net.minecraft.world.entity.Entity import net.minecraft.world.item.DyeColor class MishapImmuneEntity(val entity: Entity) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.BLUE) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.BLUE) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - env.mishapEnvironment.yeetHeldItemsTowards(entity.position()) - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + env.mishapEnvironment.yeetHeldItemsTowards(entity.position()) + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("immune_entity", entity.displayName.plainCopy().aqua) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error("immune_entity", entity.displayName.plainCopy().aqua) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInternalException.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInternalException.kt index 7301c01127..cc04180e90 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInternalException.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInternalException.kt @@ -6,13 +6,13 @@ import at.petrak.hexcasting.api.pigment.FrozenPigment import net.minecraft.world.item.DyeColor class MishapInternalException(val exception: Exception) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.BLACK) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.BLACK) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - // NO-OP - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + // NO-OP + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("unknown", exception) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error("unknown", exception) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidIota.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidIota.kt index 17e71d6044..fb9ea88ddc 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidIota.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidIota.kt @@ -8,37 +8,34 @@ import at.petrak.hexcasting.api.utils.asTranslatedComponent import net.minecraft.network.chat.Component import net.minecraft.world.item.DyeColor -/** - * The value failed some kind of predicate. - */ -class MishapInvalidIota( - val perpetrator: Iota, - val reverseIdx: Int, - val expected: Component -) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.GRAY) +/** The value failed some kind of predicate. */ +class MishapInvalidIota(val perpetrator: Iota, val reverseIdx: Int, val expected: Component) : + Mishap() { + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.GRAY) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - stack[stack.size - 1 - reverseIdx] = GarbageIota(); - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + stack[stack.size - 1 - reverseIdx] = GarbageIota() + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error( - "invalid_value", expected, reverseIdx, - perpetrator.display() - ) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error("invalid_value", expected, reverseIdx, perpetrator.display()) - companion object { - @JvmStatic - fun ofType(perpetrator: Iota, reverseIdx: Int, name: String): MishapInvalidIota { - return of(perpetrator, reverseIdx, "class.$name") - } + companion object { + @JvmStatic + fun ofType(perpetrator: Iota, reverseIdx: Int, name: String): MishapInvalidIota { + return of(perpetrator, reverseIdx, "class.$name") + } - @JvmStatic - fun of(perpetrator: Iota, reverseIdx: Int, name: String, vararg translations: Any): MishapInvalidIota { - val key = "hexcasting.mishap.invalid_value.$name" - return MishapInvalidIota(perpetrator, reverseIdx, key.asTranslatedComponent(*translations)) - } - } + @JvmStatic + fun of( + perpetrator: Iota, + reverseIdx: Int, + name: String, + vararg translations: Any + ): MishapInvalidIota { + val key = "hexcasting.mishap.invalid_value.$name" + return MishapInvalidIota(perpetrator, reverseIdx, key.asTranslatedComponent(*translations)) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidOperatorArgs.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidOperatorArgs.kt index a16c083f4c..7d0f14b5c0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidOperatorArgs.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidOperatorArgs.kt @@ -9,34 +9,28 @@ import net.minecraft.network.chat.Component import net.minecraft.network.chat.ComponentUtils import net.minecraft.world.item.DyeColor -/** - * The value failed some kind of predicate. - */ +/** The value failed some kind of predicate. */ class MishapInvalidOperatorArgs(val perpetrators: List<Iota>) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.GRAY) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.GRAY) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - for (i in perpetrators.indices) { - stack[stack.size - 1 - i] = GarbageIota() - } - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + for (i in perpetrators.indices) { + stack[stack.size - 1 - i] = GarbageIota() + } + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component { - return if (perpetrators.size == 1) { - error( - "invalid_operator_args.one", - 0, - perpetrators[0].display() - ) - } else { - error( - "invalid_operator_args.many", - perpetrators.size, - 0, - perpetrators.lastIndex, - ComponentUtils.formatList(perpetrators.map { it.display() }, ", ".asTextComponent) - ) - } - } + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component { + return if (perpetrators.size == 1) { + error("invalid_operator_args.one", 0, perpetrators[0].display()) + } else { + error( + "invalid_operator_args.many", + perpetrators.size, + 0, + perpetrators.lastIndex, + ComponentUtils.formatList(perpetrators.map { it.display() }, ", ".asTextComponent) + ) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidPattern.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidPattern.kt index 20fbd31fb5..1244c81149 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidPattern.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidPattern.kt @@ -8,15 +8,14 @@ import at.petrak.hexcasting.api.pigment.FrozenPigment import net.minecraft.world.item.DyeColor class MishapInvalidPattern : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.YELLOW) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.YELLOW) - override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.INVALID + override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.INVALID - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - stack.add(GarbageIota()) - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + stack.add(GarbageIota()) + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("invalid_pattern") + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = error("invalid_pattern") } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidSpellDatumType.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidSpellDatumType.kt index 92384b0792..142c544a92 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidSpellDatumType.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidSpellDatumType.kt @@ -5,17 +5,19 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment import net.minecraft.world.item.DyeColor -/** - * this is bad - */ +/** this is bad */ class MishapInvalidSpellDatumType(val perpetrator: Any) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.BLACK) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.BLACK) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - // NO-OP - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + // NO-OP + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("invalid_spell_datum_type", this.perpetrator.toString(), this.perpetrator.javaClass.typeName) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error( + "invalid_spell_datum_type", + this.perpetrator.toString(), + this.perpetrator.javaClass.typeName + ) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLocationInWrongDimension.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLocationInWrongDimension.kt index 2d0e721838..87a80979bf 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLocationInWrongDimension.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLocationInWrongDimension.kt @@ -9,16 +9,17 @@ import net.minecraft.resources.ResourceLocation import net.minecraft.world.item.DyeColor class MishapLocationInWrongDimension(val properDimension: ResourceLocation) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.MAGENTA) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.MAGENTA) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - stack.add(GarbageIota()) - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + stack.add(GarbageIota()) + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = - error( - "wrong_dimension", properDimension.toString(), - ctx.world.dimension().location().toString() - ) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = + error( + "wrong_dimension", + properDimension.toString(), + ctx.world.dimension().location().toString() + ) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNoAkashicRecord.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNoAkashicRecord.kt index 05eb6f5837..424ffbc1e8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNoAkashicRecord.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNoAkashicRecord.kt @@ -7,13 +7,13 @@ import net.minecraft.core.BlockPos import net.minecraft.world.item.DyeColor class MishapNoAkashicRecord(val pos: BlockPos) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.PURPLE) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.PURPLE) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - env.mishapEnvironment.removeXp(100) - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + env.mishapEnvironment.removeXp(100) + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("no_akashic_record", pos.toShortString()) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error("no_akashic_record", pos.toShortString()) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughArgs.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughArgs.kt index 646f42c927..9f85e8b178 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughArgs.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughArgs.kt @@ -7,16 +7,13 @@ import at.petrak.hexcasting.api.pigment.FrozenPigment import net.minecraft.world.item.DyeColor class MishapNotEnoughArgs(val expected: Int, val got: Int) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.LIGHT_GRAY) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.LIGHT_GRAY) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - repeat(expected - got) { stack.add(GarbageIota()) } - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + repeat(expected - got) { stack.add(GarbageIota()) } + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - if (got == 0) - error("no_args", expected) - else - error("not_enough_args", expected, got) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + if (got == 0) error("no_args", expected) else error("not_enough_args", expected, got) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughMedia.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughMedia.kt index 07d686b56e..fec5d9f35f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughMedia.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughMedia.kt @@ -8,14 +8,15 @@ import at.petrak.hexcasting.api.utils.asTranslatedComponent import net.minecraft.world.item.DyeColor class MishapNotEnoughMedia(private val cost: Long) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.RED) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.RED) - override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.ERRORED + override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.ERRORED - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - env.extractMedia(cost, false) - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + env.extractMedia(cost, false) + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = "hexcasting.message.cant_overcast".asTranslatedComponent -} \ No newline at end of file + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + "hexcasting.message.cant_overcast".asTranslatedComponent +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt index e6ea0326ed..e7da7b3952 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt @@ -3,55 +3,53 @@ package at.petrak.hexcasting.api.casting.mishaps import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.EntityIota import at.petrak.hexcasting.api.casting.iota.Iota -import at.petrak.hexcasting.api.casting.iota.ListIota import at.petrak.hexcasting.api.pigment.FrozenPigment import net.minecraft.world.entity.player.Player import net.minecraft.world.item.DyeColor -/** - * Also throwable for your *own* name, for cases like Chronicler's Gambit - */ +/** Also throwable for your *own* name, for cases like Chronicler's Gambit */ class MishapOthersName(val confidant: Player) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.BLACK) - - override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - val seconds = if (this.confidant == ctx.castingEntity) 5 else 60 - ctx.mishapEnvironment.blind(seconds * 20) - } - - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - if (this.confidant == ctx.castingEntity) - error("others_name.self") - else - error("others_name", confidant.name) - - companion object { - /** - * Return any true names found in this iota. - * - * If `caster` is non-null, it will ignore that when checking. - */ - @JvmStatic - fun getTrueNameFromDatum(datum: Iota, caster: Player?): Player? { - val poolToSearch = ArrayDeque<Iota>() - poolToSearch.addLast(datum) - - while (poolToSearch.isNotEmpty()) { - val datumToCheck = poolToSearch.removeFirst() - if (datumToCheck is EntityIota && datumToCheck.entity is Player && datumToCheck.entity != caster) - return datumToCheck.entity as Player - val datumSubIotas = datumToCheck.subIotas() - if (datumSubIotas != null) - poolToSearch.addAll(datumSubIotas) - } - - return null - } - - @JvmStatic - fun getTrueNameFromArgs(datums: List<Iota>, caster: Player?): Player? { - return datums.firstNotNullOfOrNull { getTrueNameFromDatum(it, caster) } - } - } + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.BLACK) + + override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + val seconds = if (this.confidant == ctx.castingEntity) 5 else 60 + ctx.mishapEnvironment.blind(seconds * 20) + } + + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + if (this.confidant == ctx.castingEntity) error("others_name.self") + else error("others_name", confidant.name) + + companion object { + /** + * Return any true names found in this iota. + * + * If `caster` is non-null, it will ignore that when checking. + */ + @JvmStatic + fun getTrueNameFromDatum(datum: Iota, caster: Player?): Player? { + val poolToSearch = ArrayDeque<Iota>() + poolToSearch.addLast(datum) + + while (poolToSearch.isNotEmpty()) { + val datumToCheck = poolToSearch.removeFirst() + if ( + datumToCheck is EntityIota && + datumToCheck.entity is Player && + datumToCheck.entity != caster + ) + return datumToCheck.entity as Player + val datumSubIotas = datumToCheck.subIotas() + if (datumSubIotas != null) poolToSearch.addAll(datumSubIotas) + } + + return null + } + + @JvmStatic + fun getTrueNameFromArgs(datums: List<Iota>, caster: Player?): Player? { + return datums.firstNotNullOfOrNull { getTrueNameFromDatum(it, caster) } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt index 571e39bcd9..5de4ec3b7c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt @@ -5,20 +5,18 @@ import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType import at.petrak.hexcasting.api.casting.iota.GarbageIota import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment -import at.petrak.hexcasting.common.lib.HexDamageTypes import net.minecraft.world.item.DyeColor class MishapStackSize() : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.BLACK) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.BLACK) - override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.ERRORED + override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.ERRORED - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - stack.clear() - stack.add(GarbageIota()) - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + stack.clear() + stack.add(GarbageIota()) + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("stack_size") + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = error("stack_size") } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapTooManyCloseParens.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapTooManyCloseParens.kt index dfa159bda7..da0f82a1d2 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapTooManyCloseParens.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapTooManyCloseParens.kt @@ -7,15 +7,14 @@ import at.petrak.hexcasting.api.pigment.FrozenPigment import net.minecraft.world.item.DyeColor class MishapTooManyCloseParens : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.ORANGE) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.ORANGE) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - // TODO this is a kinda shitty mishap - if (errorCtx.pattern != null) - stack.add(PatternIota(errorCtx.pattern)) - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + // TODO this is a kinda shitty mishap + if (errorCtx.pattern != null) stack.add(PatternIota(errorCtx.pattern)) + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("too_many_close_parens") + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error("too_many_close_parens") } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnenlightened.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnenlightened.kt index e0dde2150b..81219512c0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnenlightened.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnenlightened.kt @@ -12,24 +12,35 @@ import net.minecraft.sounds.SoundSource import net.minecraft.world.item.DyeColor class MishapUnenlightened : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.RED) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.RED) - override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.INVALID + override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.INVALID - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - env.mishapEnvironment.dropHeldItems() - env.castingEntity?.sendSystemMessage("hexcasting.message.cant_great_spell".asTranslatedComponent) + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + env.mishapEnvironment.dropHeldItems() + env.castingEntity?.sendSystemMessage( + "hexcasting.message.cant_great_spell".asTranslatedComponent + ) - // add some non-zero level of juice I guess - val pos = env.mishapSprayPos() - env.world.playSound(null, pos.x, pos.y, pos.z, SoundEvents.GLASS_BREAK, SoundSource.PLAYERS, 0.5f, 0.7f) + // add some non-zero level of juice I guess + val pos = env.mishapSprayPos() + env.world.playSound( + null, + pos.x, + pos.y, + pos.z, + SoundEvents.GLASS_BREAK, + SoundSource.PLAYERS, + 0.5f, + 0.7f + ) - val castingPlayer = env.castingEntity as? ServerPlayer - if (castingPlayer != null) { - HexAdvancementTriggers.FAIL_GREAT_SPELL_TRIGGER.trigger(castingPlayer) - } - } + val castingPlayer = env.castingEntity as? ServerPlayer + if (castingPlayer != null) { + HexAdvancementTriggers.FAIL_GREAT_SPELL_TRIGGER.trigger(castingPlayer) + } + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = null + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = null } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnescapedValue.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnescapedValue.kt index 6a30a8221e..8c9ae24f09 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnescapedValue.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnescapedValue.kt @@ -5,31 +5,27 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment import net.minecraft.world.item.DyeColor -/** - * The value was a naked iota without being Considered or Retrospected. - */ -class MishapUnescapedValue( - val perpetrator: Iota -) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.GRAY) +/** The value was a naked iota without being Considered or Retrospected. */ +class MishapUnescapedValue(val perpetrator: Iota) : Mishap() { + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.GRAY) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - // TODO - /* - val idx = stack.indexOfLast { it.getType() == DatumType.LIST } - if (idx != -1) { - val list = stack[idx].payload as SpellList - val idxOfIota = list.indexOfFirst { it == perpetrator } - if (idxOfIota != -1) { - stack[idx] = SpellDatum.make(list.modifyAt(idxOfIota) { - SpellList.LPair(SpellDatum.make(Widget.GARBAGE), it.cdr) - }) - } - } - */ - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + // TODO + /* + val idx = stack.indexOfLast { it.getType() == DatumType.LIST } + if (idx != -1) { + val list = stack[idx].payload as SpellList + val idxOfIota = list.indexOfFirst { it == perpetrator } + if (idxOfIota != -1) { + stack[idx] = SpellDatum.make(list.modifyAt(idxOfIota) { + SpellList.LPair(SpellDatum.make(Widget.GARBAGE), it.cdr) + }) + } + } + */ + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("unescaped", perpetrator.display()) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error("unescaped", perpetrator.display()) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixEmptyStack.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixEmptyStack.kt index ae27403f23..1f92fe0a08 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixEmptyStack.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixEmptyStack.kt @@ -10,15 +10,15 @@ import net.minecraft.world.item.DyeColor // what a mouthful class MishapBoolDirectrixEmptyStack( - val pos: BlockPos, + val pos: BlockPos, ) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.GRAY) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.GRAY) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - env.world.destroyBlock(this.pos, true) - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + env.world.destroyBlock(this.pos, true) + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = - error("circle.bool_directrix.empty_stack", pos.toShortString()) -} \ No newline at end of file + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = + error("circle.bool_directrix.empty_stack", pos.toShortString()) +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixNotBool.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixNotBool.kt index 7c3d7b1fb5..f17ccc842d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixNotBool.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixNotBool.kt @@ -10,16 +10,16 @@ import net.minecraft.world.item.DyeColor // what a mouthful class MishapBoolDirectrixNotBool( - val perpetrator: Iota, - val pos: BlockPos, + val perpetrator: Iota, + val pos: BlockPos, ) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.GRAY) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.GRAY) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - env.world.destroyBlock(this.pos, true) - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + env.world.destroyBlock(this.pos, true) + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = - error("circle.bool_directrix_no_bool", pos.toShortString(), perpetrator.display()) -} \ No newline at end of file + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = + error("circle.bool_directrix_no_bool", pos.toShortString(), perpetrator.display()) +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapNoSpellCircle.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapNoSpellCircle.kt index 9eeae0f2b5..ce68126276 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapNoSpellCircle.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapNoSpellCircle.kt @@ -11,32 +11,33 @@ import net.minecraft.world.item.ItemStack import net.minecraft.world.item.enchantment.EnchantmentHelper class MishapNoSpellCircle : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.LIGHT_BLUE) + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.LIGHT_BLUE) - // FIXME: make me work with any entity and not just players - private inline fun dropAll(player: Player, stacks: MutableList<ItemStack>, filter: (ItemStack) -> Boolean = { true }) { - for (index in stacks.indices) { - val item = stacks[index] - if (!item.isEmpty && filter(item)) { - player.drop(item, true, false) - stacks[index] = ItemStack.EMPTY - } - } - } + // FIXME: make me work with any entity and not just players + private inline fun dropAll( + player: Player, + stacks: MutableList<ItemStack>, + filter: (ItemStack) -> Boolean = { true } + ) { + for (index in stacks.indices) { + val item = stacks[index] + if (!item.isEmpty && filter(item)) { + player.drop(item, true, false) + stacks[index] = ItemStack.EMPTY + } + } + } - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { - val caster = env.castingEntity as? ServerPlayer - if (caster != null) { - // FIXME: handle null caster case - dropAll(caster, caster.inventory.items) - dropAll(caster, caster.inventory.offhand) - dropAll(caster, caster.inventory.armor) { - !EnchantmentHelper.hasBindingCurse(it) - } - } - } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) { + val caster = env.castingEntity as? ServerPlayer + if (caster != null) { + // FIXME: handle null caster case + dropAll(caster, caster.inventory.items) + dropAll(caster, caster.inventory.offhand) + dropAll(caster, caster.inventory.armor) { !EnchantmentHelper.hasBindingCurse(it) } + } + } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error("no_spell_circle") + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = error("no_spell_circle") } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/client/ClientCastingStack.kt b/Common/src/main/java/at/petrak/hexcasting/api/client/ClientCastingStack.kt index 249adc092b..5b880927bf 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/client/ClientCastingStack.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/client/ClientCastingStack.kt @@ -3,59 +3,62 @@ package at.petrak.hexcasting.api.client import at.petrak.hexcasting.api.casting.math.HexPattern import kotlin.math.min - class ClientCastingStack { - private var patterns = ArrayList<HexPatternRenderHolder>() - private var toRemove = mutableSetOf<HexPatternRenderHolder>() - - private var toAdd = ArrayList<HexPatternRenderHolder>() - - fun addPattern(pattern: HexPattern?, lifetime: Int) { - if (pattern == null) return - if (patterns.stream().anyMatch { patternRenderHolder -> patternRenderHolder.pattern.hashCode() == pattern.hashCode() }) { - return - } - if (patterns.size > 100) { - patterns.removeAt(0) - } - patterns.add(HexPatternRenderHolder(pattern, lifetime)) - } - - fun slowClear() { - patterns.forEach { it.lifetime = min(it.lifetime, 140) } - } - - fun getPatterns(): List<HexPatternRenderHolder> { - return patterns - } - - fun getPattern(index: Int): HexPattern? = patterns.getOrNull(index)?.pattern - - fun getPatternHolder(index: Int): HexPatternRenderHolder? = patterns.getOrNull(index) - - fun size(): Int { - return patterns.size - } - - fun tick() { - // tick without getting a cme - toAdd.forEach { pattern -> - if (patterns.size > 100) { - patterns.removeAt(0) - } - patterns.add(pattern) - } - - toAdd.clear() - - patterns.forEach { pattern -> - pattern.tick() - if (pattern.lifetime <= 0) { - toRemove.add(pattern) - } - } - - patterns.removeAll(toRemove) - toRemove.clear() - } -} \ No newline at end of file + private var patterns = ArrayList<HexPatternRenderHolder>() + private var toRemove = mutableSetOf<HexPatternRenderHolder>() + + private var toAdd = ArrayList<HexPatternRenderHolder>() + + fun addPattern(pattern: HexPattern?, lifetime: Int) { + if (pattern == null) return + if ( + patterns.stream().anyMatch { patternRenderHolder -> + patternRenderHolder.pattern.hashCode() == pattern.hashCode() + } + ) { + return + } + if (patterns.size > 100) { + patterns.removeAt(0) + } + patterns.add(HexPatternRenderHolder(pattern, lifetime)) + } + + fun slowClear() { + patterns.forEach { it.lifetime = min(it.lifetime, 140) } + } + + fun getPatterns(): List<HexPatternRenderHolder> { + return patterns + } + + fun getPattern(index: Int): HexPattern? = patterns.getOrNull(index)?.pattern + + fun getPatternHolder(index: Int): HexPatternRenderHolder? = patterns.getOrNull(index) + + fun size(): Int { + return patterns.size + } + + fun tick() { + // tick without getting a cme + toAdd.forEach { pattern -> + if (patterns.size > 100) { + patterns.removeAt(0) + } + patterns.add(pattern) + } + + toAdd.clear() + + patterns.forEach { pattern -> + pattern.tick() + if (pattern.lifetime <= 0) { + toRemove.add(pattern) + } + } + + patterns.removeAll(toRemove) + toRemove.clear() + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/client/ClientRenderHelper.kt b/Common/src/main/java/at/petrak/hexcasting/api/client/ClientRenderHelper.kt index 374e89c932..9602f19275 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/client/ClientRenderHelper.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/client/ClientRenderHelper.kt @@ -1,4 +1,5 @@ @file:JvmName("ClientRenderHelper") + package at.petrak.hexcasting.api.client import at.petrak.hexcasting.client.ClientTickCounter @@ -11,76 +12,101 @@ import at.petrak.hexcasting.xplat.IXplatAbstractions import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.vertex.PoseStack import com.mojang.math.Axis -import net.minecraft.client.renderer.GameRenderer -import net.minecraft.world.entity.player.Player -import net.minecraft.world.phys.Vec2 import kotlin.math.abs import kotlin.math.cos import kotlin.math.floor import kotlin.math.sin - +import net.minecraft.client.renderer.GameRenderer +import net.minecraft.world.entity.player.Player +import net.minecraft.world.phys.Vec2 fun renderCastingStack(ps: PoseStack, player: Player, pticks: Float) { - val stack = IClientXplatAbstractions.INSTANCE.getClientCastingStack(player) + val stack = IClientXplatAbstractions.INSTANCE.getClientCastingStack(player) - for (k in 0 until stack.getPatterns().size) { - val patternRenderHolder = stack.getPatternHolder(k) ?: continue - val pattern = patternRenderHolder.pattern - val lifetime = patternRenderHolder.lifetime - val lifetimeOffset = if (lifetime <= 5f) (5f - lifetime) / 5f else 0f + for (k in 0 until stack.getPatterns().size) { + val patternRenderHolder = stack.getPatternHolder(k) ?: continue + val pattern = patternRenderHolder.pattern + val lifetime = patternRenderHolder.lifetime + val lifetimeOffset = if (lifetime <= 5f) (5f - lifetime) / 5f else 0f - ps.pushPose() - ps.mulPose(Axis.YP.rotationDegrees(((player.level().gameTime + pticks) * (sin(k * 12.543565f) * 3.4f) * (k / 12.43f) % 360 + (1 + k) * 45f))) - ps.translate(0.0, 1 + sin(k.toDouble()) * 0.75, 0.75 + cos((k / 8.0)) * 0.25 + cos((player.level().gameTime + pticks) / (7 + k / 4)) * 0.065) - ps.scale(1 / 24f * (1 - lifetimeOffset), 1 / 24f * (1 - lifetimeOffset), 1 / 24f * (1 - lifetimeOffset)) - ps.translate(0.0, floor((k / 8.0)), 0.0) - ps.translate(0.0, sin((player.level().gameTime + pticks) / (7.0 + k / 8.0)), 0.0) + ps.pushPose() + ps.mulPose( + Axis.YP.rotationDegrees( + ((player.level().gameTime + pticks) * (sin(k * 12.543565f) * 3.4f) * (k / 12.43f) % 360 + + (1 + k) * 45f) + ) + ) + ps.translate( + 0.0, + 1 + sin(k.toDouble()) * 0.75, + 0.75 + cos((k / 8.0)) * 0.25 + cos((player.level().gameTime + pticks) / (7 + k / 4)) * 0.065 + ) + ps.scale( + 1 / 24f * (1 - lifetimeOffset), + 1 / 24f * (1 - lifetimeOffset), + 1 / 24f * (1 - lifetimeOffset) + ) + ps.translate(0.0, floor((k / 8.0)), 0.0) + ps.translate(0.0, sin((player.level().gameTime + pticks) / (7.0 + k / 8.0)), 0.0) - val oldShader = RenderSystem.getShader() - RenderSystem.setShader { GameRenderer.getPositionColorShader() } - RenderSystem.enableDepthTest() - RenderSystem.disableCull() - val com1 = pattern.getCenter(1f) - val lines1 = pattern.toLines(1f, Vec2.ZERO) - var maxDx = -1f - var maxDy = -1f - for (line in lines1) { - val dx = abs(line.x - com1.x) - if (dx > maxDx) { - maxDx = dx - } - val dy = abs(line.y - com1.y) - if (dy > maxDy) { - maxDy = dy - } - } - val scale = 3.8f.coerceAtMost((16 / 2.5f / maxDx).coerceAtMost(16 / 2.5f / maxDy)) - val com2 = pattern.getCenter(scale) - val lines2 = pattern.toLines(scale, com2.negated()).toMutableList() - for (i in lines2.indices) { - val line = lines2[i] - lines2[i] = Vec2(line.x, -line.y) - } - val variance = 0.65f - val speed = 0.1f - val stupidHash = player.hashCode().toDouble() - val zappy: List<Vec2> = makeZappy(lines2, findDupIndices(pattern.positions()), - 5, variance, speed, 0.2f, 0f, - 1f, stupidHash) - val outer: Int = IXplatAbstractions.INSTANCE.getPigment(player).colorProvider.getColor( - ClientTickCounter.getTotal() / 2f, - patternRenderHolder.getColourPos(player.random)) - val rgbOnly = outer and 0x00FFFFFF - var newAlpha = outer ushr 24 - if (lifetime <= 60) { - newAlpha = floor((lifetime / 60f * 255).toDouble()).toInt() - } - val newARGB = newAlpha shl 24 or rgbOnly - val inner: Int = screenCol(newARGB) - drawLineSeq(ps.last().pose(), zappy, 0.35f, 0f, newARGB, newARGB) - drawLineSeq(ps.last().pose(), zappy, 0.14f, 0.01f, inner, inner) - ps.popPose() - RenderSystem.setShader { oldShader } - RenderSystem.enableCull() - } -} \ No newline at end of file + val oldShader = RenderSystem.getShader() + RenderSystem.setShader { GameRenderer.getPositionColorShader() } + RenderSystem.enableDepthTest() + RenderSystem.disableCull() + val com1 = pattern.getCenter(1f) + val lines1 = pattern.toLines(1f, Vec2.ZERO) + var maxDx = -1f + var maxDy = -1f + for (line in lines1) { + val dx = abs(line.x - com1.x) + if (dx > maxDx) { + maxDx = dx + } + val dy = abs(line.y - com1.y) + if (dy > maxDy) { + maxDy = dy + } + } + val scale = 3.8f.coerceAtMost((16 / 2.5f / maxDx).coerceAtMost(16 / 2.5f / maxDy)) + val com2 = pattern.getCenter(scale) + val lines2 = pattern.toLines(scale, com2.negated()).toMutableList() + for (i in lines2.indices) { + val line = lines2[i] + lines2[i] = Vec2(line.x, -line.y) + } + val variance = 0.65f + val speed = 0.1f + val stupidHash = player.hashCode().toDouble() + val zappy: List<Vec2> = + makeZappy( + lines2, + findDupIndices(pattern.positions()), + 5, + variance, + speed, + 0.2f, + 0f, + 1f, + stupidHash + ) + val outer: Int = + IXplatAbstractions.INSTANCE.getPigment(player) + .colorProvider + .getColor( + ClientTickCounter.getTotal() / 2f, + patternRenderHolder.getColourPos(player.random) + ) + val rgbOnly = outer and 0x00FFFFFF + var newAlpha = outer ushr 24 + if (lifetime <= 60) { + newAlpha = floor((lifetime / 60f * 255).toDouble()).toInt() + } + val newARGB = newAlpha shl 24 or rgbOnly + val inner: Int = screenCol(newARGB) + drawLineSeq(ps.last().pose(), zappy, 0.35f, 0f, newARGB, newARGB) + drawLineSeq(ps.last().pose(), zappy, 0.14f, 0.01f, inner, inner) + ps.popPose() + RenderSystem.setShader { oldShader } + RenderSystem.enableCull() + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/client/HexPatternRenderHolder.kt b/Common/src/main/java/at/petrak/hexcasting/api/client/HexPatternRenderHolder.kt index 3092f3727a..7ae515ea44 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/client/HexPatternRenderHolder.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/client/HexPatternRenderHolder.kt @@ -5,15 +5,19 @@ import net.minecraft.util.RandomSource import net.minecraft.world.phys.Vec3 data class HexPatternRenderHolder(val pattern: HexPattern, var lifetime: Int) { - private var colourPos: Vec3? = null + private var colourPos: Vec3? = null - fun getColourPos(random: RandomSource): Vec3 { - return colourPos ?: let { - Vec3(random.nextDouble(), random.nextDouble(), random.nextDouble()).normalize().scale(3.0).also { colourPos = it } - } - } + fun getColourPos(random: RandomSource): Vec3 { + return colourPos + ?: let { + Vec3(random.nextDouble(), random.nextDouble(), random.nextDouble()) + .normalize() + .scale(3.0) + .also { colourPos = it } + } + } - fun tick() { - lifetime -= 1 - } -} \ No newline at end of file + fun tick() { + lifetime -= 1 + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/client/ScryingLensOverlayRegistry.java b/Common/src/main/java/at/petrak/hexcasting/api/client/ScryingLensOverlayRegistry.java index da72b78b42..1153ea3a8b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/client/ScryingLensOverlayRegistry.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/client/ScryingLensOverlayRegistry.java @@ -2,9 +2,12 @@ import com.google.common.collect.Lists; import com.mojang.datafixers.util.Pair; +import java.util.List; +import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; @@ -15,93 +18,86 @@ import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.NotNull; -import java.util.List; -import java.util.Vector; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - /** * Use this to make things display when the player looks at things with a Scrying Lens. - * <p> - * Client-side only. + * + * <p>Client-side only. */ public final class ScryingLensOverlayRegistry { - private static final ConcurrentMap<ResourceLocation, OverlayBuilder> ID_LOOKUP = new ConcurrentHashMap<>(); - // vectors are thread-safe! - private static final List<Pair<OverlayPredicate, OverlayBuilder>> PREDICATE_LOOKUP = new Vector<>(); + private static final ConcurrentMap<ResourceLocation, OverlayBuilder> ID_LOOKUP = + new ConcurrentHashMap<>(); + // vectors are thread-safe! + private static final List<Pair<OverlayPredicate, OverlayBuilder>> PREDICATE_LOOKUP = + new Vector<>(); - /** - * Add the block to display things when the player is holding a lens and looking at it. - * - * @throws IllegalArgumentException if the block is already registered. - */ - public static void addDisplayer(Block block, OverlayBuilder displayer) { - addDisplayer(BuiltInRegistries.BLOCK.getKey(block), displayer); - } + /** + * Add the block to display things when the player is holding a lens and looking at it. + * + * @throws IllegalArgumentException if the block is already registered. + */ + public static void addDisplayer(Block block, OverlayBuilder displayer) { + addDisplayer(BuiltInRegistries.BLOCK.getKey(block), displayer); + } - /** - * Add the block to display things when the player is holding a lens and looking at it. - * - * @throws IllegalArgumentException if the block ID is already registered. - */ - public static void addDisplayer(ResourceLocation blockID, OverlayBuilder displayer) { - if (ID_LOOKUP.containsKey(blockID)) { - throw new IllegalArgumentException("Already have a displayer for " + blockID); - } - ID_LOOKUP.put(blockID, displayer); - } + /** + * Add the block to display things when the player is holding a lens and looking at it. + * + * @throws IllegalArgumentException if the block ID is already registered. + */ + public static void addDisplayer(ResourceLocation blockID, OverlayBuilder displayer) { + if (ID_LOOKUP.containsKey(blockID)) { + throw new IllegalArgumentException("Already have a displayer for " + blockID); + } + ID_LOOKUP.put(blockID, displayer); + } - /** - * Display things when the player is holding a lens and looking at some block via a predicate. - * <p> - * These have a lower priority than the standard ID-based displays, so if an ID and predicate both match, - * this won't be displayed. - */ - public static void addPredicateDisplayer(OverlayPredicate predicate, OverlayBuilder displayer) { - PREDICATE_LOOKUP.add(new Pair<>(predicate, displayer)); - } + /** + * Display things when the player is holding a lens and looking at some block via a predicate. + * + * <p>These have a lower priority than the standard ID-based displays, so if an ID and predicate + * both match, this won't be displayed. + */ + public static void addPredicateDisplayer(OverlayPredicate predicate, OverlayBuilder displayer) { + PREDICATE_LOOKUP.add(new Pair<>(predicate, displayer)); + } - /** - * Internal use only. - */ - public static @NotNull List<Pair<ItemStack, Component>> getLines(BlockState state, BlockPos pos, - Player observer, Level world, - Direction hitFace) { - List<Pair<ItemStack, Component>> lines = Lists.newArrayList(); - var idLookedup = ID_LOOKUP.get(BuiltInRegistries.BLOCK.getKey(state.getBlock())); - if (idLookedup != null) { - idLookedup.addLines(lines, state, pos, observer, world, hitFace); - } + /** Internal use only. */ + public static @NotNull List<Pair<ItemStack, Component>> getLines( + BlockState state, BlockPos pos, Player observer, Level world, Direction hitFace) { + List<Pair<ItemStack, Component>> lines = Lists.newArrayList(); + var idLookedup = ID_LOOKUP.get(BuiltInRegistries.BLOCK.getKey(state.getBlock())); + if (idLookedup != null) { + idLookedup.addLines(lines, state, pos, observer, world, hitFace); + } - for (var pair : PREDICATE_LOOKUP) { - if (pair.getFirst().test(state, pos, observer, world, hitFace)) { - pair.getSecond().addLines(lines, state, pos, observer, world, hitFace); - } - } + for (var pair : PREDICATE_LOOKUP) { + if (pair.getFirst().test(state, pos, observer, world, hitFace)) { + pair.getSecond().addLines(lines, state, pos, observer, world, hitFace); + } + } - return lines; - } + return lines; + } - /** - * Return the lines displayed by the cursor: an item and some text. - * <p> - * The ItemStack can be empty; if it is, the text isn't shifted over for it. - */ - @FunctionalInterface - public interface OverlayBuilder { - void addLines(List<Pair<ItemStack, Component>> lines, - BlockState state, BlockPos pos, Player observer, - Level world, - Direction hitFace); - } + /** + * Return the lines displayed by the cursor: an item and some text. + * + * <p>The ItemStack can be empty; if it is, the text isn't shifted over for it. + */ + @FunctionalInterface + public interface OverlayBuilder { + void addLines( + List<Pair<ItemStack, Component>> lines, + BlockState state, + BlockPos pos, + Player observer, + Level world, + Direction hitFace); + } - /** - * Predicate for matching on a block state. - */ - @FunctionalInterface - public interface OverlayPredicate { - boolean test(BlockState state, BlockPos pos, Player observer, - Level world, - Direction hitFace); - } + /** Predicate for matching on a block state. */ + @FunctionalInterface + public interface OverlayPredicate { + boolean test(BlockState state, BlockPos pos, Player observer, Level world, Direction hitFace); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/item/HexHolderItem.java b/Common/src/main/java/at/petrak/hexcasting/api/item/HexHolderItem.java index a27ef900f1..9f1d334cc8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/item/HexHolderItem.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/item/HexHolderItem.java @@ -2,32 +2,30 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.pigment.FrozenPigment; +import java.util.List; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; -import java.util.List; - /** * Items which can cast a packaged Hex can implement this interface. - * <p> - * On both the Forge and Fabric sides, the registry will be scanned for all items which implement this interface, - * and the appropriate cap/CC will be attached. + * + * <p>On both the Forge and Fabric sides, the registry will be scanned for all items which implement + * this interface, and the appropriate cap/CC will be attached. */ @ApiStatus.OverrideOnly public interface HexHolderItem extends MediaHolderItem { - boolean canDrawMediaFromInventory(ItemStack stack); + boolean canDrawMediaFromInventory(ItemStack stack); - boolean hasHex(ItemStack stack); + boolean hasHex(ItemStack stack); - @Nullable - List<Iota> getHex(ItemStack stack, ServerLevel level); + @Nullable List<Iota> getHex(ItemStack stack, ServerLevel level); - void writeHex(ItemStack stack, List<Iota> program, @Nullable FrozenPigment pigment, long media); + void writeHex(ItemStack stack, List<Iota> program, @Nullable FrozenPigment pigment, long media); - void clearHex(ItemStack stack); + void clearHex(ItemStack stack); - @Nullable FrozenPigment getPigment(ItemStack stack); + @Nullable FrozenPigment getPigment(ItemStack stack); } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java b/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java index c312383129..4e11f81f98 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java @@ -6,6 +6,7 @@ import at.petrak.hexcasting.api.utils.NBTHelper; import at.petrak.hexcasting.client.ClientTickCounter; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import java.util.List; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; @@ -17,102 +18,96 @@ import net.minecraft.world.item.TooltipFlag; import org.jetbrains.annotations.Nullable; -import java.util.List; - /** * Items that store an iota to their tag can implement this interface. - * <p> - * On both the Forge and Fabric sides, the registry will be scanned for all items which implement this interface, - * and the appropriate cap/CC will be attached. + * + * <p>On both the Forge and Fabric sides, the registry will be scanned for all items which implement + * this interface, and the appropriate cap/CC will be attached. */ public interface IotaHolderItem { - /** - * If this key is set on the item, we ignore the rest of the item and render this as if it were of the - * {@link at.petrak.hexcasting.api.casting.iota.IotaType IotaType} given by the resource location. - * <p> - * This is not useful to the player at all. - */ - String TAG_OVERRIDE_VISUALLY = "VisualOverride"; - - @Nullable - CompoundTag readIotaTag(ItemStack stack); - - @Nullable - default Iota readIota(ItemStack stack, ServerLevel world) { - if (!(stack.getItem() instanceof IotaHolderItem dh)) { - // this should be checked via mishap beforehand - throw new IllegalArgumentException("stack's item must be an IotaHolderItem but was " + stack.getItem()); - } - - var tag = dh.readIotaTag(stack); - if (tag != null) { - return IotaType.deserialize(tag, world); - } else { - return null; - } - } - - /** - * What is this considered to contain when nothing can be read? - */ - @Nullable - default Iota emptyIota(ItemStack stack) { - return null; - } - - default int getColor(ItemStack stack) { - if (NBTHelper.hasString(stack, TAG_OVERRIDE_VISUALLY)) { - var override = NBTHelper.getString(stack, TAG_OVERRIDE_VISUALLY); - - if (override != null && ResourceLocation.isValidResourceLocation(override)) { - var key = new ResourceLocation(override); - if (HexIotaTypes.REGISTRY.containsKey(key)) { - var iotaType = HexIotaTypes.REGISTRY.get(key); - if (iotaType != null) { - return iotaType.color(); - } - } - } - - return 0xFF000000 | Mth.hsvToRgb(ClientTickCounter.getTotal() * 2 % 360 / 360F, 0.75F, 1F); - } - - var tag = this.readIotaTag(stack); - if (tag == null) { - return HexUtils.ERROR_COLOR; - } - - return IotaType.getColor(tag); - } - - /** - * @return whether it is possible to write to this IotaHolder - */ - boolean writeable(ItemStack stack); - - /** - * Write {@code null} to indicate erasing - */ - boolean canWrite(ItemStack stack, @Nullable Iota iota); - - /** - * Write {@code null} to indicate erasing - */ - void writeDatum(ItemStack stack, @Nullable Iota iota); - - static void appendHoverText(IotaHolderItem self, ItemStack stack, List<Component> components, - TooltipFlag flag) { - var datumTag = self.readIotaTag(stack); - if (datumTag != null) { - var cmp = IotaType.getDisplay(datumTag); - components.add(Component.translatable("hexcasting.spelldata.onitem", cmp)); - - if (flag.isAdvanced()) { - components.add(Component.literal("").append(NbtUtils.toPrettyComponent(datumTag))); - } - } else if (NBTHelper.hasString(stack, IotaHolderItem.TAG_OVERRIDE_VISUALLY)) { - components.add(Component.translatable("hexcasting.spelldata.onitem", - Component.translatable("hexcasting.spelldata.anything").withStyle(ChatFormatting.LIGHT_PURPLE))); - } - } + /** + * If this key is set on the item, we ignore the rest of the item and render this as if it were of + * the {@link at.petrak.hexcasting.api.casting.iota.IotaType IotaType} given by the resource + * location. + * + * <p>This is not useful to the player at all. + */ + String TAG_OVERRIDE_VISUALLY = "VisualOverride"; + + @Nullable CompoundTag readIotaTag(ItemStack stack); + + @Nullable default Iota readIota(ItemStack stack, ServerLevel world) { + if (!(stack.getItem() instanceof IotaHolderItem dh)) { + // this should be checked via mishap beforehand + throw new IllegalArgumentException( + "stack's item must be an IotaHolderItem but was " + stack.getItem()); + } + + var tag = dh.readIotaTag(stack); + if (tag != null) { + return IotaType.deserialize(tag, world); + } else { + return null; + } + } + + /** What is this considered to contain when nothing can be read? */ + @Nullable default Iota emptyIota(ItemStack stack) { + return null; + } + + default int getColor(ItemStack stack) { + if (NBTHelper.hasString(stack, TAG_OVERRIDE_VISUALLY)) { + var override = NBTHelper.getString(stack, TAG_OVERRIDE_VISUALLY); + + if (override != null && ResourceLocation.isValidResourceLocation(override)) { + var key = new ResourceLocation(override); + if (HexIotaTypes.REGISTRY.containsKey(key)) { + var iotaType = HexIotaTypes.REGISTRY.get(key); + if (iotaType != null) { + return iotaType.color(); + } + } + } + + return 0xFF000000 | Mth.hsvToRgb(ClientTickCounter.getTotal() * 2 % 360 / 360F, 0.75F, 1F); + } + + var tag = this.readIotaTag(stack); + if (tag == null) { + return HexUtils.ERROR_COLOR; + } + + return IotaType.getColor(tag); + } + + /** + * @return whether it is possible to write to this IotaHolder + */ + boolean writeable(ItemStack stack); + + /** Write {@code null} to indicate erasing */ + boolean canWrite(ItemStack stack, @Nullable Iota iota); + + /** Write {@code null} to indicate erasing */ + void writeDatum(ItemStack stack, @Nullable Iota iota); + + static void appendHoverText( + IotaHolderItem self, ItemStack stack, List<Component> components, TooltipFlag flag) { + var datumTag = self.readIotaTag(stack); + if (datumTag != null) { + var cmp = IotaType.getDisplay(datumTag); + components.add(Component.translatable("hexcasting.spelldata.onitem", cmp)); + + if (flag.isAdvanced()) { + components.add(Component.literal("").append(NbtUtils.toPrettyComponent(datumTag))); + } + } else if (NBTHelper.hasString(stack, IotaHolderItem.TAG_OVERRIDE_VISUALLY)) { + components.add( + Component.translatable( + "hexcasting.spelldata.onitem", + Component.translatable("hexcasting.spelldata.anything") + .withStyle(ChatFormatting.LIGHT_PURPLE))); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/item/MediaHolderItem.java b/Common/src/main/java/at/petrak/hexcasting/api/item/MediaHolderItem.java index a4aa3cfc0a..d11a5df891 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/item/MediaHolderItem.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/item/MediaHolderItem.java @@ -6,62 +6,62 @@ /** * Items which can store Media can implement this interface. - * <p> - * On both the Forge and Fabric sides, the registry will be scanned for all items which implement this interface, - * and the appropriate cap/CC will be attached. + * + * <p>On both the Forge and Fabric sides, the registry will be scanned for all items which implement + * this interface, and the appropriate cap/CC will be attached. */ @ApiStatus.OverrideOnly public interface MediaHolderItem { - long getMedia(ItemStack stack); + long getMedia(ItemStack stack); - long getMaxMedia(ItemStack stack); + long getMaxMedia(ItemStack stack); - void setMedia(ItemStack stack, long media); + void setMedia(ItemStack stack, long media); - boolean canProvideMedia(ItemStack stack); + boolean canProvideMedia(ItemStack stack); - boolean canRecharge(ItemStack stack); + boolean canRecharge(ItemStack stack); - default float getMediaFullness(ItemStack stack) { - long max = getMaxMedia(stack); - if (max == 0) { - return 0; - } - return (float) getMedia(stack) / (float) max; - } + default float getMediaFullness(ItemStack stack) { + long max = getMaxMedia(stack); + if (max == 0) { + return 0; + } + return (float) getMedia(stack) / (float) max; + } - default long withdrawMedia(ItemStack stack, long cost, boolean simulate) { - var mediaHere = getMedia(stack); - if (cost < 0) { - cost = mediaHere; - } - if (!simulate) { - var mediaLeft = mediaHere - cost; - setMedia(stack, mediaLeft); - } - return Math.min(cost, mediaHere); - } + default long withdrawMedia(ItemStack stack, long cost, boolean simulate) { + var mediaHere = getMedia(stack); + if (cost < 0) { + cost = mediaHere; + } + if (!simulate) { + var mediaLeft = mediaHere - cost; + setMedia(stack, mediaLeft); + } + return Math.min(cost, mediaHere); + } - default long insertMedia(ItemStack stack, long amount, boolean simulate) { - var mediaHere = getMedia(stack); - long emptySpace = getMaxMedia(stack) - mediaHere; - if (emptySpace <= 0) { - return 0; - } - if (amount < 0) { - amount = emptySpace; - } + default long insertMedia(ItemStack stack, long amount, boolean simulate) { + var mediaHere = getMedia(stack); + long emptySpace = getMaxMedia(stack) - mediaHere; + if (emptySpace <= 0) { + return 0; + } + if (amount < 0) { + amount = emptySpace; + } - long inserting = Math.min(amount, emptySpace); + long inserting = Math.min(amount, emptySpace); - if (!simulate) { - var newMedia = mediaHere + inserting; - setMedia(stack, newMedia); - } - return inserting; - } + if (!simulate) { + var newMedia = mediaHere + inserting; + setMedia(stack, newMedia); + } + return inserting; + } - default int getConsumptionPriority(ItemStack stack) { - return ADMediaHolder.BATTERY_PRIORITY; - } + default int getConsumptionPriority(ItemStack stack) { + return ADMediaHolder.BATTERY_PRIORITY; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/item/PigmentItem.java b/Common/src/main/java/at/petrak/hexcasting/api/item/PigmentItem.java index 06829c4b16..b7c38d23ba 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/item/PigmentItem.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/item/PigmentItem.java @@ -1,18 +1,17 @@ package at.petrak.hexcasting.api.item; import at.petrak.hexcasting.api.pigment.ColorProvider; +import java.util.UUID; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.ApiStatus; -import java.util.UUID; - /** * Items which can be used as a colorizer can implement this interface. - * <p> - * On both the Forge and Fabric sides, the registry will be scanned for all items which implement this interface, - * and the appropriate cap/CC will be attached. + * + * <p>On both the Forge and Fabric sides, the registry will be scanned for all items which implement + * this interface, and the appropriate cap/CC will be attached. */ @ApiStatus.OverrideOnly public interface PigmentItem { - ColorProvider provideColor(ItemStack stack, UUID owner); + ColorProvider provideColor(ItemStack stack, UUID owner); } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/item/VariantItem.java b/Common/src/main/java/at/petrak/hexcasting/api/item/VariantItem.java index 6bdca2d2d7..d091ac3bc5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/item/VariantItem.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/item/VariantItem.java @@ -4,29 +4,28 @@ import net.minecraft.world.item.ItemStack; /** - * Items that have multiple different otherwise identical visual variants can implement this interface. - * <p> - * On both the Forge and Fabric sides, the registry will be scanned for all items which implement this interface, - * and the appropriate cap/CC will be attached. + * Items that have multiple different otherwise identical visual variants can implement this + * interface. + * + * <p>On both the Forge and Fabric sides, the registry will be scanned for all items which implement + * this interface, and the appropriate cap/CC will be attached. */ public interface VariantItem { - String TAG_VARIANT = "variant"; + String TAG_VARIANT = "variant"; - int numVariants(); + int numVariants(); - default int getVariant(ItemStack stack) { - return NBTHelper.getInt(stack, TAG_VARIANT, 0); - } + default int getVariant(ItemStack stack) { + return NBTHelper.getInt(stack, TAG_VARIANT, 0); + } - default void setVariant(ItemStack stack, int variant) { - NBTHelper.putInt(stack, TAG_VARIANT, clampVariant(variant)); - } + default void setVariant(ItemStack stack, int variant) { + NBTHelper.putInt(stack, TAG_VARIANT, clampVariant(variant)); + } - default int clampVariant(int variant) { - if (variant < 0) - return 0; - if (variant >= numVariants()) - return numVariants() - 1; - return variant; - } + default int clampVariant(int variant) { + if (variant < 0) return 0; + if (variant >= numVariants()) return numVariants() - 1; + return variant; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/misc/DiscoveryHandlers.java b/Common/src/main/java/at/petrak/hexcasting/api/misc/DiscoveryHandlers.java index d94f526066..8e502f4e65 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/misc/DiscoveryHandlers.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/misc/DiscoveryHandlers.java @@ -1,26 +1,26 @@ package at.petrak.hexcasting.api.misc; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; - import java.util.ArrayList; import java.util.List; import java.util.function.BiFunction; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; public class DiscoveryHandlers { - private static final List<BiFunction<Player, String, ItemStack>> DEBUG_DISCOVERER = new ArrayList<>(); + private static final List<BiFunction<Player, String, ItemStack>> DEBUG_DISCOVERER = + new ArrayList<>(); - public static ItemStack findDebugItem(Player player, String type) { - for (var discoverer : DEBUG_DISCOVERER) { - var stack = discoverer.apply(player, type); - if (!stack.isEmpty()) { - return stack; - } - } - return ItemStack.EMPTY; - } + public static ItemStack findDebugItem(Player player, String type) { + for (var discoverer : DEBUG_DISCOVERER) { + var stack = discoverer.apply(player, type); + if (!stack.isEmpty()) { + return stack; + } + } + return ItemStack.EMPTY; + } - public static void addDebugItemDiscoverer(BiFunction<Player, String, ItemStack> discoverer) { - DEBUG_DISCOVERER.add(discoverer); - } + public static void addDebugItemDiscoverer(BiFunction<Player, String, ItemStack> discoverer) { + DEBUG_DISCOVERER.add(discoverer); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/misc/MediaConstants.java b/Common/src/main/java/at/petrak/hexcasting/api/misc/MediaConstants.java index f09571070e..9d8586f1c7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/misc/MediaConstants.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/misc/MediaConstants.java @@ -1,10 +1,10 @@ package at.petrak.hexcasting.api.misc; public final class MediaConstants { - public static final long DUST_UNIT = 10000; - public static final long SHARD_UNIT = 5 * DUST_UNIT; - public static final long CRYSTAL_UNIT = 10 * DUST_UNIT; + public static final long DUST_UNIT = 10000; + public static final long SHARD_UNIT = 5 * DUST_UNIT; + public static final long CRYSTAL_UNIT = 10 * DUST_UNIT; - public static final long QUENCHED_SHARD_UNIT = 3 * CRYSTAL_UNIT; - public static final long QUENCHED_BLOCK_UNIT = 4 * QUENCHED_SHARD_UNIT; + public static final long QUENCHED_SHARD_UNIT = 3 * CRYSTAL_UNIT; + public static final long QUENCHED_BLOCK_UNIT = 4 * QUENCHED_SHARD_UNIT; } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/misc/Result.java b/Common/src/main/java/at/petrak/hexcasting/api/misc/Result.java index 3dfcc73c23..e4bc06e599 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/misc/Result.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/misc/Result.java @@ -1,84 +1,80 @@ package at.petrak.hexcasting.api.misc; import com.mojang.datafixers.util.Unit; - import java.util.function.Consumer; import java.util.function.Function; -/** - * I'm sick and tired of not having a result class god dammit - */ +/** I'm sick and tired of not having a result class god dammit */ public abstract sealed class Result<T, E> { - public static final class Ok<T, E> extends Result<T, E> { - public final T ok; + public static final class Ok<T, E> extends Result<T, E> { + public final T ok; - public Ok(T ok) { - this.ok = ok; - } - } + public Ok(T ok) { + this.ok = ok; + } + } - public static final class Err<T, E> extends Result<T, E> { - public final E err; + public static final class Err<T, E> extends Result<T, E> { + public final E err; - public Err(E err) { - this.err = err; - } - } + public Err(E err) { + this.err = err; + } + } - public boolean isOk() { - return this instanceof Ok; - } + public boolean isOk() { + return this instanceof Ok; + } - public boolean isErr() { - return this instanceof Err; - } + public boolean isErr() { + return this instanceof Err; + } - public T unwrap() { - if (this instanceof Ok<T, E> ok) { - return ok.ok; - } else { - throw new IllegalStateException("tried to unwrap an Err"); - } - } + public T unwrap() { + if (this instanceof Ok<T, E> ok) { + return ok.ok; + } else { + throw new IllegalStateException("tried to unwrap an Err"); + } + } - public E unwrapErr() { - if (this instanceof Err<T, E> err) { - return err.err; - } else { - throw new IllegalStateException("tried to unwrapErr an Ok"); - } - } + public E unwrapErr() { + if (this instanceof Err<T, E> err) { + return err.err; + } else { + throw new IllegalStateException("tried to unwrapErr an Ok"); + } + } - public <T2, E2> Result<T2, E2> match(Function<T, T2> okBranch, Function<E, E2> errBranch) { - if (this instanceof Ok<T, E> ok) { - return new Result.Ok<>(okBranch.apply(ok.ok)); - } else if (this instanceof Err<T, E> err) { - return new Result.Err<>(errBranch.apply(err.err)); - } else { - throw new IllegalStateException(); - } - } + public <T2, E2> Result<T2, E2> match(Function<T, T2> okBranch, Function<E, E2> errBranch) { + if (this instanceof Ok<T, E> ok) { + return new Result.Ok<>(okBranch.apply(ok.ok)); + } else if (this instanceof Err<T, E> err) { + return new Result.Err<>(errBranch.apply(err.err)); + } else { + throw new IllegalStateException(); + } + } - public void matchVoid(Consumer<T> okBranch, Consumer<E> errBranch) { - this.match( - ok -> { - okBranch.accept(ok); - return Unit.INSTANCE; - }, - err -> { - errBranch.accept(err); - return Unit.INSTANCE; - } - ); - } + public void matchVoid(Consumer<T> okBranch, Consumer<E> errBranch) { + this.match( + ok -> { + okBranch.accept(ok); + return Unit.INSTANCE; + }, + err -> { + errBranch.accept(err); + return Unit.INSTANCE; + }); + } - public <U> U collapse(Function<T, U> okBranch, Function<E, U> errBranch) { - if (this instanceof Ok<T, E> ok) { - return okBranch.apply(ok.ok); - } else if (this instanceof Err<T, E> err) { - return errBranch.apply(err.err); - } else { - throw new IllegalStateException(); - } - } + public <U> U collapse(Function<T, U> okBranch, Function<E, U> errBranch) { + if (this instanceof Ok<T, E> ok) { + return okBranch.apply(ok.ok); + } else if (this instanceof Err<T, E> err) { + return errBranch.apply(err.err); + } else { + throw new IllegalStateException(); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/misc/TriPredicate.java b/Common/src/main/java/at/petrak/hexcasting/api/misc/TriPredicate.java index 04f70220ee..4da3ae414e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/misc/TriPredicate.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/misc/TriPredicate.java @@ -1,9 +1,7 @@ package at.petrak.hexcasting.api.misc; -/** - * Society if java actually had first-class function support - */ +/** Society if java actually had first-class function support */ @FunctionalInterface public interface TriPredicate<A, B, C> { - boolean test(A a, B b, C c); + boolean test(A a, B b, C c); } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexApiMessages.java b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexApiMessages.java index 16dbbb6d0f..c6bbcd1364 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexApiMessages.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexApiMessages.java @@ -14,39 +14,39 @@ @ApiStatus.Internal public final class HexApiMessages { - private static SimpleChannel channel; - private static Function<Sentinel, Object> sentinelMessage; - private static Function<FrozenColorizer, Object> colorizerMessage; - private static BiFunction<ParticleSpray, FrozenColorizer, Object> particleSprayMessage; - - public static void setSyncChannel(SimpleChannel channel, - Function<Sentinel, Object> sentinelMessage, - Function<FrozenColorizer, Object> colorizerMessage, - BiFunction<ParticleSpray, FrozenColorizer, Object> particleSprayMessage) { - if (HexApiMessages.channel != null) - throw new IllegalStateException("Already set sync channel! If you're not Hex, you shouldn't be calling - this."); - HexApiMessages.channel = channel; - HexApiMessages.sentinelMessage = sentinelMessage; - HexApiMessages.colorizerMessage = colorizerMessage; - HexApiMessages.particleSprayMessage = particleSprayMessage; - } - - public static SimpleChannel getChannel() { - return channel; - } - - public static Object getColorizerMessage(FrozenColorizer colorizer) { - return colorizerMessage.apply(colorizer); - } - - public static Object getSentinelMessage(Sentinel colorizer) { - return sentinelMessage.apply(colorizer); - } - - public static Object getParticleSprayMessage(ParticleSpray spray, FrozenColorizer colorizer) { - return particleSprayMessage.apply(spray, colorizer); - } + private static SimpleChannel channel; + private static Function<Sentinel, Object> sentinelMessage; + private static Function<FrozenColorizer, Object> colorizerMessage; + private static BiFunction<ParticleSpray, FrozenColorizer, Object> particleSprayMessage; + + public static void setSyncChannel(SimpleChannel channel, + Function<Sentinel, Object> sentinelMessage, + Function<FrozenColorizer, Object> colorizerMessage, + BiFunction<ParticleSpray, FrozenColorizer, Object> particleSprayMessage) { + if (HexApiMessages.channel != null) + throw new IllegalStateException("Already set sync channel! If you're not Hex, you shouldn't be calling + this."); + HexApiMessages.channel = channel; + HexApiMessages.sentinelMessage = sentinelMessage; + HexApiMessages.colorizerMessage = colorizerMessage; + HexApiMessages.particleSprayMessage = particleSprayMessage; + } + + public static SimpleChannel getChannel() { + return channel; + } + + public static Object getColorizerMessage(FrozenColorizer colorizer) { + return colorizerMessage.apply(colorizer); + } + + public static Object getSentinelMessage(Sentinel colorizer) { + return sentinelMessage.apply(colorizer); + } + + public static Object getParticleSprayMessage(ParticleSpray spray, FrozenColorizer colorizer) { + return particleSprayMessage.apply(spray, colorizer); + } } */ diff --git a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java index 6f17226b16..cf068cd27f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java @@ -2,159 +2,167 @@ import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.misc.MediaConstants; +import java.util.List; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Tier; import net.minecraft.world.item.Tiers; import net.minecraft.world.level.Level; -import java.util.List; - public class HexConfig { - public interface CommonConfigAccess { - - long dustMediaAmount(); - - long shardMediaAmount(); - - long chargedCrystalMediaAmount(); - - double mediaToHealthRate(); + public interface CommonConfigAccess { - int cypherCooldown(); + long dustMediaAmount(); - int trinketCooldown(); + long shardMediaAmount(); - int artifactCooldown(); + long chargedCrystalMediaAmount(); - long DEFAULT_DUST_MEDIA_AMOUNT = MediaConstants.DUST_UNIT; - long DEFAULT_SHARD_MEDIA_AMOUNT = MediaConstants.SHARD_UNIT; - long DEFAULT_CHARGED_MEDIA_AMOUNT = MediaConstants.CRYSTAL_UNIT; - double DEFAULT_MEDIA_TO_HEALTH_RATE = 2 * MediaConstants.CRYSTAL_UNIT / 20.0; + double mediaToHealthRate(); - int DEFAULT_CYPHER_COOLDOWN = 8; - int DEFAULT_TRINKET_COOLDOWN = 5; - int DEFAULT_ARTIFACT_COOLDOWN = 3; + int cypherCooldown(); - } + int trinketCooldown(); - public interface ClientConfigAccess { - boolean ctrlTogglesOffStrokeOrder(); + int artifactCooldown(); - boolean invertSpellbookScrollDirection(); + long DEFAULT_DUST_MEDIA_AMOUNT = MediaConstants.DUST_UNIT; + long DEFAULT_SHARD_MEDIA_AMOUNT = MediaConstants.SHARD_UNIT; + long DEFAULT_CHARGED_MEDIA_AMOUNT = MediaConstants.CRYSTAL_UNIT; + double DEFAULT_MEDIA_TO_HEALTH_RATE = 2 * MediaConstants.CRYSTAL_UNIT / 20.0; - boolean invertAbacusScrollDirection(); + int DEFAULT_CYPHER_COOLDOWN = 8; + int DEFAULT_TRINKET_COOLDOWN = 5; + int DEFAULT_ARTIFACT_COOLDOWN = 3; + } - double gridSnapThreshold(); + public interface ClientConfigAccess { + boolean ctrlTogglesOffStrokeOrder(); - boolean clickingTogglesDrawing(); + boolean invertSpellbookScrollDirection(); - boolean DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER = false; - boolean DEFAULT_INVERT_SPELLBOOK_SCROLL = false; - boolean DEFAULT_INVERT_ABACUS_SCROLL = false; - double DEFAULT_GRID_SNAP_THRESHOLD = 0.5; - boolean DEFAULT_CLICKING_TOGGLES_DRAWING = false; - } + boolean invertAbacusScrollDirection(); - public interface ServerConfigAccess { - int opBreakHarvestLevelBecauseForgeThoughtItWasAGoodIdeaToImplementHarvestTiersUsingAnHonestToGodTopoSort(); + double gridSnapThreshold(); - int maxOpCount(); + boolean clickingTogglesDrawing(); - int maxSpellCircleLength(); + boolean DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER = false; + boolean DEFAULT_INVERT_SPELLBOOK_SCROLL = false; + boolean DEFAULT_INVERT_ABACUS_SCROLL = false; + double DEFAULT_GRID_SNAP_THRESHOLD = 0.5; + boolean DEFAULT_CLICKING_TOGGLES_DRAWING = false; + } - boolean isActionAllowed(ResourceLocation actionID); + public interface ServerConfigAccess { + int + opBreakHarvestLevelBecauseForgeThoughtItWasAGoodIdeaToImplementHarvestTiersUsingAnHonestToGodTopoSort(); - boolean isActionAllowedInCircles(ResourceLocation actionID); + int maxOpCount(); - boolean doVillagersTakeOffenseAtMindMurder(); + int maxSpellCircleLength(); - // fun fact, although dimension keys are a RegistryHolder, they aren't a registry, so i can't do tags - boolean canTeleportInThisDimension(ResourceKey<Level> dimension); + boolean isActionAllowed(ResourceLocation actionID); - boolean trueNameHasAmbit(); + boolean isActionAllowedInCircles(ResourceLocation actionID); - int DEFAULT_MAX_OP_COUNT = 1_000_000; - int DEFAULT_MAX_SPELL_CIRCLE_LENGTH = 1024; - int DEFAULT_OP_BREAK_HARVEST_LEVEL = 3; + boolean doVillagersTakeOffenseAtMindMurder(); - boolean DEFAULT_VILLAGERS_DISLIKE_MIND_MURDER = true; + // fun fact, although dimension keys are a RegistryHolder, they aren't a registry, so i can't do + // tags + boolean canTeleportInThisDimension(ResourceKey<Level> dimension); - List<String> DEFAULT_DIM_TP_DENYLIST = List.of("twilightforest:twilight_forest"); + boolean trueNameHasAmbit(); - boolean DEFAULT_TRUE_NAME_HAS_AMBIT = true; + int DEFAULT_MAX_OP_COUNT = 1_000_000; + int DEFAULT_MAX_SPELL_CIRCLE_LENGTH = 1024; + int DEFAULT_OP_BREAK_HARVEST_LEVEL = 3; - default Tier opBreakHarvestLevel() { - return switch (this.opBreakHarvestLevelBecauseForgeThoughtItWasAGoodIdeaToImplementHarvestTiersUsingAnHonestToGodTopoSort()) { - case 0 -> Tiers.WOOD; - case 1 -> Tiers.STONE; - case 2 -> Tiers.IRON; - case 3 -> Tiers.DIAMOND; - case 4 -> Tiers.NETHERITE; - default -> throw new RuntimeException("please only return a value in 0<=x<=4"); - }; - } - } + boolean DEFAULT_VILLAGERS_DISLIKE_MIND_MURDER = true; - // Simple extensions for resource location configs - public static boolean anyMatch(List<? extends String> keys, ResourceLocation key) { - for (String s : keys) { - if (ResourceLocation.isValidResourceLocation(s)) { - var rl = new ResourceLocation(s); - if (rl.equals(key)) { - return true; - } - } - } - return false; - } + List<String> DEFAULT_DIM_TP_DENYLIST = List.of("twilightforest:twilight_forest"); - public static boolean noneMatch(List<? extends String> keys, ResourceLocation key) { - return !anyMatch(keys, key); - } + boolean DEFAULT_TRUE_NAME_HAS_AMBIT = true; - public static boolean anyMatchResLoc(List<? extends ResourceLocation> keys, ResourceLocation key) { - return keys.stream().anyMatch(key::equals); - } + default Tier opBreakHarvestLevel() { + return switch (this + .opBreakHarvestLevelBecauseForgeThoughtItWasAGoodIdeaToImplementHarvestTiersUsingAnHonestToGodTopoSort()) { + case 0 -> Tiers.WOOD; + case 1 -> Tiers.STONE; + case 2 -> Tiers.IRON; + case 3 -> Tiers.DIAMOND; + case 4 -> Tiers.NETHERITE; + default -> throw new RuntimeException("please only return a value in 0<=x<=4"); + }; + } + } - // oh man this is aesthetically pleasing - private static CommonConfigAccess common = null; - private static ClientConfigAccess client = null; - private static ServerConfigAccess server = null; + // Simple extensions for resource location configs + public static boolean anyMatch(List<? extends String> keys, ResourceLocation key) { + for (String s : keys) { + if (ResourceLocation.isValidResourceLocation(s)) { + var rl = new ResourceLocation(s); + if (rl.equals(key)) { + return true; + } + } + } + return false; + } - public static CommonConfigAccess common() { - return common; - } - - public static ClientConfigAccess client() { - return client; - } - - public static ServerConfigAccess server() { - return server; - } - - public static void setCommon(CommonConfigAccess access) { - if (common != null) { - HexAPI.LOGGER.warn("CommonConfigAccess was replaced! Old {} New {}", - common.getClass().getName(), access.getClass().getName()); - } - common = access; - } - - public static void setClient(ClientConfigAccess access) { - if (client != null) { - HexAPI.LOGGER.warn("ClientConfigAccess was replaced! Old {} New {}", - client.getClass().getName(), access.getClass().getName()); - } - client = access; - } - - public static void setServer(ServerConfigAccess access) { - if (server != null) { - HexAPI.LOGGER.warn("ServerConfigAccess was replaced! Old {} New {}", - server.getClass().getName(), access.getClass().getName()); - } - server = access; - } + public static boolean noneMatch(List<? extends String> keys, ResourceLocation key) { + return !anyMatch(keys, key); + } + + public static boolean anyMatchResLoc( + List<? extends ResourceLocation> keys, ResourceLocation key) { + return keys.stream().anyMatch(key::equals); + } + + // oh man this is aesthetically pleasing + private static CommonConfigAccess common = null; + private static ClientConfigAccess client = null; + private static ServerConfigAccess server = null; + + public static CommonConfigAccess common() { + return common; + } + + public static ClientConfigAccess client() { + return client; + } + + public static ServerConfigAccess server() { + return server; + } + + public static void setCommon(CommonConfigAccess access) { + if (common != null) { + HexAPI.LOGGER.warn( + "CommonConfigAccess was replaced! Old {} New {}", + common.getClass().getName(), + access.getClass().getName()); + } + common = access; + } + + public static void setClient(ClientConfigAccess access) { + if (client != null) { + HexAPI.LOGGER.warn( + "ClientConfigAccess was replaced! Old {} New {}", + client.getClass().getName(), + access.getClass().getName()); + } + client = access; + } + + public static void setServer(ServerConfigAccess access) { + if (server != null) { + HexAPI.LOGGER.warn( + "ServerConfigAccess was replaced! Old {} New {}", + server.getClass().getName(), + access.getClass().getName()); + } + server = access; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexStatistics.java b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexStatistics.java index fd38fdc7bb..808931cc56 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexStatistics.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexStatistics.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.api.mod; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.misc.MediaConstants; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; @@ -7,24 +9,30 @@ import net.minecraft.stats.StatFormatter; import net.minecraft.stats.Stats; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class HexStatistics { - public static final ResourceLocation MEDIA_USED = makeCustomStat("media_used", - mediamount -> StatFormatter.DEFAULT.format((int) (mediamount / MediaConstants.DUST_UNIT))); - public static final ResourceLocation MEDIA_OVERCAST = makeCustomStat("media_overcast", - mediamount -> StatFormatter.DEFAULT.format((int) (mediamount / MediaConstants.DUST_UNIT))); - public static final ResourceLocation PATTERNS_DRAWN = makeCustomStat("patterns_drawn", StatFormatter.DEFAULT); - public static final ResourceLocation SPELLS_CAST = makeCustomStat("spells_cast", StatFormatter.DEFAULT); + public static final ResourceLocation MEDIA_USED = + makeCustomStat( + "media_used", + mediamount -> + StatFormatter.DEFAULT.format((int) (mediamount / MediaConstants.DUST_UNIT))); + public static final ResourceLocation MEDIA_OVERCAST = + makeCustomStat( + "media_overcast", + mediamount -> + StatFormatter.DEFAULT.format((int) (mediamount / MediaConstants.DUST_UNIT))); + public static final ResourceLocation PATTERNS_DRAWN = + makeCustomStat("patterns_drawn", StatFormatter.DEFAULT); + public static final ResourceLocation SPELLS_CAST = + makeCustomStat("spells_cast", StatFormatter.DEFAULT); - public static void register() { - // wake up java - } + public static void register() { + // wake up java + } - private static ResourceLocation makeCustomStat(String key, StatFormatter formatter) { - ResourceLocation resourcelocation = modLoc(key); - Registry.register(BuiltInRegistries.CUSTOM_STAT, key, resourcelocation); - Stats.CUSTOM.get(resourcelocation, formatter); - return resourcelocation; - } + private static ResourceLocation makeCustomStat(String key, StatFormatter formatter) { + ResourceLocation resourcelocation = modLoc(key); + Registry.register(BuiltInRegistries.CUSTOM_STAT, key, resourcelocation); + Stats.CUSTOM.get(resourcelocation, formatter); + return resourcelocation; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexTags.java b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexTags.java index 238afae719..6f3e64a179 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexTags.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexTags.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.api.mod; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.ActionRegistryEntry; import at.petrak.hexcasting.xplat.IXplatAbstractions; import net.minecraft.core.registries.Registries; @@ -9,78 +11,76 @@ import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class HexTags { - public static final class Items { - public static final TagKey<Item> EDIFIED_LOGS = create("edified_logs"); - public static final TagKey<Item> EDIFIED_PLANKS = create("edified_planks"); - public static final TagKey<Item> STAVES = create("staves"); - public static final TagKey<Item> PHIAL_BASE = create("phial_base"); - public static final TagKey<Item> GRANTS_ROOT_ADVANCEMENT = create("grants_root_advancement"); - public static final TagKey<Item> SEAL_MATERIALS = create("seal_materials"); - - public static final TagKey<Item> IMPETI = create("impeti"); - public static final TagKey<Item> DIRECTRICES = create("directrices"); - public static final TagKey<Item> MINDFLAYED_CIRCLE_COMPONENTS = create("brainswept_circle_components"); - - public static TagKey<Item> create(String name) { - return create(modLoc(name)); - } - - public static TagKey<Item> create(ResourceLocation id) { - return TagKey.create(Registries.ITEM, id); - } - } - - public static final class Blocks { - public static final TagKey<Block> EDIFIED_LOGS = create("edified_logs"); - public static final TagKey<Block> EDIFIED_PLANKS = create("edified_planks"); - - - public static final TagKey<Block> IMPETI = create("impeti"); - public static final TagKey<Block> DIRECTRICES = create("directrices"); - public static final TagKey<Block> MINDFLAYED_CIRCLE_COMPONENTS = create("brainswept_circle_components"); - - // Used to determine what blocks should be replaced with air by OpDestroyFluid - public static final TagKey<Block> WATER_PLANTS = create("water_plants"); - - public static final TagKey<Block> CHEAP_TO_BREAK_BLOCK = create("cheap_to_break_block"); - - public static TagKey<Block> create(String name) { - return TagKey.create(Registries.BLOCK, modLoc(name)); - } - } - - public static final class Entities { - public static final TagKey<EntityType<?>> STICKY_TELEPORTERS = create("sticky_teleporters"); - public static final TagKey<EntityType<?>> CANNOT_TELEPORT = create("cannot_teleport"); - - public static final TagKey<EntityType<?>> NO_BRAINSWEEPING = create("cannot_brainsweep"); - - public static TagKey<EntityType<?>> create(String name) { - return TagKey.create(Registries.ENTITY_TYPE, modLoc(name)); - } - } - - public static final class Actions { - /** - * Actions with this tag can't be used until the caster is enlightened and send the - * "am I not skilled enough" message - */ - public static final TagKey<ActionRegistryEntry> REQUIRES_ENLIGHTENMENT = create("requires_enlightenment"); - /** - * Actions where the pattern is calculated per-world - */ - public static final TagKey<ActionRegistryEntry> PER_WORLD_PATTERN = create("per_world_pattern"); - - /** - * Actions that can cause Blind Diversion - */ - public static final TagKey<ActionRegistryEntry> CAN_START_ENLIGHTEN = create("can_start_enlighten"); - - public static TagKey<ActionRegistryEntry> create(String name) { - return TagKey.create(IXplatAbstractions.INSTANCE.getActionRegistry().key(), modLoc(name)); - } - } + public static final class Items { + public static final TagKey<Item> EDIFIED_LOGS = create("edified_logs"); + public static final TagKey<Item> EDIFIED_PLANKS = create("edified_planks"); + public static final TagKey<Item> STAVES = create("staves"); + public static final TagKey<Item> PHIAL_BASE = create("phial_base"); + public static final TagKey<Item> GRANTS_ROOT_ADVANCEMENT = create("grants_root_advancement"); + public static final TagKey<Item> SEAL_MATERIALS = create("seal_materials"); + + public static final TagKey<Item> IMPETI = create("impeti"); + public static final TagKey<Item> DIRECTRICES = create("directrices"); + public static final TagKey<Item> MINDFLAYED_CIRCLE_COMPONENTS = + create("brainswept_circle_components"); + + public static TagKey<Item> create(String name) { + return create(modLoc(name)); + } + + public static TagKey<Item> create(ResourceLocation id) { + return TagKey.create(Registries.ITEM, id); + } + } + + public static final class Blocks { + public static final TagKey<Block> EDIFIED_LOGS = create("edified_logs"); + public static final TagKey<Block> EDIFIED_PLANKS = create("edified_planks"); + + public static final TagKey<Block> IMPETI = create("impeti"); + public static final TagKey<Block> DIRECTRICES = create("directrices"); + public static final TagKey<Block> MINDFLAYED_CIRCLE_COMPONENTS = + create("brainswept_circle_components"); + + // Used to determine what blocks should be replaced with air by OpDestroyFluid + public static final TagKey<Block> WATER_PLANTS = create("water_plants"); + + public static final TagKey<Block> CHEAP_TO_BREAK_BLOCK = create("cheap_to_break_block"); + + public static TagKey<Block> create(String name) { + return TagKey.create(Registries.BLOCK, modLoc(name)); + } + } + + public static final class Entities { + public static final TagKey<EntityType<?>> STICKY_TELEPORTERS = create("sticky_teleporters"); + public static final TagKey<EntityType<?>> CANNOT_TELEPORT = create("cannot_teleport"); + + public static final TagKey<EntityType<?>> NO_BRAINSWEEPING = create("cannot_brainsweep"); + + public static TagKey<EntityType<?>> create(String name) { + return TagKey.create(Registries.ENTITY_TYPE, modLoc(name)); + } + } + + public static final class Actions { + /** + * Actions with this tag can't be used until the caster is enlightened and send the "am I not + * skilled enough" message + */ + public static final TagKey<ActionRegistryEntry> REQUIRES_ENLIGHTENMENT = + create("requires_enlightenment"); + + /** Actions where the pattern is calculated per-world */ + public static final TagKey<ActionRegistryEntry> PER_WORLD_PATTERN = create("per_world_pattern"); + + /** Actions that can cause Blind Diversion */ + public static final TagKey<ActionRegistryEntry> CAN_START_ENLIGHTEN = + create("can_start_enlighten"); + + public static TagKey<ActionRegistryEntry> create(String name) { + return TagKey.create(IXplatAbstractions.INSTANCE.getActionRegistry().key(), modLoc(name)); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/pigment/ColorProvider.java b/Common/src/main/java/at/petrak/hexcasting/api/pigment/ColorProvider.java index 8c0611db2e..86e54a0e16 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/pigment/ColorProvider.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/pigment/ColorProvider.java @@ -5,46 +5,47 @@ import net.minecraft.world.phys.Vec3; public abstract class ColorProvider { - /** - * Implers, impl this function - */ - protected abstract int getRawColor(float time, Vec3 position); - - private static final int[] MINIMUM_LUMINANCE_COLOR_WHEEL = { - 0xFF200000, 0xFF202000, 0xFF002000, 0xFF002020, 0xFF000020, 0xFF200020 - }; - - /** - * Gets a color with a minimum luminance applied. - * - * @param time absolute world time in ticks - * @param position a position for the icosahedron, a randomish number for particles. - * @return an AARRGGBB color. - */ - public final int getColor(float time, Vec3 position) { - int raw = this.getRawColor(time, position); - - var r = FastColor.ARGB32.red(raw); - var g = FastColor.ARGB32.green(raw); - var b = FastColor.ARGB32.blue(raw); - double luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 0xFF; // Standard relative luminance calculation - - if (luminance < 0.05) { - int rawMod = ADPigment.morphBetweenColors(MINIMUM_LUMINANCE_COLOR_WHEEL, new Vec3(0.1, 0.1, 0.1), - time / 20 / 20, position); - - r += FastColor.ARGB32.red(rawMod); - g += FastColor.ARGB32.green(rawMod); - b += FastColor.ARGB32.blue(rawMod); - } - - return 0xff_000000 | (r << 16) | (g << 8) | b; - } - - public static final ColorProvider MISSING = new ColorProvider() { - @Override - protected int getRawColor(float time, Vec3 position) { - return 0xFF_ff00dc; - } - }; + /** Implers, impl this function */ + protected abstract int getRawColor(float time, Vec3 position); + + private static final int[] MINIMUM_LUMINANCE_COLOR_WHEEL = { + 0xFF200000, 0xFF202000, 0xFF002000, 0xFF002020, 0xFF000020, 0xFF200020 + }; + + /** + * Gets a color with a minimum luminance applied. + * + * @param time absolute world time in ticks + * @param position a position for the icosahedron, a randomish number for particles. + * @return an AARRGGBB color. + */ + public final int getColor(float time, Vec3 position) { + int raw = this.getRawColor(time, position); + + var r = FastColor.ARGB32.red(raw); + var g = FastColor.ARGB32.green(raw); + var b = FastColor.ARGB32.blue(raw); + double luminance = + (0.2126 * r + 0.7152 * g + 0.0722 * b) / 0xFF; // Standard relative luminance calculation + + if (luminance < 0.05) { + int rawMod = + ADPigment.morphBetweenColors( + MINIMUM_LUMINANCE_COLOR_WHEEL, new Vec3(0.1, 0.1, 0.1), time / 20 / 20, position); + + r += FastColor.ARGB32.red(rawMod); + g += FastColor.ARGB32.green(rawMod); + b += FastColor.ARGB32.blue(rawMod); + } + + return 0xff_000000 | (r << 16) | (g << 8) | b; + } + + public static final ColorProvider MISSING = + new ColorProvider() { + @Override + protected int getRawColor(float time, Vec3 position) { + return 0xFF_ff00dc; + } + }; } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/pigment/FrozenPigment.java b/Common/src/main/java/at/petrak/hexcasting/api/pigment/FrozenPigment.java index f5cd478e0e..790222b90b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/pigment/FrozenPigment.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/pigment/FrozenPigment.java @@ -2,49 +2,48 @@ import at.petrak.hexcasting.common.lib.HexItems; import at.petrak.hexcasting.xplat.IXplatAbstractions; +import java.util.UUID; +import java.util.function.Supplier; import net.minecraft.Util; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; -import java.util.UUID; -import java.util.function.Supplier; - /** * A snapshot of a pigment item and its owner. - * <p> - * Due to capabilities being really slow to query many times a tick on Forge, this returns a colorizer <i>supplier</i>. - * Get it once, and then query it a lot. + * + * <p>Due to capabilities being really slow to query many times a tick on Forge, this returns a + * colorizer <i>supplier</i>. Get it once, and then query it a lot. */ public record FrozenPigment(ItemStack item, UUID owner) { - public static final String TAG_STACK = "stack"; - public static final String TAG_OWNER = "owner"; - - public static final Supplier<FrozenPigment> DEFAULT = - () -> new FrozenPigment(new ItemStack(HexItems.DEFAULT_PIGMENT), Util.NIL_UUID); - - public CompoundTag serializeToNBT() { - var out = new CompoundTag(); - out.put(TAG_STACK, this.item.save(new CompoundTag())); - out.putUUID(TAG_OWNER, this.owner); - return out; - } - - public static FrozenPigment fromNBT(CompoundTag tag) { - if (tag.isEmpty()) { - return FrozenPigment.DEFAULT.get(); - } - try { - CompoundTag stackTag = tag.getCompound(TAG_STACK); - var stack = ItemStack.of(stackTag); - var uuid = tag.getUUID(TAG_OWNER); - return new FrozenPigment(stack, uuid); - } catch (NullPointerException exn) { - return FrozenPigment.DEFAULT.get(); - } - } - - public ColorProvider getColorProvider() { - return IXplatAbstractions.INSTANCE.getColorProvider(this); - } + public static final String TAG_STACK = "stack"; + public static final String TAG_OWNER = "owner"; + + public static final Supplier<FrozenPigment> DEFAULT = + () -> new FrozenPigment(new ItemStack(HexItems.DEFAULT_PIGMENT), Util.NIL_UUID); + + public CompoundTag serializeToNBT() { + var out = new CompoundTag(); + out.put(TAG_STACK, this.item.save(new CompoundTag())); + out.putUUID(TAG_OWNER, this.owner); + return out; + } + + public static FrozenPigment fromNBT(CompoundTag tag) { + if (tag.isEmpty()) { + return FrozenPigment.DEFAULT.get(); + } + try { + CompoundTag stackTag = tag.getCompound(TAG_STACK); + var stack = ItemStack.of(stackTag); + var uuid = tag.getUUID(TAG_OWNER); + return new FrozenPigment(stack, uuid); + } catch (NullPointerException exn) { + return FrozenPigment.DEFAULT.get(); + } + } + + public ColorProvider getColorProvider() { + return IXplatAbstractions.INSTANCE.getColorProvider(this); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/player/AltioraAbility.java b/Common/src/main/java/at/petrak/hexcasting/api/player/AltioraAbility.java index 304a02121d..be7bb9fac1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/player/AltioraAbility.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/player/AltioraAbility.java @@ -1,10 +1,10 @@ package at.petrak.hexcasting.api.player; /** - * Note that this just keeps track of state, actually giving the player the elytra ability is handled - * differently per platform + * Note that this just keeps track of state, actually giving the player the elytra ability is + * handled differently per platform * - * @param gracePeriod so the flight isn't immediately removed because the player started on the ground + * @param gracePeriod so the flight isn't immediately removed because the player started on the + * ground */ -public record AltioraAbility(int gracePeriod) { -} +public record AltioraAbility(int gracePeriod) {} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/player/FlightAbility.java b/Common/src/main/java/at/petrak/hexcasting/api/player/FlightAbility.java index 7980a561be..81a145f039 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/player/FlightAbility.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/player/FlightAbility.java @@ -6,7 +6,7 @@ /** * @param timeLeft sentinel of -1 for infinite - * @param radius sentinel of negative for infinite + * @param radius sentinel of negative for infinite */ -public record FlightAbility(int timeLeft, ResourceKey<Level> dimension, Vec3 origin, double radius) { -} +public record FlightAbility( + int timeLeft, ResourceKey<Level> dimension, Vec3 origin, double radius) {} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/player/Sentinel.java b/Common/src/main/java/at/petrak/hexcasting/api/player/Sentinel.java index 867b4fca34..c0c795dfee 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/player/Sentinel.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/player/Sentinel.java @@ -4,8 +4,5 @@ import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; -/** - * A null sentinel means no sentinel - */ -public record Sentinel(boolean extendsRange, Vec3 position, ResourceKey<Level> dimension) { -} +/** A null sentinel means no sentinel */ +public record Sentinel(boolean extendsRange, Vec3 position, ResourceKey<Level> dimension) {} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt b/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt index 209297766a..31243644d9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt @@ -6,6 +6,13 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.IotaType import at.petrak.hexcasting.api.casting.iota.ListIota import at.petrak.hexcasting.api.casting.math.HexCoord +import java.lang.ref.WeakReference +import java.util.* +import kotlin.math.absoluteValue +import kotlin.math.max +import kotlin.math.min +import kotlin.math.roundToInt +import kotlin.reflect.KProperty import net.minecraft.ChatFormatting import net.minecraft.core.Registry import net.minecraft.nbt.* @@ -19,233 +26,279 @@ import net.minecraft.world.InteractionHand import net.minecraft.world.item.ItemStack import net.minecraft.world.phys.Vec2 import net.minecraft.world.phys.Vec3 -import java.lang.ref.WeakReference -import java.util.* -import kotlin.math.absoluteValue -import kotlin.math.max -import kotlin.math.min -import kotlin.math.roundToInt -import kotlin.reflect.KProperty const val TAU = Math.PI * 2.0 const val SQRT_3 = 1.7320508f fun Vec3.serializeToNBT(): CompoundTag { - val tag = CompoundTag() - tag.putDouble("x", this.x) - tag.putDouble("y", this.y) - tag.putDouble("z", this.z) - return tag + val tag = CompoundTag() + tag.putDouble("x", this.x) + tag.putDouble("y", this.y) + tag.putDouble("z", this.z) + return tag } -fun vecFromNBT(tag: LongArray): Vec3 = if (tag.size != 3) Vec3.ZERO else - Vec3( - Double.fromBits(tag[0]), - Double.fromBits(tag[1]), - Double.fromBits(tag[2]) - ) +fun vecFromNBT(tag: LongArray): Vec3 = + if (tag.size != 3) Vec3.ZERO + else Vec3(Double.fromBits(tag[0]), Double.fromBits(tag[1]), Double.fromBits(tag[2])) + fun vecFromNBT(tag: CompoundTag): Vec3 { - return if (!tag.contains("x") || !tag.contains("y") || !tag.contains("z")) - Vec3.ZERO - else - Vec3(tag.getDouble("x"), tag.getDouble("y"), tag.getDouble("z")) + return if (!tag.contains("x") || !tag.contains("y") || !tag.contains("z")) Vec3.ZERO + else Vec3(tag.getDouble("x"), tag.getDouble("y"), tag.getDouble("z")) } fun Vec2.serializeToNBT(): LongArrayTag = - LongArrayTag(longArrayOf(this.x.toDouble().toRawBits(), this.y.toDouble().toRawBits())) + LongArrayTag(longArrayOf(this.x.toDouble().toRawBits(), this.y.toDouble().toRawBits())) -fun vec2FromNBT(tag: LongArray): Vec2 = if (tag.size != 2) Vec2.ZERO else - Vec2( - Double.fromBits(tag[0]).toFloat(), - Double.fromBits(tag[1]).toFloat(), - ) +fun vec2FromNBT(tag: LongArray): Vec2 = + if (tag.size != 2) Vec2.ZERO + else + Vec2( + Double.fromBits(tag[0]).toFloat(), + Double.fromBits(tag[1]).toFloat(), + ) fun otherHand(hand: InteractionHand) = - if (hand == InteractionHand.MAIN_HAND) InteractionHand.OFF_HAND else InteractionHand.MAIN_HAND + if (hand == InteractionHand.MAIN_HAND) InteractionHand.OFF_HAND else InteractionHand.MAIN_HAND fun fixNAN(n: Double): Double = if (n.isFinite()) n else 0.0 fun findCenter(points: List<Vec2>): Vec2 { - var minX = Float.POSITIVE_INFINITY - var minY = Float.POSITIVE_INFINITY - var maxX = Float.NEGATIVE_INFINITY - var maxY = Float.NEGATIVE_INFINITY - - for (pos in points) { - minX = min(minX, pos.x) - minY = min(minY, pos.y) - maxX = max(maxX, pos.x) - maxY = max(maxY, pos.y) - } - return Vec2( - (minX + maxX) / 2f, - (minY + maxY) / 2f - ) + var minX = Float.POSITIVE_INFINITY + var minY = Float.POSITIVE_INFINITY + var maxX = Float.NEGATIVE_INFINITY + var maxY = Float.NEGATIVE_INFINITY + + for (pos in points) { + minX = min(minX, pos.x) + minY = min(minY, pos.y) + maxX = max(maxX, pos.x) + maxY = max(maxY, pos.y) + } + return Vec2((minX + maxX) / 2f, (minY + maxY) / 2f) } fun coordToPx(coord: HexCoord, size: Float, offset: Vec2): Vec2 = - Vec2( - SQRT_3 * coord.q.toFloat() + SQRT_3 / 2.0f * coord.r.toFloat(), - 1.5f * coord.r.toFloat() - ).scale(size).add(offset) + Vec2(SQRT_3 * coord.q.toFloat() + SQRT_3 / 2.0f * coord.r.toFloat(), 1.5f * coord.r.toFloat()) + .scale(size) + .add(offset) fun pxToCoord(px: Vec2, size: Float, offset: Vec2): HexCoord { - val offsetted = px.add(offset.negated()) - var qf = (SQRT_3 / 3.0f * offsetted.x - 0.33333f * offsetted.y) / size - var rf = (0.66666f * offsetted.y) / size - - val q = qf.roundToInt() - val r = rf.roundToInt() - qf -= q - rf -= r - return if (q.absoluteValue >= r.absoluteValue) - HexCoord(q + (qf + 0.5f * rf).roundToInt(), r) - else - HexCoord(q, r + (rf + 0.5 * qf).roundToInt()) + val offsetted = px.add(offset.negated()) + var qf = (SQRT_3 / 3.0f * offsetted.x - 0.33333f * offsetted.y) / size + var rf = (0.66666f * offsetted.y) / size + + val q = qf.roundToInt() + val r = rf.roundToInt() + qf -= q + rf -= r + return if (q.absoluteValue >= r.absoluteValue) HexCoord(q + (qf + 0.5f * rf).roundToInt(), r) + else HexCoord(q, r + (rf + 0.5 * qf).roundToInt()) } @JvmOverloads fun <T : Enum<T>> Array<T>.getSafe(key: String, default: T = this[0]): T { - val lowercaseKey = key.lowercase(Locale.ROOT) - return firstOrNull { it.name.lowercase(Locale.ROOT) == lowercaseKey } ?: default + val lowercaseKey = key.lowercase(Locale.ROOT) + return firstOrNull { it.name.lowercase(Locale.ROOT) == lowercaseKey } ?: default } @JvmOverloads -fun <T : Enum<T>> Array<T>.getSafe(index: Byte, default: T = this[0]) = getSafe(index.toInt(), default) +fun <T : Enum<T>> Array<T>.getSafe(index: Byte, default: T = this[0]) = + getSafe(index.toInt(), default) @JvmOverloads -fun <T : Enum<T>> Array<T>.getSafe(index: Int, default: T = this[0]) = if (index in indices) this[index] else default +fun <T : Enum<T>> Array<T>.getSafe(index: Int, default: T = this[0]) = + if (index in indices) this[index] else default fun String.withStyle(op: (Style) -> Style): MutableComponent = asTextComponent.withStyle(op) -fun String.withStyle(style: Style): MutableComponent = asTextComponent.withStyle(style) -fun String.withStyle(formatting: ChatFormatting): MutableComponent = asTextComponent.withStyle(formatting) -fun String.withStyle(vararg formatting: ChatFormatting): MutableComponent = asTextComponent.withStyle(*formatting) - -infix fun String.styledWith(op: (Style) -> Style) = withStyle(op) -infix fun String.styledWith(style: Style) = withStyle(style) -infix fun String.styledWith(formatting: ChatFormatting) = withStyle(formatting) - -infix fun MutableComponent.styledWith(op: (Style) -> Style): MutableComponent = withStyle(op) -infix fun MutableComponent.styledWith(style: Style): MutableComponent = withStyle(style) -infix fun MutableComponent.styledWith(formatting: ChatFormatting): MutableComponent = withStyle(formatting) - -val String.black get() = this styledWith ChatFormatting.BLACK -val MutableComponent.black get() = this styledWith ChatFormatting.BLACK - -val String.darkBlue get() = this styledWith ChatFormatting.DARK_BLUE -val MutableComponent.darkBlue get() = this styledWith ChatFormatting.DARK_BLUE - -val String.darkGreen get() = this styledWith ChatFormatting.DARK_GREEN -val MutableComponent.darkGreen get() = this styledWith ChatFormatting.DARK_GREEN - -val String.darkAqua get() = this styledWith ChatFormatting.DARK_AQUA -val MutableComponent.darkAqua get() = this styledWith ChatFormatting.DARK_AQUA - -val String.darkRed get() = this styledWith ChatFormatting.DARK_RED -val MutableComponent.darkRed get() = this styledWith ChatFormatting.DARK_RED - -val String.darkPurple get() = this styledWith ChatFormatting.DARK_PURPLE -val MutableComponent.darkPurple get() = this styledWith ChatFormatting.DARK_PURPLE - -val String.gold get() = this styledWith ChatFormatting.GOLD -val MutableComponent.gold get() = this styledWith ChatFormatting.GOLD - -val String.gray get() = this styledWith ChatFormatting.GRAY -val MutableComponent.gray get() = this styledWith ChatFormatting.GRAY - -val String.darkGray get() = this styledWith ChatFormatting.DARK_GRAY -val MutableComponent.darkGray get() = this styledWith ChatFormatting.DARK_GRAY - -val String.blue get() = this styledWith ChatFormatting.BLUE -val MutableComponent.blue get() = this styledWith ChatFormatting.BLUE -val String.green get() = this styledWith ChatFormatting.GREEN -val MutableComponent.green get() = this styledWith ChatFormatting.GREEN - -val String.aqua get() = this styledWith ChatFormatting.AQUA -val MutableComponent.aqua get() = this styledWith ChatFormatting.AQUA - -val String.red get() = this styledWith ChatFormatting.RED -val MutableComponent.red get() = this styledWith ChatFormatting.RED +fun String.withStyle(style: Style): MutableComponent = asTextComponent.withStyle(style) -val String.lightPurple get() = this styledWith ChatFormatting.LIGHT_PURPLE -val MutableComponent.lightPurple get() = this styledWith ChatFormatting.LIGHT_PURPLE +fun String.withStyle(formatting: ChatFormatting): MutableComponent = + asTextComponent.withStyle(formatting) -val String.yellow get() = this styledWith ChatFormatting.YELLOW -val MutableComponent.yellow get() = this styledWith ChatFormatting.YELLOW +fun String.withStyle(vararg formatting: ChatFormatting): MutableComponent = + asTextComponent.withStyle(*formatting) -val String.white get() = this styledWith ChatFormatting.WHITE -val MutableComponent.white get() = this styledWith ChatFormatting.WHITE +infix fun String.styledWith(op: (Style) -> Style) = withStyle(op) -val String.obfuscated get() = this styledWith ChatFormatting.OBFUSCATED -val MutableComponent.obfuscated get() = this styledWith ChatFormatting.OBFUSCATED +infix fun String.styledWith(style: Style) = withStyle(style) -val String.bold get() = this styledWith ChatFormatting.BOLD -val MutableComponent.bold get() = this styledWith ChatFormatting.BOLD +infix fun String.styledWith(formatting: ChatFormatting) = withStyle(formatting) -val String.strikethrough get() = this styledWith ChatFormatting.STRIKETHROUGH -val MutableComponent.strikethrough get() = this styledWith ChatFormatting.STRIKETHROUGH +infix fun MutableComponent.styledWith(op: (Style) -> Style): MutableComponent = withStyle(op) -val String.underline get() = this styledWith ChatFormatting.UNDERLINE -val MutableComponent.underline get() = this styledWith ChatFormatting.UNDERLINE +infix fun MutableComponent.styledWith(style: Style): MutableComponent = withStyle(style) -val String.italic get() = this styledWith ChatFormatting.ITALIC -val MutableComponent.italic get() = this styledWith ChatFormatting.ITALIC +infix fun MutableComponent.styledWith(formatting: ChatFormatting): MutableComponent = + withStyle(formatting) + +val String.black + get() = this styledWith ChatFormatting.BLACK +val MutableComponent.black + get() = this styledWith ChatFormatting.BLACK + +val String.darkBlue + get() = this styledWith ChatFormatting.DARK_BLUE +val MutableComponent.darkBlue + get() = this styledWith ChatFormatting.DARK_BLUE + +val String.darkGreen + get() = this styledWith ChatFormatting.DARK_GREEN +val MutableComponent.darkGreen + get() = this styledWith ChatFormatting.DARK_GREEN + +val String.darkAqua + get() = this styledWith ChatFormatting.DARK_AQUA +val MutableComponent.darkAqua + get() = this styledWith ChatFormatting.DARK_AQUA + +val String.darkRed + get() = this styledWith ChatFormatting.DARK_RED +val MutableComponent.darkRed + get() = this styledWith ChatFormatting.DARK_RED + +val String.darkPurple + get() = this styledWith ChatFormatting.DARK_PURPLE +val MutableComponent.darkPurple + get() = this styledWith ChatFormatting.DARK_PURPLE + +val String.gold + get() = this styledWith ChatFormatting.GOLD +val MutableComponent.gold + get() = this styledWith ChatFormatting.GOLD + +val String.gray + get() = this styledWith ChatFormatting.GRAY +val MutableComponent.gray + get() = this styledWith ChatFormatting.GRAY + +val String.darkGray + get() = this styledWith ChatFormatting.DARK_GRAY +val MutableComponent.darkGray + get() = this styledWith ChatFormatting.DARK_GRAY + +val String.blue + get() = this styledWith ChatFormatting.BLUE +val MutableComponent.blue + get() = this styledWith ChatFormatting.BLUE + +val String.green + get() = this styledWith ChatFormatting.GREEN +val MutableComponent.green + get() = this styledWith ChatFormatting.GREEN + +val String.aqua + get() = this styledWith ChatFormatting.AQUA +val MutableComponent.aqua + get() = this styledWith ChatFormatting.AQUA + +val String.red + get() = this styledWith ChatFormatting.RED +val MutableComponent.red + get() = this styledWith ChatFormatting.RED + +val String.lightPurple + get() = this styledWith ChatFormatting.LIGHT_PURPLE +val MutableComponent.lightPurple + get() = this styledWith ChatFormatting.LIGHT_PURPLE + +val String.yellow + get() = this styledWith ChatFormatting.YELLOW +val MutableComponent.yellow + get() = this styledWith ChatFormatting.YELLOW + +val String.white + get() = this styledWith ChatFormatting.WHITE +val MutableComponent.white + get() = this styledWith ChatFormatting.WHITE + +val String.obfuscated + get() = this styledWith ChatFormatting.OBFUSCATED +val MutableComponent.obfuscated + get() = this styledWith ChatFormatting.OBFUSCATED + +val String.bold + get() = this styledWith ChatFormatting.BOLD +val MutableComponent.bold + get() = this styledWith ChatFormatting.BOLD + +val String.strikethrough + get() = this styledWith ChatFormatting.STRIKETHROUGH +val MutableComponent.strikethrough + get() = this styledWith ChatFormatting.STRIKETHROUGH + +val String.underline + get() = this styledWith ChatFormatting.UNDERLINE +val MutableComponent.underline + get() = this styledWith ChatFormatting.UNDERLINE + +val String.italic + get() = this styledWith ChatFormatting.ITALIC +val MutableComponent.italic + get() = this styledWith ChatFormatting.ITALIC operator fun MutableComponent.plusAssign(component: Component) { - append(component) + append(component) } -val String.asTextComponent: MutableComponent get() = Component.literal(this) -val String.asTranslatedComponent: MutableComponent get() = Component.translatable(this) +val String.asTextComponent: MutableComponent + get() = Component.literal(this) +val String.asTranslatedComponent: MutableComponent + get() = Component.translatable(this) -fun String.asTranslatedComponent(vararg args: Any): MutableComponent = Component.translatable(this, *args) +fun String.asTranslatedComponent(vararg args: Any): MutableComponent = + Component.translatable(this, *args) /** - * Represents a value that the garbage collector is still allowed to collect. - * To create an instance of a [WeakValue], use [weakReference] or [weakMapped]. + * Represents a value that the garbage collector is still allowed to collect. To create an instance + * of a [WeakValue], use [weakReference] or [weakMapped]. */ interface WeakValue<T> { - var value: T? + var value: T? } /** * A weakly referenced value that relies directly on a [WeakReference]. * - * This means that if there are no other places where the contained object is referenced, - * the reference will expire, and value contained within this reference will become null. + * This means that if there are no other places where the contained object is referenced, the + * reference will expire, and value contained within this reference will become null. */ private class WeakReferencedValue<T>(var reference: WeakReference<T>?) : WeakValue<T> { - override var value: T? - get() = reference?.get() - set(value) { - reference = value?.let(::WeakReference) - } + override var value: T? + get() = reference?.get() + set(value) { + reference = value?.let(::WeakReference) + } } /** * A weakly referenced value that relies on a [WeakHashMap]. * - * Unlike [WeakReferencedValue], it relies on the continued existence of something else (obtained by [keyGen]). - * For example, this can be used to hold an entity, and have the reference expire when the world it's in is unloaded. + * Unlike [WeakReferencedValue], it relies on the continued existence of something else (obtained by + * [keyGen]). For example, this can be used to hold an entity, and have the reference expire when + * the world it's in is unloaded. */ private class WeakMappedValue<K, T>(val keyGen: (T) -> K) : WeakValue<T> { - val reference = WeakHashMap<K, T>() - override var value: T? - get() = reference.values.firstOrNull() - set(value) { - reference.clear() - if (value != null) reference[keyGen(value)] = value - } + val reference = WeakHashMap<K, T>() + override var value: T? + get() = reference.values.firstOrNull() + set(value) { + reference.clear() + if (value != null) reference[keyGen(value)] = value + } } /** - * Creates a [WeakReferencedValue], the contents of which will expire when nothing else is referencing them. + * Creates a [WeakReferencedValue], the contents of which will expire when nothing else is + * referencing them. */ -fun <T> weakReference(value: T? = null): WeakValue<T> = WeakReferencedValue(value?.let { WeakReference(it) }) +fun <T> weakReference(value: T? = null): WeakValue<T> = + WeakReferencedValue(value?.let { WeakReference(it) }) /** - * Creates a [WeakMappedValue], the contents of which will expire when nothing else is referencing the value returned by [keyGen]. + * Creates a [WeakMappedValue], the contents of which will expire when nothing else is referencing + * the value returned by [keyGen]. */ fun <T, K> weakMapped(keyGen: (T) -> K): WeakValue<T> = WeakMappedValue(keyGen) @@ -255,61 +308,57 @@ inline operator fun <T> WeakValue<T>.getValue(thisRef: Any?, property: KProperty @Suppress("NOTHING_TO_INLINE") inline operator fun <T> WeakValue<T>.setValue(thisRef: Any?, property: KProperty<*>, value: T?) { - this.value = value + this.value = value } -/** - * Returns an empty list if it's too complicated. - */ +/** Returns an empty list if it's too complicated. */ fun Iterable<Iota>.serializeToNBT() = - if (IotaType.isTooLargeToSerialize(this)) - ListTag() - else - ListIota(this.toList()).serialize() + if (IotaType.isTooLargeToSerialize(this)) ListTag() else ListIota(this.toList()).serialize() fun Iterable<Boolean>.serializeToNBT(): ByteArrayTag { - val out = ByteArray(if (this is Collection<*>) this.size else 10) - for ((i, b) in this.withIndex()) { - out[i] = if (b) 1 else 0 - } - return ByteArrayTag(out) + val out = ByteArray(if (this is Collection<*>) this.size else 10) + for ((i, b) in this.withIndex()) { + out[i] = if (b) 1 else 0 + } + return ByteArrayTag(out) } fun <A> List<A>.zipWithDefault(array: ByteArray, default: (idx: Int) -> Byte): List<Pair<A, Byte>> { - val list = ArrayList<Pair<A, Byte>>(this.size) - var i = 0 - for (element in this) list.add(element to array.getOrElse(i++, default)) + val list = ArrayList<Pair<A, Byte>>(this.size) + var i = 0 + for (element in this) list.add(element to array.getOrElse(i++, default)) - return list + return list } // Copy the impl from forge fun ItemStack.serializeToNBT(): CompoundTag { - val out = CompoundTag() - this.save(out) - return out + val out = CompoundTag() + this.save(out) + return out } @Suppress("UNCHECKED_CAST") @Throws(IllegalArgumentException::class) fun <T : Tag> Tag.downcast(type: TagType<T>): T { - if (this.type == type) { - return this as T - } else { - throw IllegalArgumentException( - "Expected this tag to be of type ${type.name}, but found ${this.type.name}." - ) - } + if (this.type == type) { + return this as T + } else { + throw IllegalArgumentException( + "Expected this tag to be of type ${type.name}, but found ${this.type.name}." + ) + } } const val ERROR_COLOR = 0xff_f800f8.toInt() + fun <T> isOfTag(registry: Registry<T>, key: ResourceKey<T>, tag: TagKey<T>): Boolean { - val maybeHolder = registry.getHolder(key) - val holder = if (maybeHolder.isPresent) maybeHolder.get() else return false - return holder.`is`(tag) + val maybeHolder = registry.getHolder(key) + val holder = if (maybeHolder.isPresent) maybeHolder.get() else return false + return holder.`is`(tag) } fun <T> isOfTag(registry: Registry<T>, loc: ResourceLocation, tag: TagKey<T>): Boolean { - val key = ResourceKey.create(registry.key(), loc); - return isOfTag(registry, key, tag) + val key = ResourceKey.create(registry.key(), loc) + return isOfTag(registry, key, tag) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/utils/MathUtils.kt b/Common/src/main/java/at/petrak/hexcasting/api/utils/MathUtils.kt index 84448cc394..d664e7466e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/utils/MathUtils.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/utils/MathUtils.kt @@ -1,38 +1,40 @@ package at.petrak.hexcasting.api.utils +import kotlin.math.* import org.joml.Quaternionf import org.joml.Vector3f -import kotlin.math.* object MathUtils { - @JvmStatic - fun clamp(long: Long, min: Long, max: Long): Long - = if (long <= min) min - else if (long >= max) max - else long + @JvmStatic + fun clamp(long: Long, min: Long, max: Long): Long = + if (long <= min) min else if (long >= max) max else long } object QuaternionfUtils { - @JvmStatic - val ONE: Quaternionf - get() = Quaternionf(0.0f, 0.0f, 0.0f, 1.0f) + @JvmStatic + val ONE: Quaternionf + get() = Quaternionf(0.0f, 0.0f, 0.0f, 1.0f) - @JvmStatic - fun fromXYZDegrees(vector3f: Vector3f): Quaternionf { - return fromXYZ(Math.toRadians(vector3f.x().toDouble()).toFloat(), Math.toRadians(vector3f.y().toDouble()).toFloat(), Math.toRadians(vector3f.z().toDouble()).toFloat()) - } + @JvmStatic + fun fromXYZDegrees(vector3f: Vector3f): Quaternionf { + return fromXYZ( + Math.toRadians(vector3f.x().toDouble()).toFloat(), + Math.toRadians(vector3f.y().toDouble()).toFloat(), + Math.toRadians(vector3f.z().toDouble()).toFloat() + ) + } - @JvmStatic - fun fromXYZ(vector3f: Vector3f): Quaternionf { - return fromXYZ(vector3f.x(), vector3f.y(), vector3f.z()) - } + @JvmStatic + fun fromXYZ(vector3f: Vector3f): Quaternionf { + return fromXYZ(vector3f.x(), vector3f.y(), vector3f.z()) + } - @JvmStatic - fun fromXYZ(f: Float, g: Float, h: Float): Quaternionf { - val quaternion = ONE - quaternion.mul(Quaternionf(sin((f / 2.0f)), 0.0f, 0.0f, cos((f / 2.0f)))) - quaternion.mul(Quaternionf(0.0f, sin((g / 2.0f)), 0.0f, cos((g / 2.0f)))) - quaternion.mul(Quaternionf(0.0f, 0.0f, sin((h / 2.0f)), cos((h / 2.0f)))) - return quaternion - } -} \ No newline at end of file + @JvmStatic + fun fromXYZ(f: Float, g: Float, h: Float): Quaternionf { + val quaternion = ONE + quaternion.mul(Quaternionf(sin((f / 2.0f)), 0.0f, 0.0f, cos((f / 2.0f)))) + quaternion.mul(Quaternionf(0.0f, sin((g / 2.0f)), 0.0f, cos((g / 2.0f)))) + quaternion.mul(Quaternionf(0.0f, 0.0f, sin((h / 2.0f)), cos((h / 2.0f)))) + return quaternion + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/utils/MediaHelper.kt b/Common/src/main/java/at/petrak/hexcasting/api/utils/MediaHelper.kt index c237ac52be..6f01f11ef8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/utils/MediaHelper.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/utils/MediaHelper.kt @@ -5,107 +5,107 @@ package at.petrak.hexcasting.api.utils import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.addldata.ADMediaHolder import at.petrak.hexcasting.xplat.IXplatAbstractions +import kotlin.math.roundToInt import net.minecraft.server.level.ServerPlayer import net.minecraft.util.Mth import net.minecraft.world.item.ItemStack -import kotlin.math.roundToInt fun isMediaItem(stack: ItemStack): Boolean { - val mediaHolder = IXplatAbstractions.INSTANCE.findMediaHolder(stack) ?: return false - if (!mediaHolder.canProvide()) - return false - return mediaHolder.withdrawMedia(-1, true) > 0 + val mediaHolder = IXplatAbstractions.INSTANCE.findMediaHolder(stack) ?: return false + if (!mediaHolder.canProvide()) return false + return mediaHolder.withdrawMedia(-1, true) > 0 } /** - * Extract [cost] media from [stack]. If [cost] is less than zero, extract all media instead. - * This may mutate [stack] (and may consume it) unless [simulate] is set. + * Extract [cost] media from [stack]. If [cost] is less than zero, extract all media instead. This + * may mutate [stack] (and may consume it) unless [simulate] is set. * - * If [drainForBatteries] is true, this will only consider forms of media that can be used to make new batteries. + * If [drainForBatteries] is true, this will only consider forms of media that can be used to make + * new batteries. * * Return the amount of media extracted. This may be over [cost] if media is wasted. */ @JvmOverloads fun extractMedia( - stack: ItemStack, - cost: Long = -1, - drainForBatteries: Boolean = false, - simulate: Boolean = false + stack: ItemStack, + cost: Long = -1, + drainForBatteries: Boolean = false, + simulate: Boolean = false ): Long { - val mediaHolder = IXplatAbstractions.INSTANCE.findMediaHolder(stack) ?: return 0 + val mediaHolder = IXplatAbstractions.INSTANCE.findMediaHolder(stack) ?: return 0 - return extractMedia(mediaHolder, cost, drainForBatteries, simulate) + return extractMedia(mediaHolder, cost, drainForBatteries, simulate) } /** - * Extract [cost] media from [holder]. If [cost] is less than zero, extract all media instead. - * This may mutate the stack underlying [holder] (and may consume it) unless [simulate] is set. + * Extract [cost] media from [holder]. If [cost] is less than zero, extract all media instead. This + * may mutate the stack underlying [holder] (and may consume it) unless [simulate] is set. * - * If [drainForBatteries] is true, this will only consider forms of media that can be used to make new batteries. + * If [drainForBatteries] is true, this will only consider forms of media that can be used to make + * new batteries. * * Return the amount of media extracted. This may be over [cost] if media is wasted. */ fun extractMedia( - holder: ADMediaHolder, - cost: Long = -1, - drainForBatteries: Boolean = false, - simulate: Boolean = false + holder: ADMediaHolder, + cost: Long = -1, + drainForBatteries: Boolean = false, + simulate: Boolean = false ): Long { - if (drainForBatteries && !holder.canConstructBattery()) - return 0 + if (drainForBatteries && !holder.canConstructBattery()) return 0 - return holder.withdrawMedia(cost, simulate) + return holder.withdrawMedia(cost, simulate) } /** - * Convenience function to scan the player's inventory, curios, etc for media sources, - * and then sorts them + * Convenience function to scan the player's inventory, curios, etc for media sources, and then + * sorts them */ fun scanPlayerForMediaStuff(player: ServerPlayer): List<ADMediaHolder> { - val sources = mutableListOf<ADMediaHolder>() + val sources = mutableListOf<ADMediaHolder>() - (player.inventory.items + player.inventory.armor + player.inventory.offhand).forEach { - val holder = HexAPI.instance().findMediaHolder(it) - if (holder?.canProvide() == true) { - sources.add(holder) - } - } + (player.inventory.items + player.inventory.armor + player.inventory.offhand).forEach { + val holder = HexAPI.instance().findMediaHolder(it) + if (holder?.canProvide() == true) { + sources.add(holder) + } + } - sources.sortWith(::compareMediaItem) - sources.reverse() - return sources + sources.sortWith(::compareMediaItem) + sources.reverse() + return sources } -/** - * Sorted from least important to most important - */ +/** Sorted from least important to most important */ fun compareMediaItem(aMedia: ADMediaHolder, bMedia: ADMediaHolder): Int { - val priority = aMedia.consumptionPriority - bMedia.consumptionPriority - if (priority != 0) - return priority + val priority = aMedia.consumptionPriority - bMedia.consumptionPriority + if (priority != 0) return priority - return (aMedia.withdrawMedia(-1, true) - bMedia.withdrawMedia(-1, true)) - .coerceIn(Int.MIN_VALUE.toLong(), Int.MAX_VALUE.toLong()).toInt() + return (aMedia.withdrawMedia(-1, true) - bMedia.withdrawMedia(-1, true)) + .coerceIn(Int.MIN_VALUE.toLong(), Int.MAX_VALUE.toLong()) + .toInt() } fun mediaBarColor(media: Long, maxMedia: Long): Int { - val amt = if (maxMedia == 0L) { - 0f - } else { - media.toFloat() / maxMedia.toFloat() - } + val amt = + if (maxMedia == 0L) { + 0f + } else { + media.toFloat() / maxMedia.toFloat() + } - val r = Mth.lerp(amt, 84f, 254f) - val g = Mth.lerp(amt, 57f, 203f) - val b = Mth.lerp(amt, 138f, 230f) - return Mth.color(r / 255f, g / 255f, b / 255f) + val r = Mth.lerp(amt, 84f, 254f) + val g = Mth.lerp(amt, 57f, 203f) + val b = Mth.lerp(amt, 138f, 230f) + return Mth.color(r / 255f, g / 255f, b / 255f) } fun mediaBarWidth(media: Long, maxMedia: Long): Int { - val amt = if (maxMedia == 0L) { - 0f - } else { - media.toFloat() / maxMedia.toFloat() - } - return (13f * amt).roundToInt() + val amt = + if (maxMedia == 0L) { + 0f + } else { + media.toFloat() / maxMedia.toFloat() + } + return (13f * amt).roundToInt() } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/utils/NBTDsl.kt b/Common/src/main/java/at/petrak/hexcasting/api/utils/NBTDsl.kt index 1c427b4c1e..b9b455d78a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/utils/NBTDsl.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/utils/NBTDsl.kt @@ -6,210 +6,292 @@ import net.minecraft.nbt.* // https://github.com/TeamWizardry/LibrarianLib/blob/9cfb2cf3e35685568942ad41395265a2edc27d30/modules/core/src/main/kotlin/com/teamwizardry/librarianlib/core/util/kotlin/NbtBuilder.kt -@DslMarker -internal annotation class NBTDslMarker +@DslMarker internal annotation class NBTDslMarker @NBTDslMarker object NBTBuilder { - inline operator fun invoke(block: NbtCompoundBuilder.() -> Unit) = compound(block) - inline operator fun invoke(tag: CompoundTag, block: NbtCompoundBuilder.() -> Unit) = use(tag, block) - - inline fun use(tag: CompoundTag, block: NbtCompoundBuilder.() -> Unit): CompoundTag = - NbtCompoundBuilder(tag).apply(block).tag - - inline fun compound(block: NbtCompoundBuilder.() -> Unit): CompoundTag = - NbtCompoundBuilder(CompoundTag()).apply(block).tag - - inline fun list(block: NbtListBuilder.() -> Unit): ListTag = - NbtListBuilder(ListTag()).apply(block).tag - - inline fun list(vararg elements: Tag, block: NbtListBuilder.() -> Unit): ListTag = - NbtListBuilder(ListTag()).also { - it.addAll(elements.toList()) - it.block() - }.tag - - inline fun list(vararg elements: Tag): ListTag = ListTag().also { it.addAll(elements) } - inline fun list(elements: Collection<Tag>): ListTag = ListTag().also { it.addAll(elements) } - inline fun <T> list(elements: Collection<T>, mapper: (T) -> Tag): ListTag = ListTag().also { it.addAll(elements.map(mapper)) } - - inline fun double(value: Number): DoubleTag = DoubleTag.valueOf(value.toDouble()) - inline fun float(value: Number): FloatTag = FloatTag.valueOf(value.toFloat()) - inline fun long(value: Number): LongTag = LongTag.valueOf(value.toLong()) - inline fun int(value: Number): IntTag = IntTag.valueOf(value.toInt()) - inline fun short(value: Number): ShortTag = ShortTag.valueOf(value.toShort()) - inline fun byte(value: Number): ByteTag = ByteTag.valueOf(value.toByte()) - - inline fun string(value: String): StringTag = StringTag.valueOf(value) - - inline fun byteArray(value: Collection<Number>): ByteArrayTag = ByteArrayTag(value.map { it.toByte() }) - inline fun byteArray(vararg value: Int): ByteArrayTag = ByteArrayTag(ByteArray(value.size) { value[it].toByte() }) - inline fun byteArray(vararg value: Byte): ByteArrayTag = ByteArrayTag(value) - inline fun byteArray(): ByteArrayTag = ByteArrayTag(byteArrayOf()) // avoiding overload ambiguity - inline fun longArray(value: Collection<Number>): LongArrayTag = LongArrayTag(value.map { it.toLong() }) - inline fun longArray(vararg value: Int): LongArrayTag = LongArrayTag(LongArray(value.size) { value[it].toLong() }) - inline fun longArray(vararg value: Long): LongArrayTag = LongArrayTag(value) - inline fun longArray(): LongArrayTag = LongArrayTag(longArrayOf()) // avoiding overload ambiguity - inline fun intArray(value: Collection<Number>): IntArrayTag = IntArrayTag(value.map { it.toInt() }) - inline fun intArray(vararg value: Int): IntArrayTag = IntArrayTag(value) + inline operator fun invoke(block: NbtCompoundBuilder.() -> Unit) = compound(block) + + inline operator fun invoke(tag: CompoundTag, block: NbtCompoundBuilder.() -> Unit) = + use(tag, block) + + inline fun use(tag: CompoundTag, block: NbtCompoundBuilder.() -> Unit): CompoundTag = + NbtCompoundBuilder(tag).apply(block).tag + + inline fun compound(block: NbtCompoundBuilder.() -> Unit): CompoundTag = + NbtCompoundBuilder(CompoundTag()).apply(block).tag + + inline fun list(block: NbtListBuilder.() -> Unit): ListTag = + NbtListBuilder(ListTag()).apply(block).tag + + inline fun list(vararg elements: Tag, block: NbtListBuilder.() -> Unit): ListTag = + NbtListBuilder(ListTag()) + .also { + it.addAll(elements.toList()) + it.block() + } + .tag + + inline fun list(vararg elements: Tag): ListTag = ListTag().also { it.addAll(elements) } + + inline fun list(elements: Collection<Tag>): ListTag = ListTag().also { it.addAll(elements) } + + inline fun <T> list(elements: Collection<T>, mapper: (T) -> Tag): ListTag = + ListTag().also { it.addAll(elements.map(mapper)) } + + inline fun double(value: Number): DoubleTag = DoubleTag.valueOf(value.toDouble()) + + inline fun float(value: Number): FloatTag = FloatTag.valueOf(value.toFloat()) + + inline fun long(value: Number): LongTag = LongTag.valueOf(value.toLong()) + + inline fun int(value: Number): IntTag = IntTag.valueOf(value.toInt()) + + inline fun short(value: Number): ShortTag = ShortTag.valueOf(value.toShort()) + + inline fun byte(value: Number): ByteTag = ByteTag.valueOf(value.toByte()) + + inline fun string(value: String): StringTag = StringTag.valueOf(value) + + inline fun byteArray(value: Collection<Number>): ByteArrayTag = + ByteArrayTag(value.map { it.toByte() }) + + inline fun byteArray(vararg value: Int): ByteArrayTag = + ByteArrayTag(ByteArray(value.size) { value[it].toByte() }) + + inline fun byteArray(vararg value: Byte): ByteArrayTag = ByteArrayTag(value) + + inline fun byteArray(): ByteArrayTag = ByteArrayTag(byteArrayOf()) // avoiding overload ambiguity + + inline fun longArray(value: Collection<Number>): LongArrayTag = + LongArrayTag(value.map { it.toLong() }) + + inline fun longArray(vararg value: Int): LongArrayTag = + LongArrayTag(LongArray(value.size) { value[it].toLong() }) + + inline fun longArray(vararg value: Long): LongArrayTag = LongArrayTag(value) + + inline fun longArray(): LongArrayTag = LongArrayTag(longArrayOf()) // avoiding overload ambiguity + + inline fun intArray(value: Collection<Number>): IntArrayTag = + IntArrayTag(value.map { it.toInt() }) + + inline fun intArray(vararg value: Int): IntArrayTag = IntArrayTag(value) } @JvmInline @NBTDslMarker value class NbtCompoundBuilder(val tag: CompoundTag) { - // configuring this tag - - inline operator fun String.remAssign(nbt: Tag) { - tag.put(this, nbt) - } - - inline operator fun String.remAssign(str: String) { - tag.put(this, string(str)) - } - - inline operator fun String.remAssign(num: Int) { - tag.put(this, int(num)) - } - - inline operator fun String.remAssign(num: Long) { - tag.put(this, long(num)) - } - - inline operator fun String.remAssign(num: Double) { - tag.put(this, double(num)) - } - - inline operator fun String.remAssign(num: Float) { - tag.put(this, float(num)) - } - - inline operator fun String.remAssign(bool: Boolean) { - tag.put(this, byte(if (bool) 1 else 0)) - } - - // creating new tags - - inline fun compound(block: NbtCompoundBuilder.() -> Unit): CompoundTag = - NbtCompoundBuilder(CompoundTag()).apply(block).tag - - inline fun list(block: NbtListBuilder.() -> Unit): ListTag = - NbtListBuilder(ListTag()).apply(block).tag - - inline fun list(vararg elements: Tag, block: NbtListBuilder.() -> Unit): ListTag = - NbtListBuilder(ListTag()).also { - it.addAll(elements.toList()) - it.block() - }.tag - - inline fun list(vararg elements: Tag): ListTag = ListTag().also { it.addAll(elements) } - inline fun list(elements: Collection<Tag>): ListTag = ListTag().also { it.addAll(elements) } - inline fun <T> list(elements: Collection<T>, mapper: (T) -> Tag): ListTag = ListTag().also { it.addAll(elements.map(mapper)) } - - inline fun double(value: Number): DoubleTag = DoubleTag.valueOf(value.toDouble()) - inline fun float(value: Number): FloatTag = FloatTag.valueOf(value.toFloat()) - inline fun long(value: Number): LongTag = LongTag.valueOf(value.toLong()) - inline fun int(value: Number): IntTag = IntTag.valueOf(value.toInt()) - inline fun short(value: Number): ShortTag = ShortTag.valueOf(value.toShort()) - inline fun byte(value: Number): ByteTag = ByteTag.valueOf(value.toByte()) - - inline fun string(value: String): StringTag = StringTag.valueOf(value) - - inline fun byteArray(value: Collection<Number>): ByteArrayTag = ByteArrayTag(value.map { it.toByte() }) - inline fun byteArray(vararg value: Int): ByteArrayTag = ByteArrayTag(ByteArray(value.size) { value[it].toByte() }) - inline fun byteArray(vararg value: Byte): ByteArrayTag = ByteArrayTag(value) - inline fun byteArray(): ByteArrayTag = ByteArrayTag(byteArrayOf()) // avoiding overload ambiguity - inline fun longArray(value: Collection<Number>): LongArrayTag = LongArrayTag(value.map { it.toLong() }) - inline fun longArray(vararg value: Int): LongArrayTag = LongArrayTag(LongArray(value.size) { value[it].toLong() }) - inline fun longArray(vararg value: Long): LongArrayTag = LongArrayTag(value) - inline fun longArray(): LongArrayTag = LongArrayTag(longArrayOf()) // avoiding overload ambiguity - inline fun intArray(value: Collection<Number>): IntArrayTag = IntArrayTag(value.map { it.toInt() }) - inline fun intArray(vararg value: Int): IntArrayTag = IntArrayTag(value) + // configuring this tag + + inline operator fun String.remAssign(nbt: Tag) { + tag.put(this, nbt) + } + + inline operator fun String.remAssign(str: String) { + tag.put(this, string(str)) + } + + inline operator fun String.remAssign(num: Int) { + tag.put(this, int(num)) + } + + inline operator fun String.remAssign(num: Long) { + tag.put(this, long(num)) + } + + inline operator fun String.remAssign(num: Double) { + tag.put(this, double(num)) + } + + inline operator fun String.remAssign(num: Float) { + tag.put(this, float(num)) + } + + inline operator fun String.remAssign(bool: Boolean) { + tag.put(this, byte(if (bool) 1 else 0)) + } + + // creating new tags + + inline fun compound(block: NbtCompoundBuilder.() -> Unit): CompoundTag = + NbtCompoundBuilder(CompoundTag()).apply(block).tag + + inline fun list(block: NbtListBuilder.() -> Unit): ListTag = + NbtListBuilder(ListTag()).apply(block).tag + + inline fun list(vararg elements: Tag, block: NbtListBuilder.() -> Unit): ListTag = + NbtListBuilder(ListTag()) + .also { + it.addAll(elements.toList()) + it.block() + } + .tag + + inline fun list(vararg elements: Tag): ListTag = ListTag().also { it.addAll(elements) } + + inline fun list(elements: Collection<Tag>): ListTag = ListTag().also { it.addAll(elements) } + + inline fun <T> list(elements: Collection<T>, mapper: (T) -> Tag): ListTag = + ListTag().also { it.addAll(elements.map(mapper)) } + + inline fun double(value: Number): DoubleTag = DoubleTag.valueOf(value.toDouble()) + + inline fun float(value: Number): FloatTag = FloatTag.valueOf(value.toFloat()) + + inline fun long(value: Number): LongTag = LongTag.valueOf(value.toLong()) + + inline fun int(value: Number): IntTag = IntTag.valueOf(value.toInt()) + + inline fun short(value: Number): ShortTag = ShortTag.valueOf(value.toShort()) + + inline fun byte(value: Number): ByteTag = ByteTag.valueOf(value.toByte()) + + inline fun string(value: String): StringTag = StringTag.valueOf(value) + + inline fun byteArray(value: Collection<Number>): ByteArrayTag = + ByteArrayTag(value.map { it.toByte() }) + + inline fun byteArray(vararg value: Int): ByteArrayTag = + ByteArrayTag(ByteArray(value.size) { value[it].toByte() }) + + inline fun byteArray(vararg value: Byte): ByteArrayTag = ByteArrayTag(value) + + inline fun byteArray(): ByteArrayTag = ByteArrayTag(byteArrayOf()) // avoiding overload ambiguity + + inline fun longArray(value: Collection<Number>): LongArrayTag = + LongArrayTag(value.map { it.toLong() }) + + inline fun longArray(vararg value: Int): LongArrayTag = + LongArrayTag(LongArray(value.size) { value[it].toLong() }) + + inline fun longArray(vararg value: Long): LongArrayTag = LongArrayTag(value) + + inline fun longArray(): LongArrayTag = LongArrayTag(longArrayOf()) // avoiding overload ambiguity + + inline fun intArray(value: Collection<Number>): IntArrayTag = + IntArrayTag(value.map { it.toInt() }) + + inline fun intArray(vararg value: Int): IntArrayTag = IntArrayTag(value) } @JvmInline @NBTDslMarker value class NbtListBuilder(val tag: ListTag) { - // configuring this tag - - /** - * Add the given tag to this list - */ - inline operator fun Tag.unaryPlus() { - tag.add(this) - } - - /** - * Add the given tags to this list - */ - inline operator fun Collection<Tag>.unaryPlus() { - tag.addAll(this) - } - - /** - * Add the given tag to this list. This is explicitly defined for [ListTag] because otherwise there is overload - * ambiguity between the [Tag] and [Collection]<Tag> methods. - */ - inline operator fun ListTag.unaryPlus() { - tag.add(this) - } - - inline fun addAll(nbt: Collection<Tag>) { - this.tag.addAll(nbt) - } - - inline fun add(nbt: Tag) { - this.tag.add(nbt) - } - - // creating new tags - - inline fun compound(block: NbtCompoundBuilder.() -> Unit): CompoundTag = - NbtCompoundBuilder(CompoundTag()).apply(block).tag - - inline fun list(block: NbtListBuilder.() -> Unit): ListTag = - NbtListBuilder(ListTag()).apply(block).tag - - inline fun list(vararg elements: Tag, block: NbtListBuilder.() -> Unit): ListTag = - NbtListBuilder(ListTag()).also { - it.addAll(elements.toList()) - it.block() - }.tag - - inline fun list(vararg elements: Tag): ListTag = ListTag().also { it.addAll(elements) } - inline fun list(elements: Collection<Tag>): ListTag = ListTag().also { it.addAll(elements) } - inline fun <T> list(elements: Collection<T>, mapper: (T) -> Tag): ListTag = ListTag().also { it.addAll(elements.map(mapper)) } - - inline fun double(value: Number): DoubleTag = DoubleTag.valueOf(value.toDouble()) - inline fun float(value: Number): FloatTag = FloatTag.valueOf(value.toFloat()) - inline fun long(value: Number): LongTag = LongTag.valueOf(value.toLong()) - inline fun int(value: Number): IntTag = IntTag.valueOf(value.toInt()) - inline fun short(value: Number): ShortTag = ShortTag.valueOf(value.toShort()) - inline fun byte(value: Number): ByteTag = ByteTag.valueOf(value.toByte()) - - inline fun string(value: String): StringTag = StringTag.valueOf(value) - - inline fun byteArray(value: Collection<Number>): ByteArrayTag = ByteArrayTag(value.map { it.toByte() }) - inline fun byteArray(vararg value: Int): ByteArrayTag = ByteArrayTag(ByteArray(value.size) { value[it].toByte() }) - inline fun byteArray(vararg value: Byte): ByteArrayTag = ByteArrayTag(value) - inline fun byteArray(): ByteArrayTag = ByteArrayTag(byteArrayOf()) // avoiding overload ambiguity - inline fun longArray(value: Collection<Number>): LongArrayTag = LongArrayTag(value.map { it.toLong() }) - inline fun longArray(vararg value: Int): LongArrayTag = LongArrayTag(LongArray(value.size) { value[it].toLong() }) - inline fun longArray(vararg value: Long): LongArrayTag = LongArrayTag(value) - inline fun longArray(): LongArrayTag = LongArrayTag(longArrayOf()) // avoiding overload ambiguity - inline fun intArray(value: Collection<Number>): IntArrayTag = IntArrayTag(value.map { it.toInt() }) - inline fun intArray(vararg value: Int): IntArrayTag = IntArrayTag(value) - - inline fun doubles(vararg value: Int): List<DoubleTag> = value.map { DoubleTag.valueOf(it.toDouble()) } - inline fun doubles(vararg value: Double): List<DoubleTag> = value.map { DoubleTag.valueOf(it) } - inline fun floats(vararg value: Int): List<FloatTag> = value.map { FloatTag.valueOf(it.toFloat()) } - inline fun floats(vararg value: Float): List<FloatTag> = value.map { FloatTag.valueOf(it) } - inline fun longs(vararg value: Int): List<LongTag> = value.map { LongTag.valueOf(it.toLong()) } - inline fun longs(vararg value: Long): List<LongTag> = value.map { LongTag.valueOf(it) } - inline fun ints(vararg value: Int): List<IntTag> = value.map { IntTag.valueOf(it) } - inline fun shorts(vararg value: Int): List<ShortTag> = value.map { ShortTag.valueOf(it.toShort()) } - inline fun shorts(vararg value: Short): List<ShortTag> = value.map { ShortTag.valueOf(it) } - inline fun bytes(vararg value: Int): List<ByteTag> = value.map { ByteTag.valueOf(it.toByte()) } - inline fun bytes(vararg value: Byte): List<ByteTag> = value.map { ByteTag.valueOf(it) } - - fun strings(vararg value: String): List<StringTag> = value.map { StringTag.valueOf(it) } + // configuring this tag + + /** Add the given tag to this list */ + inline operator fun Tag.unaryPlus() { + tag.add(this) + } + + /** Add the given tags to this list */ + inline operator fun Collection<Tag>.unaryPlus() { + tag.addAll(this) + } + + /** + * Add the given tag to this list. This is explicitly defined for [ListTag] because otherwise + * there is overload ambiguity between the [Tag] and [Collection]<Tag> methods. + */ + inline operator fun ListTag.unaryPlus() { + tag.add(this) + } + + inline fun addAll(nbt: Collection<Tag>) { + this.tag.addAll(nbt) + } + + inline fun add(nbt: Tag) { + this.tag.add(nbt) + } + + // creating new tags + + inline fun compound(block: NbtCompoundBuilder.() -> Unit): CompoundTag = + NbtCompoundBuilder(CompoundTag()).apply(block).tag + + inline fun list(block: NbtListBuilder.() -> Unit): ListTag = + NbtListBuilder(ListTag()).apply(block).tag + + inline fun list(vararg elements: Tag, block: NbtListBuilder.() -> Unit): ListTag = + NbtListBuilder(ListTag()) + .also { + it.addAll(elements.toList()) + it.block() + } + .tag + + inline fun list(vararg elements: Tag): ListTag = ListTag().also { it.addAll(elements) } + + inline fun list(elements: Collection<Tag>): ListTag = ListTag().also { it.addAll(elements) } + + inline fun <T> list(elements: Collection<T>, mapper: (T) -> Tag): ListTag = + ListTag().also { it.addAll(elements.map(mapper)) } + + inline fun double(value: Number): DoubleTag = DoubleTag.valueOf(value.toDouble()) + + inline fun float(value: Number): FloatTag = FloatTag.valueOf(value.toFloat()) + + inline fun long(value: Number): LongTag = LongTag.valueOf(value.toLong()) + + inline fun int(value: Number): IntTag = IntTag.valueOf(value.toInt()) + + inline fun short(value: Number): ShortTag = ShortTag.valueOf(value.toShort()) + + inline fun byte(value: Number): ByteTag = ByteTag.valueOf(value.toByte()) + + inline fun string(value: String): StringTag = StringTag.valueOf(value) + + inline fun byteArray(value: Collection<Number>): ByteArrayTag = + ByteArrayTag(value.map { it.toByte() }) + + inline fun byteArray(vararg value: Int): ByteArrayTag = + ByteArrayTag(ByteArray(value.size) { value[it].toByte() }) + + inline fun byteArray(vararg value: Byte): ByteArrayTag = ByteArrayTag(value) + + inline fun byteArray(): ByteArrayTag = ByteArrayTag(byteArrayOf()) // avoiding overload ambiguity + + inline fun longArray(value: Collection<Number>): LongArrayTag = + LongArrayTag(value.map { it.toLong() }) + + inline fun longArray(vararg value: Int): LongArrayTag = + LongArrayTag(LongArray(value.size) { value[it].toLong() }) + + inline fun longArray(vararg value: Long): LongArrayTag = LongArrayTag(value) + + inline fun longArray(): LongArrayTag = LongArrayTag(longArrayOf()) // avoiding overload ambiguity + + inline fun intArray(value: Collection<Number>): IntArrayTag = + IntArrayTag(value.map { it.toInt() }) + + inline fun intArray(vararg value: Int): IntArrayTag = IntArrayTag(value) + + inline fun doubles(vararg value: Int): List<DoubleTag> = + value.map { DoubleTag.valueOf(it.toDouble()) } + + inline fun doubles(vararg value: Double): List<DoubleTag> = value.map { DoubleTag.valueOf(it) } + + inline fun floats(vararg value: Int): List<FloatTag> = + value.map { FloatTag.valueOf(it.toFloat()) } + + inline fun floats(vararg value: Float): List<FloatTag> = value.map { FloatTag.valueOf(it) } + + inline fun longs(vararg value: Int): List<LongTag> = value.map { LongTag.valueOf(it.toLong()) } + + inline fun longs(vararg value: Long): List<LongTag> = value.map { LongTag.valueOf(it) } + + inline fun ints(vararg value: Int): List<IntTag> = value.map { IntTag.valueOf(it) } + + inline fun shorts(vararg value: Int): List<ShortTag> = + value.map { ShortTag.valueOf(it.toShort()) } + + inline fun shorts(vararg value: Short): List<ShortTag> = value.map { ShortTag.valueOf(it) } + + inline fun bytes(vararg value: Int): List<ByteTag> = value.map { ByteTag.valueOf(it.toByte()) } + + inline fun bytes(vararg value: Byte): List<ByteTag> = value.map { ByteTag.valueOf(it) } + + fun strings(vararg value: String): List<StringTag> = value.map { StringTag.valueOf(it) } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/utils/NBTHelper.kt b/Common/src/main/java/at/petrak/hexcasting/api/utils/NBTHelper.kt index ef9a757c01..26268ec254 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/utils/NBTHelper.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/utils/NBTHelper.kt @@ -2,17 +2,24 @@ package at.petrak.hexcasting.api.utils +import java.util.* import net.minecraft.nbt.* import net.minecraft.world.item.ItemStack -import java.util.* - -private inline fun <T : Any, K, E> T?.getIf(key: K, predicate: T?.(K) -> Boolean, get: T.(K) -> E): E? = - getIf(key, predicate, get, null) -private inline fun <T : Any, K, E> T?.getIf(key: K, predicate: T?.(K) -> Boolean, get: T.(K) -> E, default: E): E { - if (this != null && predicate(key)) - return get(key) - return default +private inline fun <T : Any, K, E> T?.getIf( + key: K, + predicate: T?.(K) -> Boolean, + get: T.(K) -> E +): E? = getIf(key, predicate, get, null) + +private inline fun <T : Any, K, E> T?.getIf( + key: K, + predicate: T?.(K) -> Boolean, + get: T.(K) -> E, + default: E +): E { + if (this != null && predicate(key)) return get(key) + return default } // ======================================================================================================== CompoundTag @@ -20,47 +27,77 @@ private inline fun <T : Any, K, E> T?.getIf(key: K, predicate: T?.(K) -> Boolean // Checks for containment fun CompoundTag?.hasNumber(key: String) = contains(key, Tag.TAG_ANY_NUMERIC) + fun CompoundTag?.hasByte(key: String) = contains(key, Tag.TAG_BYTE) + fun CompoundTag?.hasShort(key: String) = contains(key, Tag.TAG_SHORT) + fun CompoundTag?.hasInt(key: String) = contains(key, Tag.TAG_INT) + fun CompoundTag?.hasLong(key: String) = contains(key, Tag.TAG_LONG) + fun CompoundTag?.hasFloat(key: String) = contains(key, Tag.TAG_FLOAT) + fun CompoundTag?.hasDouble(key: String) = contains(key, Tag.TAG_DOUBLE) + fun CompoundTag?.hasLongArray(key: String) = contains(key, Tag.TAG_LONG_ARRAY) + fun CompoundTag?.hasIntArray(key: String) = contains(key, Tag.TAG_INT_ARRAY) + fun CompoundTag?.hasByteArray(key: String) = contains(key, Tag.TAG_BYTE_ARRAY) + fun CompoundTag?.hasCompound(key: String) = contains(key, Tag.TAG_COMPOUND) + fun CompoundTag?.hasString(key: String) = contains(key, Tag.TAG_STRING) + fun CompoundTag?.hasList(key: String) = contains(key, Tag.TAG_LIST) + fun CompoundTag?.hasList(key: String, objType: Int) = hasList(key, objType.toByte()) + fun CompoundTag?.hasList(key: String, objType: Byte): Boolean { - if (!hasList(key)) return false - val lt = get(key) as ListTag - return lt.elementType == objType || lt.elementType == 0.toByte() + if (!hasList(key)) return false + val lt = get(key) as ListTag + return lt.elementType == objType || lt.elementType == 0.toByte() } fun CompoundTag?.hasUUID(key: String) = this != null && hasUUID(key) fun CompoundTag?.contains(key: String, id: Byte) = contains(key, id.toInt()) + fun CompoundTag?.contains(key: String, id: Int) = this != null && contains(key, id) + fun CompoundTag?.contains(key: String) = this != null && contains(key) // Puts fun CompoundTag?.putBoolean(key: String, value: Boolean) = this?.putBoolean(key, value) + fun CompoundTag?.putByte(key: String, value: Byte) = this?.putByte(key, value) + fun CompoundTag?.putShort(key: String, value: Short) = this?.putShort(key, value) + fun CompoundTag?.putInt(key: String, value: Int) = this?.putInt(key, value) + fun CompoundTag?.putLong(key: String, value: Long) = this?.putLong(key, value) + fun CompoundTag?.putFloat(key: String, value: Float) = this?.putFloat(key, value) + fun CompoundTag?.putDouble(key: String, value: Double) = this?.putDouble(key, value) + fun CompoundTag?.putLongArray(key: String, value: LongArray) = this?.putLongArray(key, value) + fun CompoundTag?.putIntArray(key: String, value: IntArray) = this?.putIntArray(key, value) + fun CompoundTag?.putByteArray(key: String, value: ByteArray) = this?.putByteArray(key, value) + fun CompoundTag?.putCompound(key: String, value: CompoundTag) = put(key, value) + fun CompoundTag?.putString(key: String, value: String) = this?.putString(key, value) + fun CompoundTag?.putList(key: String, value: ListTag) = put(key, value) + fun CompoundTag?.putUUID(key: String, value: UUID) = this?.putUUID(key, value) + fun CompoundTag?.put(key: String, value: Tag) = this?.put(key, value) // Remove @@ -71,42 +108,54 @@ fun CompoundTag?.remove(key: String) = this?.remove(key) @JvmOverloads fun CompoundTag?.getBoolean(key: String, defaultExpected: Boolean = false) = - getIf(key, CompoundTag?::hasNumber, CompoundTag::getBoolean, defaultExpected) + getIf(key, CompoundTag?::hasNumber, CompoundTag::getBoolean, defaultExpected) @JvmOverloads fun CompoundTag?.getByte(key: String, defaultExpected: Byte = 0) = - getIf(key, CompoundTag?::hasNumber, CompoundTag::getByte, defaultExpected) + getIf(key, CompoundTag?::hasNumber, CompoundTag::getByte, defaultExpected) @JvmOverloads fun CompoundTag?.getShort(key: String, defaultExpected: Short = 0) = - getIf(key, CompoundTag?::hasNumber, CompoundTag::getShort, defaultExpected) + getIf(key, CompoundTag?::hasNumber, CompoundTag::getShort, defaultExpected) @JvmOverloads fun CompoundTag?.getInt(key: String, defaultExpected: Int = 0) = - getIf(key, CompoundTag?::hasNumber, CompoundTag::getInt, defaultExpected) + getIf(key, CompoundTag?::hasNumber, CompoundTag::getInt, defaultExpected) @JvmOverloads fun CompoundTag?.getLong(key: String, defaultExpected: Long = 0) = - getIf(key, CompoundTag?::hasNumber, CompoundTag::getLong, defaultExpected) + getIf(key, CompoundTag?::hasNumber, CompoundTag::getLong, defaultExpected) @JvmOverloads fun CompoundTag?.getFloat(key: String, defaultExpected: Float = 0f) = - getIf(key, CompoundTag?::hasNumber, CompoundTag::getFloat, defaultExpected) + getIf(key, CompoundTag?::hasNumber, CompoundTag::getFloat, defaultExpected) @JvmOverloads fun CompoundTag?.getDouble(key: String, defaultExpected: Double = 0.0) = - getIf(key, CompoundTag?::hasNumber, CompoundTag::getDouble, defaultExpected) + getIf(key, CompoundTag?::hasNumber, CompoundTag::getDouble, defaultExpected) + +fun CompoundTag?.getLongArray(key: String) = + getIf(key, CompoundTag?::hasLongArray, CompoundTag::getLongArray) + +fun CompoundTag?.getIntArray(key: String) = + getIf(key, CompoundTag?::hasIntArray, CompoundTag::getIntArray) + +fun CompoundTag?.getByteArray(key: String) = + getIf(key, CompoundTag?::hasByteArray, CompoundTag::getByteArray) -fun CompoundTag?.getLongArray(key: String) = getIf(key, CompoundTag?::hasLongArray, CompoundTag::getLongArray) -fun CompoundTag?.getIntArray(key: String) = getIf(key, CompoundTag?::hasIntArray, CompoundTag::getIntArray) -fun CompoundTag?.getByteArray(key: String) = getIf(key, CompoundTag?::hasByteArray, CompoundTag::getByteArray) fun CompoundTag?.getCompound(key: String): CompoundTag? = - getIf(key, CompoundTag?::hasCompound, CompoundTag::getCompound) + getIf(key, CompoundTag?::hasCompound, CompoundTag::getCompound) + +fun CompoundTag?.getString(key: String) = + getIf(key, CompoundTag?::hasString, CompoundTag::getString) -fun CompoundTag?.getString(key: String) = getIf(key, CompoundTag?::hasString, CompoundTag::getString) fun CompoundTag?.getList(key: String, objType: Byte) = getList(key, objType.toInt()) -fun CompoundTag?.getList(key: String, objType: Int) = getIf(key, { hasList(key, objType) }) { getList(it, objType) } + +fun CompoundTag?.getList(key: String, objType: Int) = + getIf(key, { hasList(key, objType) }) { getList(it, objType) } + fun CompoundTag?.getUUID(key: String) = getIf(key, CompoundTag?::hasUUID, CompoundTag::getUUID) + fun CompoundTag?.get(key: String) = getIf(key, CompoundTag?::contains, CompoundTag::get) @JvmSynthetic @@ -115,118 +164,158 @@ fun CompoundTag.getList(key: String, objType: Byte): ListTag = getList(key, objT // Get-or-create -fun CompoundTag.getOrCreateCompound(key: String): CompoundTag = getCompound(key) ?: CompoundTag().also { putCompound(key, it) } +fun CompoundTag.getOrCreateCompound(key: String): CompoundTag = + getCompound(key) ?: CompoundTag().also { putCompound(key, it) } + fun CompoundTag.getOrCreateList(key: String, objType: Byte) = getOrCreateList(key, objType.toInt()) -fun CompoundTag.getOrCreateList(key: String, objType: Int): ListTag = if (hasList(key, objType)) getList(key, objType) else ListTag().also { putList(key, it) } + +fun CompoundTag.getOrCreateList(key: String, objType: Int): ListTag = + if (hasList(key, objType)) getList(key, objType) else ListTag().also { putList(key, it) } // ================================================================================================================ Tag -val Tag.asBoolean get() = asByte == 0.toByte() -val Tag.asByte get() = (this as? NumericTag)?.asByte ?: 0.toByte() -val Tag.asShort get() = (this as? NumericTag)?.asShort ?: 0.toShort() -val Tag.asInt get() = (this as? NumericTag)?.asInt ?: 0 -val Tag.asLong get() = (this as? NumericTag)?.asLong ?: 0L -val Tag.asFloat get() = (this as? NumericTag)?.asFloat ?: 0F -val Tag.asDouble get() = (this as? NumericTag)?.asDouble ?: 0.0 +val Tag.asBoolean + get() = asByte == 0.toByte() +val Tag.asByte + get() = (this as? NumericTag)?.asByte ?: 0.toByte() +val Tag.asShort + get() = (this as? NumericTag)?.asShort ?: 0.toShort() +val Tag.asInt + get() = (this as? NumericTag)?.asInt ?: 0 +val Tag.asLong + get() = (this as? NumericTag)?.asLong ?: 0L +val Tag.asFloat + get() = (this as? NumericTag)?.asFloat ?: 0F +val Tag.asDouble + get() = (this as? NumericTag)?.asDouble ?: 0.0 val Tag.asLongArray: LongArray - get() = when (this) { - is LongArrayTag -> this.asLongArray - is IntArrayTag -> { - val array = this.asIntArray - LongArray(array.size) { array[it].toLong() } - } - is ByteArrayTag -> { - val array = this.asByteArray - LongArray(array.size) { array[it].toLong() } - } - else -> LongArray(0) - } + get() = + when (this) { + is LongArrayTag -> this.asLongArray + is IntArrayTag -> { + val array = this.asIntArray + LongArray(array.size) { array[it].toLong() } + } + is ByteArrayTag -> { + val array = this.asByteArray + LongArray(array.size) { array[it].toLong() } + } + else -> LongArray(0) + } val Tag.asIntArray: IntArray - get() = when (this) { - is IntArrayTag -> this.asIntArray - is LongArrayTag -> { - val array = this.asLongArray - IntArray(array.size) { array[it].toInt() } - } - is ByteArrayTag -> { - val array = this.asByteArray - IntArray(array.size) { array[it].toInt() } - } - else -> IntArray(0) - } + get() = + when (this) { + is IntArrayTag -> this.asIntArray + is LongArrayTag -> { + val array = this.asLongArray + IntArray(array.size) { array[it].toInt() } + } + is ByteArrayTag -> { + val array = this.asByteArray + IntArray(array.size) { array[it].toInt() } + } + else -> IntArray(0) + } val Tag.asByteArray: ByteArray - get() = when (this) { - is ByteArrayTag -> this.asByteArray - is LongArrayTag -> { - val array = this.asLongArray - ByteArray(array.size) { array[it].toByte() } - } - is IntArrayTag -> { - val array = this.asIntArray - ByteArray(array.size) { array[it].toByte() } - } - else -> ByteArray(0) - } - -val Tag.asCompound get() = this as? CompoundTag ?: CompoundTag() + get() = + when (this) { + is ByteArrayTag -> this.asByteArray + is LongArrayTag -> { + val array = this.asLongArray + ByteArray(array.size) { array[it].toByte() } + } + is IntArrayTag -> { + val array = this.asIntArray + ByteArray(array.size) { array[it].toByte() } + } + else -> ByteArray(0) + } + +val Tag.asCompound + get() = this as? CompoundTag ?: CompoundTag() // asString is defined in Tag -val Tag.asList get() = this as? ListTag ?: ListTag() -val Tag.asUUID: UUID get() = if (this is IntArrayTag && this.size == 4) NbtUtils.loadUUID(this) else UUID(0, 0) +val Tag.asList + get() = this as? ListTag ?: ListTag() +val Tag.asUUID: UUID + get() = if (this is IntArrayTag && this.size == 4) NbtUtils.loadUUID(this) else UUID(0, 0) // ========================================================================================================== ItemStack // Checks for containment fun ItemStack.hasNumber(key: String) = tag.hasNumber(key) + fun ItemStack.hasByte(key: String) = tag.hasByte(key) + fun ItemStack.hasShort(key: String) = tag.hasShort(key) + fun ItemStack.hasInt(key: String) = tag.hasInt(key) + fun ItemStack.hasLong(key: String) = tag.hasLong(key) + fun ItemStack.hasFloat(key: String) = tag.hasFloat(key) + fun ItemStack.hasDouble(key: String) = tag.hasDouble(key) + fun ItemStack.hasLongArray(key: String) = tag.hasLongArray(key) + fun ItemStack.hasIntArray(key: String) = tag.hasIntArray(key) + fun ItemStack.hasByteArray(key: String) = tag.hasByteArray(key) + fun ItemStack.hasCompound(key: String) = tag.hasCompound(key) + fun ItemStack.hasString(key: String) = tag.hasString(key) + fun ItemStack.hasList(key: String) = tag.hasList(key) + fun ItemStack.hasList(key: String, objType: Int) = tag.hasList(key, objType) + fun ItemStack.hasList(key: String, objType: Byte) = tag.hasList(key, objType) + fun ItemStack.hasUUID(key: String) = tag.hasUUID(key) -@JvmName("contains") -fun ItemStack.containsTag(key: String) = tag.contains(key) +@JvmName("contains") fun ItemStack.containsTag(key: String) = tag.contains(key) -@JvmName("contains") -fun ItemStack.containsTag(key: String, id: Byte) = tag.contains(key, id) +@JvmName("contains") fun ItemStack.containsTag(key: String, id: Byte) = tag.contains(key, id) -@JvmName("contains") -fun ItemStack.containsTag(key: String, id: Int) = tag.contains(key, id) +@JvmName("contains") fun ItemStack.containsTag(key: String, id: Int) = tag.contains(key, id) // Puts fun ItemStack.putBoolean(key: String, value: Boolean) = orCreateTag.putBoolean(key, value) + fun ItemStack.putByte(key: String, value: Byte) = orCreateTag.putByte(key, value) + fun ItemStack.putShort(key: String, value: Short) = orCreateTag.putShort(key, value) + fun ItemStack.putInt(key: String, value: Int) = orCreateTag.putInt(key, value) + fun ItemStack.putLong(key: String, value: Long) = orCreateTag.putLong(key, value) + fun ItemStack.putFloat(key: String, value: Float) = orCreateTag.putFloat(key, value) + fun ItemStack.putDouble(key: String, value: Double) = orCreateTag.putDouble(key, value) fun ItemStack.putLongArray(key: String, value: LongArray) = orCreateTag.putLongArray(key, value) + fun ItemStack.putIntArray(key: String, value: IntArray) = orCreateTag.putIntArray(key, value) + fun ItemStack.putByteArray(key: String, value: ByteArray) = orCreateTag.putByteArray(key, value) + fun ItemStack.putCompound(key: String, value: CompoundTag) = putTag(key, value) + fun ItemStack.putString(key: String, value: String) = orCreateTag.putString(key, value) + fun ItemStack.putList(key: String, value: ListTag) = putTag(key, value) + fun ItemStack.putUUID(key: String, value: UUID) = orCreateTag.putUUID(key, value) -@JvmName("put") -fun ItemStack.putTag(key: String, value: Tag) = orCreateTag.put(key, value) +@JvmName("put") fun ItemStack.putTag(key: String, value: Tag) = orCreateTag.put(key, value) // Remove @@ -235,7 +324,8 @@ fun ItemStack.remove(key: String) = removeTagKey(key) // Gets @JvmOverloads -fun ItemStack.getBoolean(key: String, defaultExpected: Boolean = false) = tag.getBoolean(key, defaultExpected) +fun ItemStack.getBoolean(key: String, defaultExpected: Boolean = false) = + tag.getBoolean(key, defaultExpected) @JvmOverloads fun ItemStack.getByte(key: String, defaultExpected: Byte = 0) = tag.getByte(key, defaultExpected) @@ -250,24 +340,34 @@ fun ItemStack.getInt(key: String, defaultExpected: Int = 0) = tag.getInt(key, de fun ItemStack.getLong(key: String, defaultExpected: Long = 0) = tag.getLong(key, defaultExpected) @JvmOverloads -fun ItemStack.getFloat(key: String, defaultExpected: Float = 0f) = tag.getFloat(key, defaultExpected) +fun ItemStack.getFloat(key: String, defaultExpected: Float = 0f) = + tag.getFloat(key, defaultExpected) @JvmOverloads -fun ItemStack.getDouble(key: String, defaultExpected: Double = 0.0) = tag.getDouble(key, defaultExpected) +fun ItemStack.getDouble(key: String, defaultExpected: Double = 0.0) = + tag.getDouble(key, defaultExpected) fun ItemStack.getLongArray(key: String) = tag.getLongArray(key) + fun ItemStack.getIntArray(key: String) = tag.getIntArray(key) + fun ItemStack.getByteArray(key: String) = tag.getByteArray(key) + fun ItemStack.getCompound(key: String) = tag.getCompound(key) + fun ItemStack.getString(key: String) = tag.getString(key) + fun ItemStack.getList(key: String, objType: Int) = tag.getList(key, objType) + fun ItemStack.getUUID(key: String) = tag.getUUID(key) -@JvmName("get") -fun ItemStack.getTag(key: String) = tag.get(key) +@JvmName("get") fun ItemStack.getTag(key: String) = tag.get(key) // Get-or-create fun ItemStack.getOrCreateCompound(key: String): CompoundTag = getOrCreateTagElement(key) -fun ItemStack.getOrCreateList(key: String, objType: Byte) = orCreateTag.getOrCreateList(key, objType) + +fun ItemStack.getOrCreateList(key: String, objType: Byte) = + orCreateTag.getOrCreateList(key, objType) + fun ItemStack.getOrCreateList(key: String, objType: Int) = orCreateTag.getOrCreateList(key, objType) diff --git a/Common/src/main/java/at/petrak/hexcasting/client/ClientTickCounter.java b/Common/src/main/java/at/petrak/hexcasting/client/ClientTickCounter.java index e45ba75643..45c67f4786 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/ClientTickCounter.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/ClientTickCounter.java @@ -4,22 +4,22 @@ import net.minecraft.client.Minecraft; public class ClientTickCounter { - public static long ticksInGame = 0L; - public static float partialTicks = 0.0F; + public static long ticksInGame = 0L; + public static float partialTicks = 0.0F; - public static float getTotal() { - return (float) ticksInGame + partialTicks; - } + public static float getTotal() { + return (float) ticksInGame + partialTicks; + } - public static void renderTickStart(float renderTickTime) { - partialTicks = renderTickTime; - } + public static void renderTickStart(float renderTickTime) { + partialTicks = renderTickTime; + } - public static void clientTickEnd() { - if (!Minecraft.getInstance().isPaused()) { - ++ticksInGame; - partialTicks = 0.0F; - GaslightingTracker.postFrameCheckRendered(); - } - } + public static void clientTickEnd() { + if (!Minecraft.getInstance().isPaused()) { + ++ticksInGame; + partialTicks = 0.0F; + GaslightingTracker.postFrameCheckRendered(); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/PatternShapeMatcher.java b/Common/src/main/java/at/petrak/hexcasting/client/PatternShapeMatcher.java index dbe366ceb9..b8867c5aa2 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/PatternShapeMatcher.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/PatternShapeMatcher.java @@ -1,4 +1,3 @@ package at.petrak.hexcasting.client; -public class PatternShapeMatcher { -} +public class PatternShapeMatcher {} diff --git a/Common/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java b/Common/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java index 75658fa63a..cd387da70e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.client; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.item.IotaHolderItem; import at.petrak.hexcasting.api.item.MediaHolderItem; @@ -24,13 +26,14 @@ import at.petrak.hexcasting.common.lib.HexBlocks; import at.petrak.hexcasting.common.lib.HexItems; import at.petrak.hexcasting.xplat.IClientXplatAbstractions; +import java.util.*; +import java.util.function.*; import net.minecraft.client.color.block.BlockColor; import net.minecraft.client.color.item.ItemColor; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.ModelBakery; -import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; @@ -41,246 +44,270 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import org.jetbrains.annotations.NotNull; -import java.util.*; -import java.util.function.*; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class RegisterClientStuff { - public static Map<ResourceLocation, List<BakedModel>> QUENCHED_ALLAY_VARIANTS = new HashMap<>(); - private static final Map<BlockQuenchedAllay, Boolean> QUENCHED_ALLAY_TYPES = Map.of( - HexBlocks.QUENCHED_ALLAY, false, - HexBlocks.QUENCHED_ALLAY_TILES, true, - HexBlocks.QUENCHED_ALLAY_BRICKS, true, - HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL, true); - - public static void init() { - registerSealableDataHolderOverrides(HexItems.FOCUS, - stack -> HexItems.FOCUS.readIotaTag(stack) != null, - ItemFocus::isSealed); - registerSealableDataHolderOverrides(HexItems.SPELLBOOK, - stack -> HexItems.SPELLBOOK.readIotaTag(stack) != null, - ItemSpellbook::isSealed); - registerVariantOverrides(HexItems.FOCUS, HexItems.FOCUS::getVariant); - registerVariantOverrides(HexItems.SPELLBOOK, HexItems.SPELLBOOK::getVariant); - registerVariantOverrides(HexItems.CYPHER, HexItems.CYPHER::getVariant); - registerVariantOverrides(HexItems.TRINKET, HexItems.TRINKET::getVariant); - registerVariantOverrides(HexItems.ARTIFACT, HexItems.ARTIFACT::getVariant); - IClientXplatAbstractions.INSTANCE.registerItemProperty(HexItems.THOUGHT_KNOT, ItemThoughtKnot.WRITTEN_PRED, - (stack, level, holder, holderID) -> { - if (NBTHelper.contains(stack, ItemThoughtKnot.TAG_DATA)) { - return 1; - } else { - return 0; - } - }); - - registerPackagedSpellOverrides(HexItems.CYPHER); - registerPackagedSpellOverrides(HexItems.TRINKET); - registerPackagedSpellOverrides(HexItems.ARTIFACT); - - var x = IClientXplatAbstractions.INSTANCE; - x.registerItemProperty(HexItems.BATTERY, ItemMediaBattery.MEDIA_PREDICATE, - (stack, level, holder, holderID) -> { - var item = (MediaHolderItem) stack.getItem(); - return item.getMediaFullness(stack); - }); - x.registerItemProperty(HexItems.BATTERY, ItemMediaBattery.MAX_MEDIA_PREDICATE, - (stack, level, holder, holderID) -> { - var item = (ItemMediaBattery) stack.getItem(); - var max = item.getMaxMedia(stack); - return 1.049658f * (float) Math.log((float) max / MediaConstants.CRYSTAL_UNIT + 9.06152f) - 2.1436f; - }); - - registerScrollOverrides(HexItems.SCROLL_SMOL); - registerScrollOverrides(HexItems.SCROLL_MEDIUM); - registerScrollOverrides(HexItems.SCROLL_LARGE); - - x.registerItemProperty(HexItems.SLATE, ItemSlate.WRITTEN_PRED, - (stack, level, holder, holderID) -> ItemSlate.hasPattern(stack) ? 1f : 0f); - - registerWandOverrides(HexItems.STAFF_OAK); - registerWandOverrides(HexItems.STAFF_BIRCH); - registerWandOverrides(HexItems.STAFF_SPRUCE); - registerWandOverrides(HexItems.STAFF_JUNGLE); - registerWandOverrides(HexItems.STAFF_DARK_OAK); - registerWandOverrides(HexItems.STAFF_ACACIA); - registerWandOverrides(HexItems.STAFF_EDIFIED); - // purposely skip quenched - registerWandOverrides(HexItems.STAFF_MINDSPLICE); - - registerGaslight4(HexItems.STAFF_QUENCHED); - registerGaslight4(HexBlocks.QUENCHED_ALLAY.asItem()); - registerGaslight4(HexBlocks.QUENCHED_ALLAY_TILES.asItem()); - registerGaslight4(HexBlocks.QUENCHED_ALLAY_BRICKS.asItem()); - registerGaslight4(HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL.asItem()); - registerGaslight4(HexItems.QUENCHED_SHARD); - - x.setRenderLayer(HexBlocks.CONJURED_LIGHT, RenderType.cutout()); - x.setRenderLayer(HexBlocks.CONJURED_BLOCK, RenderType.cutout()); - x.setRenderLayer(HexBlocks.EDIFIED_DOOR, RenderType.cutout()); - x.setRenderLayer(HexBlocks.EDIFIED_TRAPDOOR, RenderType.cutout()); - x.setRenderLayer(HexBlocks.AKASHIC_BOOKSHELF, RenderType.cutout()); - x.setRenderLayer(HexBlocks.SCONCE, RenderType.cutout()); - - x.setRenderLayer(HexBlocks.AMETHYST_EDIFIED_LEAVES, RenderType.cutoutMipped()); - x.setRenderLayer(HexBlocks.AVENTURINE_EDIFIED_LEAVES, RenderType.cutoutMipped()); - x.setRenderLayer(HexBlocks.CITRINE_EDIFIED_LEAVES, RenderType.cutoutMipped()); - - x.setRenderLayer(HexBlocks.AKASHIC_RECORD, RenderType.translucent()); - x.setRenderLayer(HexBlocks.QUENCHED_ALLAY, RenderType.translucent()); - - x.registerEntityRenderer(HexEntities.WALL_SCROLL, WallScrollRenderer::new); - -// for (var tex : new ResourceLocation[]{ -// PatternTooltipComponent.PRISTINE_BG, -// PatternTooltipComponent.ANCIENT_BG, -// PatternTooltipComponent.SLATE_BG -// }) { -// Minecraft.getInstance().getTextureManager().bindForSetup(tex); -// } - - ScryingLensOverlays.addScryingLensStuff(); - } - - private static void registerGaslight4(Item item) { - IClientXplatAbstractions.INSTANCE.registerItemProperty(item, - GaslightingTracker.GASLIGHTING_PRED, (stack, level, holder, holderID) -> - Math.abs(GaslightingTracker.getGaslightingAmount() % 4)); - } - - public static void registerColorProviders(BiConsumer<ItemColor, Item> itemColorRegistry, - BiConsumer<BlockColor, Block> blockColorRegistry) { - itemColorRegistry.accept(makeIotaStorageColorizer(HexItems.FOCUS::getColor), HexItems.FOCUS); - itemColorRegistry.accept(makeIotaStorageColorizer(HexItems.SPELLBOOK::getColor), HexItems.SPELLBOOK); - itemColorRegistry.accept(makeIotaStorageColorizer(HexItems.THOUGHT_KNOT::getColor), HexItems.THOUGHT_KNOT); - - blockColorRegistry.accept((bs, level, pos, idx) -> { - if (!bs.getValue(BlockAkashicBookshelf.HAS_BOOKS) || level == null || pos == null) { - return 0xff_ffffff; - } - var tile = level.getBlockEntity(pos); - if (!(tile instanceof BlockEntityAkashicBookshelf beas)) { - // this gets called for particles for some irritating reason - return 0xff_ffffff; - } - var iotaTag = beas.getIotaTag(); - if (iotaTag == null) { - return 0xff_ffffff; - } - return IotaType.getColor(iotaTag); - }, HexBlocks.AKASHIC_BOOKSHELF); - } - - /** - * Helper function to colorize the layers of an item that stores an iota, in the manner of foci and spellbooks. - * <br> - * 0 = base; 1 = overlay - */ - public static ItemColor makeIotaStorageColorizer(ToIntFunction<ItemStack> getColor) { - return (stack, idx) -> { - if (idx == 1) { - return getColor.applyAsInt(stack); - } - return 0xff_ffffff; - }; - } - - private static void registerSealableDataHolderOverrides(IotaHolderItem item, Predicate<ItemStack> hasIota, - Predicate<ItemStack> isSealed) { - IClientXplatAbstractions.INSTANCE.registerItemProperty((Item) item, ItemFocus.OVERLAY_PRED, - (stack, level, holder, holderID) -> { - if (!hasIota.test(stack) && !NBTHelper.hasString(stack, IotaHolderItem.TAG_OVERRIDE_VISUALLY)) { - return 0; - } - if (!isSealed.test(stack)) { - return 1; - } - return 2; - }); - } - - private static void registerVariantOverrides(VariantItem item, Function<ItemStack, Integer> variant) { - IClientXplatAbstractions.INSTANCE.registerItemProperty((Item) item, ItemFocus.VARIANT_PRED, - (stack, level, holder, holderID) -> variant.apply(stack)); - } - - private static void registerScrollOverrides(ItemScroll scroll) { - IClientXplatAbstractions.INSTANCE.registerItemProperty(scroll, ItemScroll.ANCIENT_PREDICATE, - (stack, level, holder, holderID) -> NBTHelper.hasString(stack, ItemScroll.TAG_OP_ID) ? 1f : 0f); - } - - private static void registerPackagedSpellOverrides(ItemPackagedHex item) { - IClientXplatAbstractions.INSTANCE.registerItemProperty(item, ItemPackagedHex.HAS_PATTERNS_PRED, - (stack, level, holder, holderID) -> - item.hasHex(stack) ? 1f : 0f - ); - } - - private static void registerWandOverrides(ItemStaff item) { - IClientXplatAbstractions.INSTANCE.registerItemProperty(item, ItemStaff.FUNNY_LEVEL_PREDICATE, - (stack, level, holder, holderID) -> { - if (!stack.hasCustomHoverName()) { - return 0; - } - var name = stack.getHoverName().getString().toLowerCase(Locale.ROOT); - if (name.contains("old")) { - return 1f; - } else if (name.contains("cherry")) { - return 2f; - } else { - return 0f; - } - }); - } - - public static void registerBlockEntityRenderers(@NotNull BlockEntityRendererRegisterererer registerer) { - registerer.registerBlockEntityRenderer(HexBlockEntities.SLATE_TILE, BlockEntitySlateRenderer::new); - registerer.registerBlockEntityRenderer(HexBlockEntities.AKASHIC_BOOKSHELF_TILE, - BlockEntityAkashicBookshelfRenderer::new); - registerer.registerBlockEntityRenderer(HexBlockEntities.QUENCHED_ALLAY_TILE, - BlockEntityQuenchedAllayRenderer::new); - registerer.registerBlockEntityRenderer(HexBlockEntities.QUENCHED_ALLAY_TILES_TILE, - BlockEntityQuenchedAllayRenderer::new); - registerer.registerBlockEntityRenderer(HexBlockEntities.QUENCHED_ALLAY_BRICKS_TILE, - BlockEntityQuenchedAllayRenderer::new); - registerer.registerBlockEntityRenderer(HexBlockEntities.QUENCHED_ALLAY_BRICKS_SMALL_TILE, - BlockEntityQuenchedAllayRenderer::new); - } - - @FunctionalInterface - public interface BlockEntityRendererRegisterererer { - <T extends BlockEntity> void registerBlockEntityRenderer(BlockEntityType<T> type, - BlockEntityRendererProvider<? super T> berp); - } - - public static void onModelRegister(ResourceManager recMan, Consumer<ResourceLocation> extraModels) { - for (var type : QUENCHED_ALLAY_TYPES.entrySet()) { - var blockLoc = BuiltInRegistries.BLOCK.getKey(type.getKey()); - var locStart = "block/"; - if (type.getValue()) - locStart += "deco/"; - - for (int i = 0; i < BlockQuenchedAllay.VARIANTS; i++) { - extraModels.accept(modLoc( locStart + blockLoc.getPath() + "_" + i)); - } - } - } - - public static void onModelBake(ModelBakery loader, Map<ResourceLocation, BakedModel> map) { - for (var type : QUENCHED_ALLAY_TYPES.entrySet()) { - var blockLoc = BuiltInRegistries.BLOCK.getKey(type.getKey()); - var locStart = "block/"; - if (type.getValue()) - locStart += "deco/"; - - var list = new ArrayList<BakedModel>(); - for (int i = 0; i < BlockQuenchedAllay.VARIANTS; i++) { - var variantLoc = modLoc(locStart + blockLoc.getPath() + "_" + i); - var model = map.get(variantLoc); - list.add(model); - } - QUENCHED_ALLAY_VARIANTS.put(blockLoc, list); - } - } + public static Map<ResourceLocation, List<BakedModel>> QUENCHED_ALLAY_VARIANTS = new HashMap<>(); + private static final Map<BlockQuenchedAllay, Boolean> QUENCHED_ALLAY_TYPES = + Map.of( + HexBlocks.QUENCHED_ALLAY, false, + HexBlocks.QUENCHED_ALLAY_TILES, true, + HexBlocks.QUENCHED_ALLAY_BRICKS, true, + HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL, true); + + public static void init() { + registerSealableDataHolderOverrides( + HexItems.FOCUS, stack -> HexItems.FOCUS.readIotaTag(stack) != null, ItemFocus::isSealed); + registerSealableDataHolderOverrides( + HexItems.SPELLBOOK, + stack -> HexItems.SPELLBOOK.readIotaTag(stack) != null, + ItemSpellbook::isSealed); + registerVariantOverrides(HexItems.FOCUS, HexItems.FOCUS::getVariant); + registerVariantOverrides(HexItems.SPELLBOOK, HexItems.SPELLBOOK::getVariant); + registerVariantOverrides(HexItems.CYPHER, HexItems.CYPHER::getVariant); + registerVariantOverrides(HexItems.TRINKET, HexItems.TRINKET::getVariant); + registerVariantOverrides(HexItems.ARTIFACT, HexItems.ARTIFACT::getVariant); + IClientXplatAbstractions.INSTANCE.registerItemProperty( + HexItems.THOUGHT_KNOT, + ItemThoughtKnot.WRITTEN_PRED, + (stack, level, holder, holderID) -> { + if (NBTHelper.contains(stack, ItemThoughtKnot.TAG_DATA)) { + return 1; + } else { + return 0; + } + }); + + registerPackagedSpellOverrides(HexItems.CYPHER); + registerPackagedSpellOverrides(HexItems.TRINKET); + registerPackagedSpellOverrides(HexItems.ARTIFACT); + + var x = IClientXplatAbstractions.INSTANCE; + x.registerItemProperty( + HexItems.BATTERY, + ItemMediaBattery.MEDIA_PREDICATE, + (stack, level, holder, holderID) -> { + var item = (MediaHolderItem) stack.getItem(); + return item.getMediaFullness(stack); + }); + x.registerItemProperty( + HexItems.BATTERY, + ItemMediaBattery.MAX_MEDIA_PREDICATE, + (stack, level, holder, holderID) -> { + var item = (ItemMediaBattery) stack.getItem(); + var max = item.getMaxMedia(stack); + return 1.049658f * (float) Math.log((float) max / MediaConstants.CRYSTAL_UNIT + 9.06152f) + - 2.1436f; + }); + + registerScrollOverrides(HexItems.SCROLL_SMOL); + registerScrollOverrides(HexItems.SCROLL_MEDIUM); + registerScrollOverrides(HexItems.SCROLL_LARGE); + + x.registerItemProperty( + HexItems.SLATE, + ItemSlate.WRITTEN_PRED, + (stack, level, holder, holderID) -> ItemSlate.hasPattern(stack) ? 1f : 0f); + + registerWandOverrides(HexItems.STAFF_OAK); + registerWandOverrides(HexItems.STAFF_BIRCH); + registerWandOverrides(HexItems.STAFF_SPRUCE); + registerWandOverrides(HexItems.STAFF_JUNGLE); + registerWandOverrides(HexItems.STAFF_DARK_OAK); + registerWandOverrides(HexItems.STAFF_ACACIA); + registerWandOverrides(HexItems.STAFF_EDIFIED); + // purposely skip quenched + registerWandOverrides(HexItems.STAFF_MINDSPLICE); + + registerGaslight4(HexItems.STAFF_QUENCHED); + registerGaslight4(HexBlocks.QUENCHED_ALLAY.asItem()); + registerGaslight4(HexBlocks.QUENCHED_ALLAY_TILES.asItem()); + registerGaslight4(HexBlocks.QUENCHED_ALLAY_BRICKS.asItem()); + registerGaslight4(HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL.asItem()); + registerGaslight4(HexItems.QUENCHED_SHARD); + + x.setRenderLayer(HexBlocks.CONJURED_LIGHT, RenderType.cutout()); + x.setRenderLayer(HexBlocks.CONJURED_BLOCK, RenderType.cutout()); + x.setRenderLayer(HexBlocks.EDIFIED_DOOR, RenderType.cutout()); + x.setRenderLayer(HexBlocks.EDIFIED_TRAPDOOR, RenderType.cutout()); + x.setRenderLayer(HexBlocks.AKASHIC_BOOKSHELF, RenderType.cutout()); + x.setRenderLayer(HexBlocks.SCONCE, RenderType.cutout()); + + x.setRenderLayer(HexBlocks.AMETHYST_EDIFIED_LEAVES, RenderType.cutoutMipped()); + x.setRenderLayer(HexBlocks.AVENTURINE_EDIFIED_LEAVES, RenderType.cutoutMipped()); + x.setRenderLayer(HexBlocks.CITRINE_EDIFIED_LEAVES, RenderType.cutoutMipped()); + + x.setRenderLayer(HexBlocks.AKASHIC_RECORD, RenderType.translucent()); + x.setRenderLayer(HexBlocks.QUENCHED_ALLAY, RenderType.translucent()); + + x.registerEntityRenderer(HexEntities.WALL_SCROLL, WallScrollRenderer::new); + + // for (var tex : new ResourceLocation[]{ + // PatternTooltipComponent.PRISTINE_BG, + // PatternTooltipComponent.ANCIENT_BG, + // PatternTooltipComponent.SLATE_BG + // }) { + // Minecraft.getInstance().getTextureManager().bindForSetup(tex); + // } + + ScryingLensOverlays.addScryingLensStuff(); + } + + private static void registerGaslight4(Item item) { + IClientXplatAbstractions.INSTANCE.registerItemProperty( + item, + GaslightingTracker.GASLIGHTING_PRED, + (stack, level, holder, holderID) -> + Math.abs(GaslightingTracker.getGaslightingAmount() % 4)); + } + + public static void registerColorProviders( + BiConsumer<ItemColor, Item> itemColorRegistry, + BiConsumer<BlockColor, Block> blockColorRegistry) { + itemColorRegistry.accept(makeIotaStorageColorizer(HexItems.FOCUS::getColor), HexItems.FOCUS); + itemColorRegistry.accept( + makeIotaStorageColorizer(HexItems.SPELLBOOK::getColor), HexItems.SPELLBOOK); + itemColorRegistry.accept( + makeIotaStorageColorizer(HexItems.THOUGHT_KNOT::getColor), HexItems.THOUGHT_KNOT); + + blockColorRegistry.accept( + (bs, level, pos, idx) -> { + if (!bs.getValue(BlockAkashicBookshelf.HAS_BOOKS) || level == null || pos == null) { + return 0xff_ffffff; + } + var tile = level.getBlockEntity(pos); + if (!(tile instanceof BlockEntityAkashicBookshelf beas)) { + // this gets called for particles for some irritating reason + return 0xff_ffffff; + } + var iotaTag = beas.getIotaTag(); + if (iotaTag == null) { + return 0xff_ffffff; + } + return IotaType.getColor(iotaTag); + }, + HexBlocks.AKASHIC_BOOKSHELF); + } + + /** + * Helper function to colorize the layers of an item that stores an iota, in the manner of foci + * and spellbooks. <br> + * 0 = base; 1 = overlay + */ + public static ItemColor makeIotaStorageColorizer(ToIntFunction<ItemStack> getColor) { + return (stack, idx) -> { + if (idx == 1) { + return getColor.applyAsInt(stack); + } + return 0xff_ffffff; + }; + } + + private static void registerSealableDataHolderOverrides( + IotaHolderItem item, Predicate<ItemStack> hasIota, Predicate<ItemStack> isSealed) { + IClientXplatAbstractions.INSTANCE.registerItemProperty( + (Item) item, + ItemFocus.OVERLAY_PRED, + (stack, level, holder, holderID) -> { + if (!hasIota.test(stack) + && !NBTHelper.hasString(stack, IotaHolderItem.TAG_OVERRIDE_VISUALLY)) { + return 0; + } + if (!isSealed.test(stack)) { + return 1; + } + return 2; + }); + } + + private static void registerVariantOverrides( + VariantItem item, Function<ItemStack, Integer> variant) { + IClientXplatAbstractions.INSTANCE.registerItemProperty( + (Item) item, + ItemFocus.VARIANT_PRED, + (stack, level, holder, holderID) -> variant.apply(stack)); + } + + private static void registerScrollOverrides(ItemScroll scroll) { + IClientXplatAbstractions.INSTANCE.registerItemProperty( + scroll, + ItemScroll.ANCIENT_PREDICATE, + (stack, level, holder, holderID) -> + NBTHelper.hasString(stack, ItemScroll.TAG_OP_ID) ? 1f : 0f); + } + + private static void registerPackagedSpellOverrides(ItemPackagedHex item) { + IClientXplatAbstractions.INSTANCE.registerItemProperty( + item, + ItemPackagedHex.HAS_PATTERNS_PRED, + (stack, level, holder, holderID) -> item.hasHex(stack) ? 1f : 0f); + } + + private static void registerWandOverrides(ItemStaff item) { + IClientXplatAbstractions.INSTANCE.registerItemProperty( + item, + ItemStaff.FUNNY_LEVEL_PREDICATE, + (stack, level, holder, holderID) -> { + if (!stack.hasCustomHoverName()) { + return 0; + } + var name = stack.getHoverName().getString().toLowerCase(Locale.ROOT); + if (name.contains("old")) { + return 1f; + } else if (name.contains("cherry")) { + return 2f; + } else { + return 0f; + } + }); + } + + public static void registerBlockEntityRenderers( + @NotNull BlockEntityRendererRegisterererer registerer) { + registerer.registerBlockEntityRenderer( + HexBlockEntities.SLATE_TILE, BlockEntitySlateRenderer::new); + registerer.registerBlockEntityRenderer( + HexBlockEntities.AKASHIC_BOOKSHELF_TILE, BlockEntityAkashicBookshelfRenderer::new); + registerer.registerBlockEntityRenderer( + HexBlockEntities.QUENCHED_ALLAY_TILE, BlockEntityQuenchedAllayRenderer::new); + registerer.registerBlockEntityRenderer( + HexBlockEntities.QUENCHED_ALLAY_TILES_TILE, BlockEntityQuenchedAllayRenderer::new); + registerer.registerBlockEntityRenderer( + HexBlockEntities.QUENCHED_ALLAY_BRICKS_TILE, BlockEntityQuenchedAllayRenderer::new); + registerer.registerBlockEntityRenderer( + HexBlockEntities.QUENCHED_ALLAY_BRICKS_SMALL_TILE, BlockEntityQuenchedAllayRenderer::new); + } + + @FunctionalInterface + public interface BlockEntityRendererRegisterererer { + <T extends BlockEntity> void registerBlockEntityRenderer( + BlockEntityType<T> type, BlockEntityRendererProvider<? super T> berp); + } + + public static void onModelRegister( + ResourceManager recMan, Consumer<ResourceLocation> extraModels) { + for (var type : QUENCHED_ALLAY_TYPES.entrySet()) { + var blockLoc = BuiltInRegistries.BLOCK.getKey(type.getKey()); + var locStart = "block/"; + if (type.getValue()) locStart += "deco/"; + + for (int i = 0; i < BlockQuenchedAllay.VARIANTS; i++) { + extraModels.accept(modLoc(locStart + blockLoc.getPath() + "_" + i)); + } + } + } + + public static void onModelBake(ModelBakery loader, Map<ResourceLocation, BakedModel> map) { + for (var type : QUENCHED_ALLAY_TYPES.entrySet()) { + var blockLoc = BuiltInRegistries.BLOCK.getKey(type.getKey()); + var locStart = "block/"; + if (type.getValue()) locStart += "deco/"; + + var list = new ArrayList<BakedModel>(); + for (int i = 0; i < BlockQuenchedAllay.VARIANTS; i++) { + var variantLoc = modLoc(locStart + blockLoc.getPath() + "_" + i); + var model = map.get(variantLoc); + list.add(model); + } + QUENCHED_ALLAY_VARIANTS.put(blockLoc, list); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/ShiftScrollListener.java b/Common/src/main/java/at/petrak/hexcasting/client/ShiftScrollListener.java index c6073517cc..5c22ffeefb 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/ShiftScrollListener.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/ShiftScrollListener.java @@ -9,51 +9,54 @@ import net.minecraft.world.item.Item; public class ShiftScrollListener { - private static double mainHandDelta = 0; - private static double offHandDelta = 0; - - public static boolean onScrollInGameplay(double delta) { - if (Minecraft.getInstance().screen != null) { - return false; - } - - return onScroll(delta, true); - } - - public static boolean onScroll(double delta, boolean needsSneaking) { - LocalPlayer player = Minecraft.getInstance().player; - // not .isCrouching! that fails for players who are not on the ground - // yes, this does work if you remap your sneak key - if (player != null && (player.isShiftKeyDown() || !needsSneaking)) { - // Spectators shouldn't interact with items! - if (player.isSpectator()) { - return false; - } - - if (IsScrollableItem(player.getMainHandItem().getItem())) { - mainHandDelta += delta; - return true; - } else if (IsScrollableItem(player.getOffhandItem().getItem())) { - offHandDelta += delta; - return true; - } - } - - return false; - } - - public static void clientTickEnd() { - if (mainHandDelta != 0 || offHandDelta != 0) { - IClientXplatAbstractions.INSTANCE.sendPacketToServer( - new MsgShiftScrollC2S(mainHandDelta, offHandDelta, Minecraft.getInstance().options.keySprint.isDown(), - HexConfig.client().invertSpellbookScrollDirection(), - HexConfig.client().invertAbacusScrollDirection())); - mainHandDelta = 0; - offHandDelta = 0; - } - } - - private static boolean IsScrollableItem(Item item) { - return item == HexItems.SPELLBOOK || item == HexItems.ABACUS; - } + private static double mainHandDelta = 0; + private static double offHandDelta = 0; + + public static boolean onScrollInGameplay(double delta) { + if (Minecraft.getInstance().screen != null) { + return false; + } + + return onScroll(delta, true); + } + + public static boolean onScroll(double delta, boolean needsSneaking) { + LocalPlayer player = Minecraft.getInstance().player; + // not .isCrouching! that fails for players who are not on the ground + // yes, this does work if you remap your sneak key + if (player != null && (player.isShiftKeyDown() || !needsSneaking)) { + // Spectators shouldn't interact with items! + if (player.isSpectator()) { + return false; + } + + if (IsScrollableItem(player.getMainHandItem().getItem())) { + mainHandDelta += delta; + return true; + } else if (IsScrollableItem(player.getOffhandItem().getItem())) { + offHandDelta += delta; + return true; + } + } + + return false; + } + + public static void clientTickEnd() { + if (mainHandDelta != 0 || offHandDelta != 0) { + IClientXplatAbstractions.INSTANCE.sendPacketToServer( + new MsgShiftScrollC2S( + mainHandDelta, + offHandDelta, + Minecraft.getInstance().options.keySprint.isDown(), + HexConfig.client().invertSpellbookScrollDirection(), + HexConfig.client().invertAbacusScrollDirection())); + mainHandDelta = 0; + offHandDelta = 0; + } + } + + private static boolean IsScrollableItem(Item item) { + return item == HexItems.SPELLBOOK || item == HexItems.ABACUS; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/entity/WallScrollRenderer.java b/Common/src/main/java/at/petrak/hexcasting/client/entity/WallScrollRenderer.java index d17e617cd9..fdb7bfc863 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/entity/WallScrollRenderer.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/entity/WallScrollRenderer.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.client.entity; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.client.render.WorldlyPatternRenderHelpers; import at.petrak.hexcasting.common.entities.EntityWallScroll; import com.mojang.blaze3d.systems.RenderSystem; @@ -17,120 +19,149 @@ import org.joml.Matrix3f; import org.joml.Matrix4f; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class WallScrollRenderer extends EntityRenderer<EntityWallScroll> { - private static final ResourceLocation PRISTINE_BG_LARGE = modLoc("textures/entity/scroll_large.png"); - private static final ResourceLocation PRISTINE_BG_MEDIUM = modLoc("textures/entity/scroll_medium.png"); - private static final ResourceLocation PRISTINE_BG_SMOL = modLoc("textures/block/scroll_paper.png"); - private static final ResourceLocation ANCIENT_BG_LARGE = modLoc("textures/entity/scroll_ancient_large.png"); - private static final ResourceLocation ANCIENT_BG_MEDIUM = modLoc("textures/entity/scroll_ancient_medium.png"); - private static final ResourceLocation ANCIENT_BG_SMOL = modLoc("textures/block/ancient_scroll_paper.png"); - - public WallScrollRenderer(EntityRendererProvider.Context p_174008_) { - super(p_174008_); - } - - // I do as the PaintingRenderer guides - @Override - public void render(EntityWallScroll wallScroll, float yaw, float partialTicks, PoseStack ps, - MultiBufferSource bufSource, int packedLight) { - - RenderSystem.setShader(GameRenderer::getPositionTexShader); - - ps.pushPose(); - - ps.mulPose(Axis.YP.rotationDegrees(180f - yaw)); - ps.mulPose(Axis.ZP.rotationDegrees(180f)); - - int light = LevelRenderer.getLightColor(wallScroll.level(), wallScroll.getPos()); - - { - ps.pushPose(); - // X is right, Y is down, Z is *in* - // Our origin will be the lower-left corner of the scroll touching the wall - // (so it has "negative" thickness) - ps.translate(-wallScroll.blockSize / 2f, -wallScroll.blockSize / 2f, 1f / 32f); - - float dx = wallScroll.blockSize, dy = wallScroll.blockSize, dz = -1f / 16f; - float margin = 1f / 48f; - var last = ps.last(); - var mat = last.pose(); - var norm = last.normal(); - - RenderType layer = RenderType.entityCutout(this.getTextureLocation(wallScroll)); - - var verts = bufSource.getBuffer(layer); - // Remember: CCW - // Front face - vertex(mat, norm, light, verts, 0, 0, dz, 0, 0, 0, 0, -1); - vertex(mat, norm, light, verts, 0, dy, dz, 0, 1, 0, 0, -1); - vertex(mat, norm, light, verts, dx, dy, dz, 1, 1, 0, 0, -1); - vertex(mat, norm, light, verts, dx, 0, dz, 1, 0, 0, 0, -1); - // Back face - vertex(mat, norm, light, verts, 0, 0, 0, 0, 0, 0, 0, 1); - vertex(mat, norm, light, verts, dx, 0, 0, 1, 0, 0, 0, 1); - vertex(mat, norm, light, verts, dx, dy, 0, 1, 1, 0, 0, 1); - vertex(mat, norm, light, verts, 0, dy, 0, 0, 1, 0, 0, 1); - // Top face - vertex(mat, norm, light, verts, 0, 0, 0, 0, 0, 0, -1, 0); - vertex(mat, norm, light, verts, 0, 0, dz, 0, margin, 0, -1, 0); - vertex(mat, norm, light, verts, dx, 0, dz, 1, margin, 0, -1, 0); - vertex(mat, norm, light, verts, dx, 0, 0, 1, 0, 0, -1, 0); - // Left face - vertex(mat, norm, light, verts, 0, 0, 0, 0, 0, -1, 0, 0); - vertex(mat, norm, light, verts, 0, dy, 0, 0, 1, -1, 0, 0); - vertex(mat, norm, light, verts, 0, dy, dz, margin, 1, -1, 0, 0); - vertex(mat, norm, light, verts, 0, 0, dz, margin, 0, -1, 0, 0); - // Right face - vertex(mat, norm, light, verts, dx, 0, dz, 1 - margin, 0, 1, 0, 0); - vertex(mat, norm, light, verts, dx, dy, dz, 1 - margin, 1, 1, 0, 0); - vertex(mat, norm, light, verts, dx, dy, 0, 1, 1, 1, 0, 0); - vertex(mat, norm, light, verts, dx, 0, 0, 1, 0, 1, 0, 0); - // Bottom face - vertex(mat, norm, light, verts, 0, dy, dz, 0, 1 - margin, 0, 1, 0); - vertex(mat, norm, light, verts, 0, dy, 0, 0, 1, 0, 1, 0); - vertex(mat, norm, light, verts, dx, dy, 0, 1, 1, 0, 1, 0); - vertex(mat, norm, light, verts, dx, dy, dz, 1, 1 - margin, 0, 1, 0); - - ps.popPose(); - - if(wallScroll.pattern != null) - WorldlyPatternRenderHelpers.renderPatternForScroll(wallScroll.pattern, wallScroll, ps, bufSource, light, wallScroll.blockSize, wallScroll.getShowsStrokeOrder()); - } - - ps.popPose(); - super.render(wallScroll, yaw, partialTicks, ps, bufSource, packedLight); - } - - @Override - public ResourceLocation getTextureLocation(EntityWallScroll wallScroll) { - if (wallScroll.isAncient) { - if (wallScroll.blockSize <= 1) { - return ANCIENT_BG_SMOL; - } else if (wallScroll.blockSize == 2) { - return ANCIENT_BG_MEDIUM; - } else { - return ANCIENT_BG_LARGE; - } - } else { - if (wallScroll.blockSize <= 1) { - return PRISTINE_BG_SMOL; - } else if (wallScroll.blockSize == 2) { - return PRISTINE_BG_MEDIUM; - } else { - return PRISTINE_BG_LARGE; - } - } - } - - private static void vertex(Matrix4f mat, Matrix3f normal, int light, VertexConsumer verts, float x, float y, - float z, float u, - float v, float nx, float ny, float nz) { - verts.vertex(mat, x, y, z) - .color(0xffffffff) - .uv(u, v).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(light) - .normal(normal, nx, ny, nz) - .endVertex(); - } + private static final ResourceLocation PRISTINE_BG_LARGE = + modLoc("textures/entity/scroll_large.png"); + private static final ResourceLocation PRISTINE_BG_MEDIUM = + modLoc("textures/entity/scroll_medium.png"); + private static final ResourceLocation PRISTINE_BG_SMOL = + modLoc("textures/block/scroll_paper.png"); + private static final ResourceLocation ANCIENT_BG_LARGE = + modLoc("textures/entity/scroll_ancient_large.png"); + private static final ResourceLocation ANCIENT_BG_MEDIUM = + modLoc("textures/entity/scroll_ancient_medium.png"); + private static final ResourceLocation ANCIENT_BG_SMOL = + modLoc("textures/block/ancient_scroll_paper.png"); + + public WallScrollRenderer(EntityRendererProvider.Context p_174008_) { + super(p_174008_); + } + + // I do as the PaintingRenderer guides + @Override + public void render( + EntityWallScroll wallScroll, + float yaw, + float partialTicks, + PoseStack ps, + MultiBufferSource bufSource, + int packedLight) { + + RenderSystem.setShader(GameRenderer::getPositionTexShader); + + ps.pushPose(); + + ps.mulPose(Axis.YP.rotationDegrees(180f - yaw)); + ps.mulPose(Axis.ZP.rotationDegrees(180f)); + + int light = LevelRenderer.getLightColor(wallScroll.level(), wallScroll.getPos()); + + { + ps.pushPose(); + // X is right, Y is down, Z is *in* + // Our origin will be the lower-left corner of the scroll touching the wall + // (so it has "negative" thickness) + ps.translate(-wallScroll.blockSize / 2f, -wallScroll.blockSize / 2f, 1f / 32f); + + float dx = wallScroll.blockSize, dy = wallScroll.blockSize, dz = -1f / 16f; + float margin = 1f / 48f; + var last = ps.last(); + var mat = last.pose(); + var norm = last.normal(); + + RenderType layer = RenderType.entityCutout(this.getTextureLocation(wallScroll)); + + var verts = bufSource.getBuffer(layer); + // Remember: CCW + // Front face + vertex(mat, norm, light, verts, 0, 0, dz, 0, 0, 0, 0, -1); + vertex(mat, norm, light, verts, 0, dy, dz, 0, 1, 0, 0, -1); + vertex(mat, norm, light, verts, dx, dy, dz, 1, 1, 0, 0, -1); + vertex(mat, norm, light, verts, dx, 0, dz, 1, 0, 0, 0, -1); + // Back face + vertex(mat, norm, light, verts, 0, 0, 0, 0, 0, 0, 0, 1); + vertex(mat, norm, light, verts, dx, 0, 0, 1, 0, 0, 0, 1); + vertex(mat, norm, light, verts, dx, dy, 0, 1, 1, 0, 0, 1); + vertex(mat, norm, light, verts, 0, dy, 0, 0, 1, 0, 0, 1); + // Top face + vertex(mat, norm, light, verts, 0, 0, 0, 0, 0, 0, -1, 0); + vertex(mat, norm, light, verts, 0, 0, dz, 0, margin, 0, -1, 0); + vertex(mat, norm, light, verts, dx, 0, dz, 1, margin, 0, -1, 0); + vertex(mat, norm, light, verts, dx, 0, 0, 1, 0, 0, -1, 0); + // Left face + vertex(mat, norm, light, verts, 0, 0, 0, 0, 0, -1, 0, 0); + vertex(mat, norm, light, verts, 0, dy, 0, 0, 1, -1, 0, 0); + vertex(mat, norm, light, verts, 0, dy, dz, margin, 1, -1, 0, 0); + vertex(mat, norm, light, verts, 0, 0, dz, margin, 0, -1, 0, 0); + // Right face + vertex(mat, norm, light, verts, dx, 0, dz, 1 - margin, 0, 1, 0, 0); + vertex(mat, norm, light, verts, dx, dy, dz, 1 - margin, 1, 1, 0, 0); + vertex(mat, norm, light, verts, dx, dy, 0, 1, 1, 1, 0, 0); + vertex(mat, norm, light, verts, dx, 0, 0, 1, 0, 1, 0, 0); + // Bottom face + vertex(mat, norm, light, verts, 0, dy, dz, 0, 1 - margin, 0, 1, 0); + vertex(mat, norm, light, verts, 0, dy, 0, 0, 1, 0, 1, 0); + vertex(mat, norm, light, verts, dx, dy, 0, 1, 1, 0, 1, 0); + vertex(mat, norm, light, verts, dx, dy, dz, 1, 1 - margin, 0, 1, 0); + + ps.popPose(); + + if (wallScroll.pattern != null) + WorldlyPatternRenderHelpers.renderPatternForScroll( + wallScroll.pattern, + wallScroll, + ps, + bufSource, + light, + wallScroll.blockSize, + wallScroll.getShowsStrokeOrder()); + } + + ps.popPose(); + super.render(wallScroll, yaw, partialTicks, ps, bufSource, packedLight); + } + + @Override + public ResourceLocation getTextureLocation(EntityWallScroll wallScroll) { + if (wallScroll.isAncient) { + if (wallScroll.blockSize <= 1) { + return ANCIENT_BG_SMOL; + } else if (wallScroll.blockSize == 2) { + return ANCIENT_BG_MEDIUM; + } else { + return ANCIENT_BG_LARGE; + } + } else { + if (wallScroll.blockSize <= 1) { + return PRISTINE_BG_SMOL; + } else if (wallScroll.blockSize == 2) { + return PRISTINE_BG_MEDIUM; + } else { + return PRISTINE_BG_LARGE; + } + } + } + + private static void vertex( + Matrix4f mat, + Matrix3f normal, + int light, + VertexConsumer verts, + float x, + float y, + float z, + float u, + float v, + float nx, + float ny, + float nz) { + verts + .vertex(mat, x, y, z) + .color(0xffffffff) + .uv(u, v) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(light) + .normal(normal, nx, ny, nz) + .endVertex(); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/gui/GuiSpellcasting.kt b/Common/src/main/java/at/petrak/hexcasting/client/gui/GuiSpellcasting.kt index 0a9f66cd2b..4f10867779 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/gui/GuiSpellcasting.kt +++ b/Common/src/main/java/at/petrak/hexcasting/client/gui/GuiSpellcasting.kt @@ -22,6 +22,7 @@ import at.petrak.hexcasting.common.msgs.MsgNewSpellPatternC2S import at.petrak.hexcasting.xplat.IClientXplatAbstractions import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.vertex.PoseStack +import kotlin.math.* import net.minecraft.client.Minecraft import net.minecraft.client.gui.GuiGraphics import net.minecraft.client.gui.screens.Screen @@ -34,500 +35,508 @@ import net.minecraft.util.FormattedCharSequence import net.minecraft.util.Mth import net.minecraft.world.InteractionHand import net.minecraft.world.phys.Vec2 -import kotlin.math.* // TODO winfy: fix this class to use ExecutionClientView -class GuiSpellcasting constructor( - private val handOpenedWith: InteractionHand, - private var patterns: MutableList<ResolvedPattern>, - private var cachedStack: List<CompoundTag>, - private var cachedRavenmind: CompoundTag?, - private var parenCount: Int, +class GuiSpellcasting +constructor( + private val handOpenedWith: InteractionHand, + private var patterns: MutableList<ResolvedPattern>, + private var cachedStack: List<CompoundTag>, + private var cachedRavenmind: CompoundTag?, + private var parenCount: Int, ) : Screen("gui.hexcasting.spellcasting".asTranslatedComponent) { - private var stackDescs: List<FormattedCharSequence> = listOf() - private var parenDescs: List<FormattedCharSequence> = listOf() - private var ravenmind: FormattedCharSequence? = null - - private var drawState: PatternDrawState = PatternDrawState.BetweenPatterns - private val usedSpots: MutableSet<HexCoord> = HashSet() - - private var ambianceSoundInstance: GridSoundInstance? = null - - private val randSrc = SoundInstance.createUnseededRandom() - - init { - for ((pattern, origin) in patterns) { - this.usedSpots.addAll(pattern.positions(origin)) - } - this.calculateIotaDisplays() - } - - fun recvServerUpdate(info: ExecutionClientView, index: Int) { - if (info.isStackClear) { - this.minecraft?.setScreen(null) - return - } - - // TODO this is the kinda hacky bit - if (info.resolutionType == ResolvedPatternType.UNDONE) { - this.patterns.reversed().drop(1).firstOrNull { it.type == ResolvedPatternType.ESCAPED }?.let { it.type = ResolvedPatternType.UNDONE } - this.patterns.getOrNull(index)?.let { it.type = ResolvedPatternType.EVALUATED } - } else this.patterns.getOrNull(index)?.let { - it.type = info.resolutionType - } - - this.cachedStack = info.stackDescs - this.cachedRavenmind = info.ravenmind - this.calculateIotaDisplays() - } - - fun calculateIotaDisplays() { - val mc = Minecraft.getInstance() - val width = (this.width * LHS_IOTAS_ALLOCATION).toInt() - this.stackDescs = - this.cachedStack.map { IotaType.getDisplayWithMaxWidth(it, width, mc.font) } - .asReversed() -// this.parenDescs = if (this.cachedParens.isNotEmpty()) -// this.cachedParens.flatMap { HexIotaTypes.getDisplayWithMaxWidth(it, width, mc.font) } -// else if (this.parenCount > 0) -// listOf("...".gold.visualOrderText) -// else -// emptyList() - this.parenDescs = emptyList() - this.ravenmind = - this.cachedRavenmind?.let { - IotaType.getDisplayWithMaxWidth( - it, - (this.width * RHS_IOTAS_ALLOCATION).toInt(), - mc.font - ) - } - } - - override fun init() { - val minecraft = Minecraft.getInstance() - val soundManager = minecraft.soundManager - soundManager.stop(HexSounds.CASTING_AMBIANCE.location, null) - val player = minecraft.player - if (player != null) { - this.ambianceSoundInstance = GridSoundInstance(player) - soundManager.play(this.ambianceSoundInstance!!) - } - - this.calculateIotaDisplays() - } - - override fun tick() { - val minecraft = Minecraft.getInstance() - val player = minecraft.player - if (player != null) { - val heldItem = player.getItemInHand(handOpenedWith) - if (heldItem.isEmpty || !heldItem.`is`(HexTags.Items.STAVES)) - closeForReal() - } - } - - override fun mouseClicked(mxOut: Double, myOut: Double, pButton: Int): Boolean { - if (super.mouseClicked(mxOut, myOut, pButton)) { - return true - } - if (HexConfig.client().clickingTogglesDrawing()) { - return if (this.drawState is PatternDrawState.BetweenPatterns) - drawStart(mxOut, myOut) - else - drawEnd() - } - return drawStart(mxOut, myOut) - } - - private fun drawStart(mxOut: Double, myOut: Double): Boolean { - val mx = Mth.clamp(mxOut, 0.0, this.width.toDouble()) - val my = Mth.clamp(myOut, 0.0, this.height.toDouble()) - if (this.drawState is PatternDrawState.BetweenPatterns) { - val coord = this.pxToCoord(Vec2(mx.toFloat(), my.toFloat())) - if (!this.usedSpots.contains(coord)) { - this.drawState = PatternDrawState.JustStarted(coord) - Minecraft.getInstance().soundManager.play( - SimpleSoundInstance( - HexSounds.START_PATTERN, - SoundSource.PLAYERS, - 0.25f, - 1f, - randSrc, - this.ambianceSoundInstance!!.x, - this.ambianceSoundInstance!!.y, - this.ambianceSoundInstance!!.z, - ) - ) - } - } - - return false - } - - override fun mouseMoved(mxOut: Double, myOut: Double) { - super.mouseMoved(mxOut, myOut) - - if (HexConfig.client().clickingTogglesDrawing() && this.drawState !is PatternDrawState.BetweenPatterns) - drawMove(mxOut, myOut) - } - - override fun mouseDragged(mxOut: Double, myOut: Double, pButton: Int, pDragX: Double, pDragY: Double): Boolean { - if (super.mouseDragged(mxOut, myOut, pButton, pDragX, pDragY)) { - return true - } - if (HexConfig.client().clickingTogglesDrawing()) - return false - return drawMove(mxOut, myOut) - } - - private fun drawMove(mxOut: Double, myOut: Double): Boolean { - val mx = Mth.clamp(mxOut, 0.0, this.width.toDouble()) - val my = Mth.clamp(myOut, 0.0, this.height.toDouble()) - - val anchorCoord = when (this.drawState) { - PatternDrawState.BetweenPatterns -> null - is PatternDrawState.JustStarted -> (this.drawState as PatternDrawState.JustStarted).start - is PatternDrawState.Drawing -> (this.drawState as PatternDrawState.Drawing).current - } - if (anchorCoord != null) { - val anchor = this.coordToPx(anchorCoord) - val mouse = Vec2(mx.toFloat(), my.toFloat()) - val snapDist = - this.hexSize() * this.hexSize() * 2.0 * Mth.clamp(HexConfig.client().gridSnapThreshold(), 0.5, 1.0) - if (anchor.distanceToSqr(mouse) >= snapDist) { - val delta = mouse.add(anchor.negated()) - val angle = atan2(delta.y, delta.x) - // 0 is right, increases clockwise(?) - val snappedAngle = angle.div(Mth.TWO_PI).mod(6.0f) - val newdir = HexDir.values()[(snappedAngle.times(6).roundToInt() + 1).mod(6)] - // The player might have a lousy aim, so set the new anchor point to the "ideal" - // location as if they had hit it exactly on the nose. - val idealNextLoc = anchorCoord + newdir - var playSound = false - if (!this.usedSpots.contains(idealNextLoc)) { - if (this.drawState is PatternDrawState.JustStarted) { - val pat = HexPattern(newdir) - - this.drawState = PatternDrawState.Drawing(anchorCoord, idealNextLoc, pat) - playSound = true - } else if (this.drawState is PatternDrawState.Drawing) { - // how anyone gets around without a borrowck is beyond me - val ds = (this.drawState as PatternDrawState.Drawing) - val lastDir = ds.wipPattern.finalDir() - if (newdir == lastDir.rotatedBy(HexAngle.BACK)) { - // We're diametrically opposite! Do a backtrack - if (ds.wipPattern.angles.isEmpty()) { - this.drawState = PatternDrawState.JustStarted(ds.current + newdir) - } else { - ds.current += newdir - ds.wipPattern.angles.removeLast() - } - playSound = true - } else { - val success = ds.wipPattern.tryAppendDir(newdir) - if (success) { - ds.current = idealNextLoc - } - playSound = success - } - } - } - - if (playSound) { - Minecraft.getInstance().soundManager.play( - SimpleSoundInstance( - HexSounds.ADD_TO_PATTERN, - SoundSource.PLAYERS, - 0.25f, - 1f + (Math.random().toFloat() - 0.5f) * 0.1f, - randSrc, - this.ambianceSoundInstance!!.x, - this.ambianceSoundInstance!!.y, - this.ambianceSoundInstance!!.z, - ) - ) - } - } - } - - return false - } - - override fun mouseReleased(mx: Double, my: Double, pButton: Int): Boolean { - if (super.mouseReleased(mx, my, pButton)) { - return true - } - if (HexConfig.client().clickingTogglesDrawing()) - return false - return drawEnd() - } - - private fun drawEnd(): Boolean { - when (this.drawState) { - PatternDrawState.BetweenPatterns -> {} - is PatternDrawState.JustStarted -> { - // Well, we never managed to get anything on the stack this go-around. - this.drawState = PatternDrawState.BetweenPatterns - } - - is PatternDrawState.Drawing -> { - val (start, _, pat) = this.drawState as PatternDrawState.Drawing - this.drawState = PatternDrawState.BetweenPatterns - this.patterns.add(ResolvedPattern(pat, start, ResolvedPatternType.UNRESOLVED)) - - this.usedSpots.addAll(pat.positions(start)) - - IClientXplatAbstractions.INSTANCE.sendPacketToServer( - MsgNewSpellPatternC2S( - this.handOpenedWith, - pat, - this.patterns - ) - ) - } - } - - return false - } - - override fun mouseScrolled(pMouseX: Double, pMouseY: Double, pDelta: Double): Boolean { - super.mouseScrolled(pMouseX, pMouseY, pDelta) - - val mouseHandler = Minecraft.getInstance().mouseHandler - - if (mouseHandler.accumulatedScroll != 0.0 && sign(pDelta) != sign(mouseHandler.accumulatedScroll)) { - mouseHandler.accumulatedScroll = 0.0 - } - - mouseHandler.accumulatedScroll += pDelta - val accumulation: Int = mouseHandler.accumulatedScroll.toInt() - if (accumulation == 0) { - return true - } - - mouseHandler.accumulatedScroll -= accumulation.toDouble() - - ShiftScrollListener.onScroll(pDelta, false) - - return true - } - - override fun onClose() { - if (drawState == PatternDrawState.BetweenPatterns) - closeForReal() - else - drawState = PatternDrawState.BetweenPatterns - } - - fun closeForReal() { - Minecraft.getInstance().soundManager.stop(HexSounds.CASTING_AMBIANCE.location, null) - - super.onClose() - } - - - override fun render(graphics: GuiGraphics, pMouseX: Int, pMouseY: Int, pPartialTick: Float) { - super.render(graphics, pMouseX, pMouseY, pPartialTick) - - this.ambianceSoundInstance?.mousePosX = pMouseX / this.width.toDouble() - this.ambianceSoundInstance?.mousePosY = pMouseX / this.width.toDouble() - - val ps = graphics.pose() // TODO: Determine if this is still necessary. - - val mat = ps.last().pose() - val prevShader = RenderSystem.getShader() - RenderSystem.setShader(GameRenderer::getPositionColorShader) - RenderSystem.disableDepthTest() - RenderSystem.disableCull() - - // Draw guide dots around the cursor - val mousePos = Vec2(pMouseX.toFloat(), pMouseY.toFloat()) - // snap it to the center - val mouseCoord = this.pxToCoord(mousePos) - val radius = 3 - for (dotCoord in mouseCoord.rangeAround(radius)) { - if (!this.usedSpots.contains(dotCoord)) { - val dotPx = this.coordToPx(dotCoord) - val delta = dotPx.add(mousePos.negated()).length() - // when right on top of the cursor, 1.0 - // when at the full radius, 0! this is so we don't have dots suddenly appear/disappear. - // we subtract size from delta so there's a little "island" of 100% bright points by the mouse - val scaledDist = Mth.clamp( - 1.0f - ((delta - this.hexSize()) / (radius.toFloat() * this.hexSize())), - 0f, - 1f - ) - drawSpot( - mat, - dotPx, - scaledDist * 2f, - Mth.lerp(scaledDist, 0.4f, 0.5f), - Mth.lerp(scaledDist, 0.8f, 1.0f), - Mth.lerp(scaledDist, 0.7f, 0.9f), - scaledDist - ) - } - } - RenderSystem.defaultBlendFunc() - - for ((idx, elts) in this.patterns.withIndex()) { - val (pat, origin, valid) = elts - drawPatternFromPoints( - mat, - pat.toLines( - this.hexSize(), - this.coordToPx(origin) - ), - findDupIndices(pat.positions()), - true, - valid.color or (0xC8 shl 24), - valid.fadeColor or (0xC8 shl 24), - if (valid.success) 0.2f else 0.9f, - DEFAULT_READABILITY_OFFSET, - 1f, - idx.toDouble() - ) - } - - // Now draw the currently WIP pattern - if (this.drawState !is PatternDrawState.BetweenPatterns) { - val points = mutableListOf<Vec2>() - var dupIndices: Set<Int>? = null - - if (this.drawState is PatternDrawState.JustStarted) { - val ds = this.drawState as PatternDrawState.JustStarted - points.add(this.coordToPx(ds.start)) - } else if (this.drawState is PatternDrawState.Drawing) { - val ds = this.drawState as PatternDrawState.Drawing - dupIndices = findDupIndices(ds.wipPattern.positions()) - for (pos in ds.wipPattern.positions()) { - val pix = this.coordToPx(pos + ds.start) - points.add(pix) - } - } - - points.add(mousePos) - // Use the size of the patterns as the seed so that way when this one is added the zappies don't jump - drawPatternFromPoints(mat, - points, - dupIndices, - false, - 0xff_64c8ff_u.toInt(), - 0xff_fecbe6_u.toInt(), - 0.1f, - DEFAULT_READABILITY_OFFSET, - 1f, - this.patterns.size.toDouble()) - } - - RenderSystem.enableDepthTest() - - val mc = Minecraft.getInstance() - val font = mc.font - ps.pushPose() - ps.translate(10.0, 10.0, 0.0) - -// if (this.parenCount > 0) { -// val boxHeight = (this.parenDescs.size + 1f) * 10f -// RenderSystem.setShader(GameRenderer::getPositionColorShader) -// RenderSystem.defaultBlendFunc() -// drawBox(ps, 0f, 0f, (this.width * LHS_IOTAS_ALLOCATION + 5).toFloat(), boxHeight, 7.5f) -// ps.translate(0.0, 0.0, 1.0) -// -// val time = ClientTickCounter.getTotal() * 0.16f -// val opacity = (Mth.map(cos(time), -1f, 1f, 200f, 255f)).toInt() -// val color = 0x00_ffffff or (opacity shl 24) -// RenderSystem.setShader { prevShader } -// for (desc in this.parenDescs) { -// font.draw(ps, desc, 10f, 7f, color) -// ps.translate(0.0, 10.0, 0.0) -// } -// ps.translate(0.0, 15.0, 0.0) -// } - - if (this.stackDescs.isNotEmpty()) { - val boxHeight = (this.stackDescs.size + 1f) * 10f - RenderSystem.setShader(GameRenderer::getPositionColorShader) - RenderSystem.enableBlend() - drawBox(ps, 0f, 0f, (this.width * LHS_IOTAS_ALLOCATION + 5).toFloat(), boxHeight) - ps.translate(0.0, 0.0, 1.0) - RenderSystem.setShader { prevShader } - for (desc in this.stackDescs) { - graphics.drawString(font, desc, 5, 7, -1) // TODO: Confirm this works - ps.translate(0.0, 10.0, 0.0) - } - } - - ps.popPose() - if (this.ravenmind != null) { - val kotlinBad = this.ravenmind!! - ps.pushPose() - val boxHeight = 15f - val addlScale = 1.5f - ps.translate(this.width * (1.0 - RHS_IOTAS_ALLOCATION * addlScale) - 10, 10.0, 0.0) - RenderSystem.setShader(GameRenderer::getPositionColorShader) - RenderSystem.enableBlend() - drawBox( - ps, 0f, 0f, - (this.width * RHS_IOTAS_ALLOCATION * addlScale).toFloat(), boxHeight * addlScale, - ) - ps.translate(5.0, 5.0, 1.0) - ps.scale(addlScale, addlScale, 1f) - - val time = ClientTickCounter.getTotal() * 0.2f - val opacity = (Mth.map(sin(time), -1f, 1f, 150f, 255f)).toInt() - val color = 0x00_ffffff or (opacity shl 24) - - RenderSystem.setShader { prevShader } - graphics.drawString(font, kotlinBad, 0, 0, color) // TODO: Confirm this works - ps.popPose() - } - - RenderSystem.setShader { prevShader } - } - - // why the hell is this default true - override fun isPauseScreen(): Boolean = false - - /** Distance between adjacent hex centers */ - fun hexSize(): Float { - val scaleModifier = Minecraft.getInstance().player!!.getAttributeValue(HexAttributes.GRID_ZOOM) - - // Originally, we allowed 32 dots across. Assuming a 1920x1080 screen this allowed like 500-odd area. - // Let's be generous and give them 512. - val baseScale = sqrt(this.width.toDouble() * this.height / 512.0) - return (baseScale / scaleModifier).toFloat() - } - - fun coordsOffset(): Vec2 = Vec2(this.width.toFloat() * 0.5f, this.height.toFloat() * 0.5f) - - fun coordToPx(coord: HexCoord) = - at.petrak.hexcasting.api.utils.coordToPx(coord, this.hexSize(), this.coordsOffset()) - - fun pxToCoord(px: Vec2) = at.petrak.hexcasting.api.utils.pxToCoord(px, this.hexSize(), this.coordsOffset()) - - - private sealed class PatternDrawState { - /** We're waiting on the player to right-click again */ - object BetweenPatterns : PatternDrawState() - - /** We just started drawing and haven't drawn the first line yet. */ - data class JustStarted(val start: HexCoord) : PatternDrawState() - - /** We've started drawing a pattern for real. */ - data class Drawing(val start: HexCoord, var current: HexCoord, val wipPattern: HexPattern) : PatternDrawState() - } - - companion object { - const val LHS_IOTAS_ALLOCATION = 0.7 - const val RHS_IOTAS_ALLOCATION = 0.15 - - fun drawBox(ps: PoseStack, x: Float, y: Float, w: Float, h: Float, leftMargin: Float = 2.5f) { - RenderSystem.setShader(GameRenderer::getPositionColorShader) - RenderSystem.enableBlend() - renderQuad(ps, x, y, w, h, 0x50_303030) - renderQuad(ps, x + leftMargin, y + 2.5f, w - leftMargin - 2.5f, h - 5f, 0x50_303030) - } - } + private var stackDescs: List<FormattedCharSequence> = listOf() + private var parenDescs: List<FormattedCharSequence> = listOf() + private var ravenmind: FormattedCharSequence? = null + + private var drawState: PatternDrawState = PatternDrawState.BetweenPatterns + private val usedSpots: MutableSet<HexCoord> = HashSet() + + private var ambianceSoundInstance: GridSoundInstance? = null + + private val randSrc = SoundInstance.createUnseededRandom() + + init { + for ((pattern, origin) in patterns) { + this.usedSpots.addAll(pattern.positions(origin)) + } + this.calculateIotaDisplays() + } + + fun recvServerUpdate(info: ExecutionClientView, index: Int) { + if (info.isStackClear) { + this.minecraft?.setScreen(null) + return + } + + // TODO this is the kinda hacky bit + if (info.resolutionType == ResolvedPatternType.UNDONE) { + this.patterns + .reversed() + .drop(1) + .firstOrNull { it.type == ResolvedPatternType.ESCAPED } + ?.let { it.type = ResolvedPatternType.UNDONE } + this.patterns.getOrNull(index)?.let { it.type = ResolvedPatternType.EVALUATED } + } else this.patterns.getOrNull(index)?.let { it.type = info.resolutionType } + + this.cachedStack = info.stackDescs + this.cachedRavenmind = info.ravenmind + this.calculateIotaDisplays() + } + + fun calculateIotaDisplays() { + val mc = Minecraft.getInstance() + val width = (this.width * LHS_IOTAS_ALLOCATION).toInt() + this.stackDescs = + this.cachedStack.map { IotaType.getDisplayWithMaxWidth(it, width, mc.font) }.asReversed() + // this.parenDescs = if (this.cachedParens.isNotEmpty()) + // this.cachedParens.flatMap { HexIotaTypes.getDisplayWithMaxWidth(it, width, + // mc.font) } + // else if (this.parenCount > 0) + // listOf("...".gold.visualOrderText) + // else + // emptyList() + this.parenDescs = emptyList() + this.ravenmind = + this.cachedRavenmind?.let { + IotaType.getDisplayWithMaxWidth(it, (this.width * RHS_IOTAS_ALLOCATION).toInt(), mc.font) + } + } + + override fun init() { + val minecraft = Minecraft.getInstance() + val soundManager = minecraft.soundManager + soundManager.stop(HexSounds.CASTING_AMBIANCE.location, null) + val player = minecraft.player + if (player != null) { + this.ambianceSoundInstance = GridSoundInstance(player) + soundManager.play(this.ambianceSoundInstance!!) + } + + this.calculateIotaDisplays() + } + + override fun tick() { + val minecraft = Minecraft.getInstance() + val player = minecraft.player + if (player != null) { + val heldItem = player.getItemInHand(handOpenedWith) + if (heldItem.isEmpty || !heldItem.`is`(HexTags.Items.STAVES)) closeForReal() + } + } + + override fun mouseClicked(mxOut: Double, myOut: Double, pButton: Int): Boolean { + if (super.mouseClicked(mxOut, myOut, pButton)) { + return true + } + if (HexConfig.client().clickingTogglesDrawing()) { + return if (this.drawState is PatternDrawState.BetweenPatterns) drawStart(mxOut, myOut) + else drawEnd() + } + return drawStart(mxOut, myOut) + } + + private fun drawStart(mxOut: Double, myOut: Double): Boolean { + val mx = Mth.clamp(mxOut, 0.0, this.width.toDouble()) + val my = Mth.clamp(myOut, 0.0, this.height.toDouble()) + if (this.drawState is PatternDrawState.BetweenPatterns) { + val coord = this.pxToCoord(Vec2(mx.toFloat(), my.toFloat())) + if (!this.usedSpots.contains(coord)) { + this.drawState = PatternDrawState.JustStarted(coord) + Minecraft.getInstance() + .soundManager + .play( + SimpleSoundInstance( + HexSounds.START_PATTERN, + SoundSource.PLAYERS, + 0.25f, + 1f, + randSrc, + this.ambianceSoundInstance!!.x, + this.ambianceSoundInstance!!.y, + this.ambianceSoundInstance!!.z, + ) + ) + } + } + + return false + } + + override fun mouseMoved(mxOut: Double, myOut: Double) { + super.mouseMoved(mxOut, myOut) + + if ( + HexConfig.client().clickingTogglesDrawing() && + this.drawState !is PatternDrawState.BetweenPatterns + ) + drawMove(mxOut, myOut) + } + + override fun mouseDragged( + mxOut: Double, + myOut: Double, + pButton: Int, + pDragX: Double, + pDragY: Double + ): Boolean { + if (super.mouseDragged(mxOut, myOut, pButton, pDragX, pDragY)) { + return true + } + if (HexConfig.client().clickingTogglesDrawing()) return false + return drawMove(mxOut, myOut) + } + + private fun drawMove(mxOut: Double, myOut: Double): Boolean { + val mx = Mth.clamp(mxOut, 0.0, this.width.toDouble()) + val my = Mth.clamp(myOut, 0.0, this.height.toDouble()) + + val anchorCoord = + when (this.drawState) { + PatternDrawState.BetweenPatterns -> null + is PatternDrawState.JustStarted -> (this.drawState as PatternDrawState.JustStarted).start + is PatternDrawState.Drawing -> (this.drawState as PatternDrawState.Drawing).current + } + if (anchorCoord != null) { + val anchor = this.coordToPx(anchorCoord) + val mouse = Vec2(mx.toFloat(), my.toFloat()) + val snapDist = + this.hexSize() * + this.hexSize() * + 2.0 * + Mth.clamp(HexConfig.client().gridSnapThreshold(), 0.5, 1.0) + if (anchor.distanceToSqr(mouse) >= snapDist) { + val delta = mouse.add(anchor.negated()) + val angle = atan2(delta.y, delta.x) + // 0 is right, increases clockwise(?) + val snappedAngle = angle.div(Mth.TWO_PI).mod(6.0f) + val newdir = HexDir.values()[(snappedAngle.times(6).roundToInt() + 1).mod(6)] + // The player might have a lousy aim, so set the new anchor point to the "ideal" + // location as if they had hit it exactly on the nose. + val idealNextLoc = anchorCoord + newdir + var playSound = false + if (!this.usedSpots.contains(idealNextLoc)) { + if (this.drawState is PatternDrawState.JustStarted) { + val pat = HexPattern(newdir) + + this.drawState = PatternDrawState.Drawing(anchorCoord, idealNextLoc, pat) + playSound = true + } else if (this.drawState is PatternDrawState.Drawing) { + // how anyone gets around without a borrowck is beyond me + val ds = (this.drawState as PatternDrawState.Drawing) + val lastDir = ds.wipPattern.finalDir() + if (newdir == lastDir.rotatedBy(HexAngle.BACK)) { + // We're diametrically opposite! Do a backtrack + if (ds.wipPattern.angles.isEmpty()) { + this.drawState = PatternDrawState.JustStarted(ds.current + newdir) + } else { + ds.current += newdir + ds.wipPattern.angles.removeLast() + } + playSound = true + } else { + val success = ds.wipPattern.tryAppendDir(newdir) + if (success) { + ds.current = idealNextLoc + } + playSound = success + } + } + } + + if (playSound) { + Minecraft.getInstance() + .soundManager + .play( + SimpleSoundInstance( + HexSounds.ADD_TO_PATTERN, + SoundSource.PLAYERS, + 0.25f, + 1f + (Math.random().toFloat() - 0.5f) * 0.1f, + randSrc, + this.ambianceSoundInstance!!.x, + this.ambianceSoundInstance!!.y, + this.ambianceSoundInstance!!.z, + ) + ) + } + } + } + + return false + } + + override fun mouseReleased(mx: Double, my: Double, pButton: Int): Boolean { + if (super.mouseReleased(mx, my, pButton)) { + return true + } + if (HexConfig.client().clickingTogglesDrawing()) return false + return drawEnd() + } + + private fun drawEnd(): Boolean { + when (this.drawState) { + PatternDrawState.BetweenPatterns -> {} + is PatternDrawState.JustStarted -> { + // Well, we never managed to get anything on the stack this go-around. + this.drawState = PatternDrawState.BetweenPatterns + } + is PatternDrawState.Drawing -> { + val (start, _, pat) = this.drawState as PatternDrawState.Drawing + this.drawState = PatternDrawState.BetweenPatterns + this.patterns.add(ResolvedPattern(pat, start, ResolvedPatternType.UNRESOLVED)) + + this.usedSpots.addAll(pat.positions(start)) + + IClientXplatAbstractions.INSTANCE.sendPacketToServer( + MsgNewSpellPatternC2S(this.handOpenedWith, pat, this.patterns) + ) + } + } + + return false + } + + override fun mouseScrolled(pMouseX: Double, pMouseY: Double, pDelta: Double): Boolean { + super.mouseScrolled(pMouseX, pMouseY, pDelta) + + val mouseHandler = Minecraft.getInstance().mouseHandler + + if ( + mouseHandler.accumulatedScroll != 0.0 && sign(pDelta) != sign(mouseHandler.accumulatedScroll) + ) { + mouseHandler.accumulatedScroll = 0.0 + } + + mouseHandler.accumulatedScroll += pDelta + val accumulation: Int = mouseHandler.accumulatedScroll.toInt() + if (accumulation == 0) { + return true + } + + mouseHandler.accumulatedScroll -= accumulation.toDouble() + + ShiftScrollListener.onScroll(pDelta, false) + + return true + } + + override fun onClose() { + if (drawState == PatternDrawState.BetweenPatterns) closeForReal() + else drawState = PatternDrawState.BetweenPatterns + } + + fun closeForReal() { + Minecraft.getInstance().soundManager.stop(HexSounds.CASTING_AMBIANCE.location, null) + + super.onClose() + } + + override fun render(graphics: GuiGraphics, pMouseX: Int, pMouseY: Int, pPartialTick: Float) { + super.render(graphics, pMouseX, pMouseY, pPartialTick) + + this.ambianceSoundInstance?.mousePosX = pMouseX / this.width.toDouble() + this.ambianceSoundInstance?.mousePosY = pMouseX / this.width.toDouble() + + val ps = graphics.pose() // TODO: Determine if this is still necessary. + + val mat = ps.last().pose() + val prevShader = RenderSystem.getShader() + RenderSystem.setShader(GameRenderer::getPositionColorShader) + RenderSystem.disableDepthTest() + RenderSystem.disableCull() + + // Draw guide dots around the cursor + val mousePos = Vec2(pMouseX.toFloat(), pMouseY.toFloat()) + // snap it to the center + val mouseCoord = this.pxToCoord(mousePos) + val radius = 3 + for (dotCoord in mouseCoord.rangeAround(radius)) { + if (!this.usedSpots.contains(dotCoord)) { + val dotPx = this.coordToPx(dotCoord) + val delta = dotPx.add(mousePos.negated()).length() + // when right on top of the cursor, 1.0 + // when at the full radius, 0! this is so we don't have dots suddenly appear/disappear. + // we subtract size from delta so there's a little "island" of 100% bright points by the + // mouse + val scaledDist = + Mth.clamp(1.0f - ((delta - this.hexSize()) / (radius.toFloat() * this.hexSize())), 0f, 1f) + drawSpot( + mat, + dotPx, + scaledDist * 2f, + Mth.lerp(scaledDist, 0.4f, 0.5f), + Mth.lerp(scaledDist, 0.8f, 1.0f), + Mth.lerp(scaledDist, 0.7f, 0.9f), + scaledDist + ) + } + } + RenderSystem.defaultBlendFunc() + + for ((idx, elts) in this.patterns.withIndex()) { + val (pat, origin, valid) = elts + drawPatternFromPoints( + mat, + pat.toLines(this.hexSize(), this.coordToPx(origin)), + findDupIndices(pat.positions()), + true, + valid.color or (0xC8 shl 24), + valid.fadeColor or (0xC8 shl 24), + if (valid.success) 0.2f else 0.9f, + DEFAULT_READABILITY_OFFSET, + 1f, + idx.toDouble() + ) + } + + // Now draw the currently WIP pattern + if (this.drawState !is PatternDrawState.BetweenPatterns) { + val points = mutableListOf<Vec2>() + var dupIndices: Set<Int>? = null + + if (this.drawState is PatternDrawState.JustStarted) { + val ds = this.drawState as PatternDrawState.JustStarted + points.add(this.coordToPx(ds.start)) + } else if (this.drawState is PatternDrawState.Drawing) { + val ds = this.drawState as PatternDrawState.Drawing + dupIndices = findDupIndices(ds.wipPattern.positions()) + for (pos in ds.wipPattern.positions()) { + val pix = this.coordToPx(pos + ds.start) + points.add(pix) + } + } + + points.add(mousePos) + // Use the size of the patterns as the seed so that way when this one is added the zappies + // don't jump + drawPatternFromPoints( + mat, + points, + dupIndices, + false, + 0xff_64c8ff_u.toInt(), + 0xff_fecbe6_u.toInt(), + 0.1f, + DEFAULT_READABILITY_OFFSET, + 1f, + this.patterns.size.toDouble() + ) + } + + RenderSystem.enableDepthTest() + + val mc = Minecraft.getInstance() + val font = mc.font + ps.pushPose() + ps.translate(10.0, 10.0, 0.0) + + // if (this.parenCount > 0) { + // val boxHeight = (this.parenDescs.size + 1f) * 10f + // RenderSystem.setShader(GameRenderer::getPositionColorShader) + // RenderSystem.defaultBlendFunc() + // drawBox(ps, 0f, 0f, (this.width * LHS_IOTAS_ALLOCATION + 5).toFloat(), boxHeight, + // 7.5f) + // ps.translate(0.0, 0.0, 1.0) + // + // val time = ClientTickCounter.getTotal() * 0.16f + // val opacity = (Mth.map(cos(time), -1f, 1f, 200f, 255f)).toInt() + // val color = 0x00_ffffff or (opacity shl 24) + // RenderSystem.setShader { prevShader } + // for (desc in this.parenDescs) { + // font.draw(ps, desc, 10f, 7f, color) + // ps.translate(0.0, 10.0, 0.0) + // } + // ps.translate(0.0, 15.0, 0.0) + // } + + if (this.stackDescs.isNotEmpty()) { + val boxHeight = (this.stackDescs.size + 1f) * 10f + RenderSystem.setShader(GameRenderer::getPositionColorShader) + RenderSystem.enableBlend() + drawBox(ps, 0f, 0f, (this.width * LHS_IOTAS_ALLOCATION + 5).toFloat(), boxHeight) + ps.translate(0.0, 0.0, 1.0) + RenderSystem.setShader { prevShader } + for (desc in this.stackDescs) { + graphics.drawString(font, desc, 5, 7, -1) // TODO: Confirm this works + ps.translate(0.0, 10.0, 0.0) + } + } + + ps.popPose() + if (this.ravenmind != null) { + val kotlinBad = this.ravenmind!! + ps.pushPose() + val boxHeight = 15f + val addlScale = 1.5f + ps.translate(this.width * (1.0 - RHS_IOTAS_ALLOCATION * addlScale) - 10, 10.0, 0.0) + RenderSystem.setShader(GameRenderer::getPositionColorShader) + RenderSystem.enableBlend() + drawBox( + ps, + 0f, + 0f, + (this.width * RHS_IOTAS_ALLOCATION * addlScale).toFloat(), + boxHeight * addlScale, + ) + ps.translate(5.0, 5.0, 1.0) + ps.scale(addlScale, addlScale, 1f) + + val time = ClientTickCounter.getTotal() * 0.2f + val opacity = (Mth.map(sin(time), -1f, 1f, 150f, 255f)).toInt() + val color = 0x00_ffffff or (opacity shl 24) + + RenderSystem.setShader { prevShader } + graphics.drawString(font, kotlinBad, 0, 0, color) // TODO: Confirm this works + ps.popPose() + } + + RenderSystem.setShader { prevShader } + } + + // why the hell is this default true + override fun isPauseScreen(): Boolean = false + + /** Distance between adjacent hex centers */ + fun hexSize(): Float { + val scaleModifier = Minecraft.getInstance().player!!.getAttributeValue(HexAttributes.GRID_ZOOM) + + // Originally, we allowed 32 dots across. Assuming a 1920x1080 screen this allowed like 500-odd + // area. + // Let's be generous and give them 512. + val baseScale = sqrt(this.width.toDouble() * this.height / 512.0) + return (baseScale / scaleModifier).toFloat() + } + + fun coordsOffset(): Vec2 = Vec2(this.width.toFloat() * 0.5f, this.height.toFloat() * 0.5f) + + fun coordToPx(coord: HexCoord) = + at.petrak.hexcasting.api.utils.coordToPx(coord, this.hexSize(), this.coordsOffset()) + + fun pxToCoord(px: Vec2) = + at.petrak.hexcasting.api.utils.pxToCoord(px, this.hexSize(), this.coordsOffset()) + + private sealed class PatternDrawState { + /** We're waiting on the player to right-click again */ + object BetweenPatterns : PatternDrawState() + + /** We just started drawing and haven't drawn the first line yet. */ + data class JustStarted(val start: HexCoord) : PatternDrawState() + + /** We've started drawing a pattern for real. */ + data class Drawing(val start: HexCoord, var current: HexCoord, val wipPattern: HexPattern) : + PatternDrawState() + } + + companion object { + const val LHS_IOTAS_ALLOCATION = 0.7 + const val RHS_IOTAS_ALLOCATION = 0.15 + + fun drawBox(ps: PoseStack, x: Float, y: Float, w: Float, h: Float, leftMargin: Float = 2.5f) { + RenderSystem.setShader(GameRenderer::getPositionColorShader) + RenderSystem.enableBlend() + renderQuad(ps, x, y, w, h, 0x50_303030) + renderQuad(ps, x + leftMargin, y + 2.5f, w - leftMargin - 2.5f, h - 5f, 0x50_303030) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/gui/PatternTooltipComponent.java b/Common/src/main/java/at/petrak/hexcasting/client/gui/PatternTooltipComponent.java index c6f7da11d8..1d0f34d03a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/gui/PatternTooltipComponent.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/gui/PatternTooltipComponent.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.client.gui; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.math.HexPattern; import at.petrak.hexcasting.client.render.PatternColors; import at.petrak.hexcasting.client.render.PatternRenderer; @@ -13,8 +15,6 @@ import net.minecraft.world.inventory.tooltip.TooltipComponent; import org.jetbrains.annotations.Nullable; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - // https://github.com/VazkiiMods/Botania/blob/95bd2d3fbc857b7c102687554e1d1b112f8af436/Xplat/src/main/java/vazkii/botania/client/gui/ManaBarTooltipComponent.java // yoink @@ -22,68 +22,79 @@ * @see PatternTooltip the associated data for this */ public class PatternTooltipComponent implements ClientTooltipComponent { - public static final ResourceLocation PRISTINE_BG = modLoc("textures/gui/scroll.png"); - public static final ResourceLocation ANCIENT_BG = modLoc("textures/gui/scroll_ancient.png"); - public static final ResourceLocation SLATE_BG = modLoc("textures/gui/slate.png"); - - private static final float RENDER_SIZE = 128f; - private static final int TEXTURE_SIZE = 48; - - private final HexPattern pattern; - private final ResourceLocation background; - - public PatternTooltipComponent(PatternTooltip tt) { - this.pattern = tt.pattern(); - this.background = tt.background(); - } - - @Nullable - public static ClientTooltipComponent tryConvert(TooltipComponent cmp) { - if (cmp instanceof PatternTooltip ptt) { - return new PatternTooltipComponent(ptt); - } - return null; - } - - @Override - public void renderImage(Font font, int mouseX, int mouseY, GuiGraphics graphics) { - var ps = graphics.pose(); - - // far as i can tell "mouseX" and "mouseY" are actually the positions of the corner of the tooltip - ps.pushPose(); - ps.translate(mouseX, mouseY, 500); - RenderSystem.enableBlend(); - renderBG(graphics, this.background); - - // renderText happens *before* renderImage for some asinine reason - ps.translate(0, 0, 100); - ps.scale(RENDER_SIZE, RENDER_SIZE, 1); - - PatternRenderer.renderPattern(pattern, ps, WorldlyPatternRenderHelpers.READABLE_SCROLL_SETTINGS, - (PatternRenderer.shouldDoStrokeGradient() ? PatternColors.DEFAULT_GRADIENT_COLOR : PatternColors.DEFAULT_PATTERN_COLOR) - .withDots(true, true), - 0, 512); - - ps.popPose(); - } - - private static void renderBG(GuiGraphics graphics, ResourceLocation background) { - graphics.blit( - background, // texture - 0, 0, // x, y - (int) RENDER_SIZE, (int) RENDER_SIZE, // renderWidth, renderHeight - 0f, 0f, // u, v (textureCoords) - TEXTURE_SIZE, TEXTURE_SIZE, // regionWidth, regionHeight (texture sample dimensions) - TEXTURE_SIZE, TEXTURE_SIZE); // textureWidth, textureHeight (total dimensions of texture) - } - - @Override - public int getWidth(Font pFont) { - return (int) RENDER_SIZE; - } - - @Override - public int getHeight() { - return (int) RENDER_SIZE; - } + public static final ResourceLocation PRISTINE_BG = modLoc("textures/gui/scroll.png"); + public static final ResourceLocation ANCIENT_BG = modLoc("textures/gui/scroll_ancient.png"); + public static final ResourceLocation SLATE_BG = modLoc("textures/gui/slate.png"); + + private static final float RENDER_SIZE = 128f; + private static final int TEXTURE_SIZE = 48; + + private final HexPattern pattern; + private final ResourceLocation background; + + public PatternTooltipComponent(PatternTooltip tt) { + this.pattern = tt.pattern(); + this.background = tt.background(); + } + + @Nullable public static ClientTooltipComponent tryConvert(TooltipComponent cmp) { + if (cmp instanceof PatternTooltip ptt) { + return new PatternTooltipComponent(ptt); + } + return null; + } + + @Override + public void renderImage(Font font, int mouseX, int mouseY, GuiGraphics graphics) { + var ps = graphics.pose(); + + // far as i can tell "mouseX" and "mouseY" are actually the positions of the corner of the + // tooltip + ps.pushPose(); + ps.translate(mouseX, mouseY, 500); + RenderSystem.enableBlend(); + renderBG(graphics, this.background); + + // renderText happens *before* renderImage for some asinine reason + ps.translate(0, 0, 100); + ps.scale(RENDER_SIZE, RENDER_SIZE, 1); + + PatternRenderer.renderPattern( + pattern, + ps, + WorldlyPatternRenderHelpers.READABLE_SCROLL_SETTINGS, + (PatternRenderer.shouldDoStrokeGradient() + ? PatternColors.DEFAULT_GRADIENT_COLOR + : PatternColors.DEFAULT_PATTERN_COLOR) + .withDots(true, true), + 0, + 512); + + ps.popPose(); + } + + private static void renderBG(GuiGraphics graphics, ResourceLocation background) { + graphics.blit( + background, // texture + 0, + 0, // x, y + (int) RENDER_SIZE, + (int) RENDER_SIZE, // renderWidth, renderHeight + 0f, + 0f, // u, v (textureCoords) + TEXTURE_SIZE, + TEXTURE_SIZE, // regionWidth, regionHeight (texture sample dimensions) + TEXTURE_SIZE, + TEXTURE_SIZE); // textureWidth, textureHeight (total dimensions of texture) + } + + @Override + public int getWidth(Font pFont) { + return (int) RENDER_SIZE; + } + + @Override + public int getHeight() { + return (int) RENDER_SIZE; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/ktxt/ClientAccessorWrappers.kt b/Common/src/main/java/at/petrak/hexcasting/client/ktxt/ClientAccessorWrappers.kt index 5863d7f050..255a80b361 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/ktxt/ClientAccessorWrappers.kt +++ b/Common/src/main/java/at/petrak/hexcasting/client/ktxt/ClientAccessorWrappers.kt @@ -1,9 +1,10 @@ @file:JvmName("ClientAccessorWrappers") + package at.petrak.hexcasting.client.ktxt import at.petrak.hexcasting.mixin.accessor.client.AccessorMouseHandler import net.minecraft.client.MouseHandler var MouseHandler.accumulatedScroll: Double - get() = (this as AccessorMouseHandler).`hex$getAccumulatedScroll`() - set(value) = (this as AccessorMouseHandler).`hex$setAccumulatedScroll`(value) + get() = (this as AccessorMouseHandler).`hex$getAccumulatedScroll`() + set(value) = (this as AccessorMouseHandler).`hex$setAccumulatedScroll`(value) diff --git a/Common/src/main/java/at/petrak/hexcasting/client/model/AltioraLayer.java b/Common/src/main/java/at/petrak/hexcasting/client/model/AltioraLayer.java index a354d6eba3..dca5cf3183 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/model/AltioraLayer.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/model/AltioraLayer.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.client.model; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; @@ -17,36 +19,46 @@ import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.item.Items; -import static at.petrak.hexcasting.api.HexAPI.modLoc; +public class AltioraLayer<M extends EntityModel<AbstractClientPlayer>> + extends RenderLayer<AbstractClientPlayer, M> { + private static final ResourceLocation TEX_LOC = modLoc("textures/misc/altiora.png"); + + private final ElytraModel<AbstractClientPlayer> elytraModel; + + public AltioraLayer(RenderLayerParent<AbstractClientPlayer, M> renderer, EntityModelSet ems) { + super(renderer); + this.elytraModel = new ElytraModel<>(ems.bakeLayer(HexModelLayers.ALTIORA)); + } + + @Override + public void render( + PoseStack ps, + MultiBufferSource buffer, + int packedLight, + AbstractClientPlayer player, + float limbSwing, + float limbSwingAmount, + float partialTick, + float ageInTicks, + float netHeadYaw, + float headPitch) { + var altiora = IXplatAbstractions.INSTANCE.getAltiora(player); + // do a best effort to not render over other elytra, although we can never patch up everything + var chestSlot = player.getItemBySlot(EquipmentSlot.CHEST); + if (altiora != null && !chestSlot.is(Items.ELYTRA)) { + ps.pushPose(); + ps.translate(0.0, 0.0, 0.125); + + this.getParentModel().copyPropertiesTo(this.elytraModel); + this.elytraModel.setupAnim( + player, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); + VertexConsumer verts = + ItemRenderer.getArmorFoilBuffer( + buffer, RenderType.armorCutoutNoCull(TEX_LOC), false, true); + this.elytraModel.renderToBuffer( + ps, verts, packedLight, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F); -public class AltioraLayer<M extends EntityModel<AbstractClientPlayer>> extends RenderLayer<AbstractClientPlayer, M> { - private static final ResourceLocation TEX_LOC = modLoc("textures/misc/altiora.png"); - - private final ElytraModel<AbstractClientPlayer> elytraModel; - - public AltioraLayer(RenderLayerParent<AbstractClientPlayer, M> renderer, EntityModelSet ems) { - super(renderer); - this.elytraModel = new ElytraModel<>(ems.bakeLayer(HexModelLayers.ALTIORA)); - } - - @Override - public void render(PoseStack ps, MultiBufferSource buffer, int packedLight, AbstractClientPlayer player, - float limbSwing, float limbSwingAmount, float partialTick, float ageInTicks, float netHeadYaw, - float headPitch) { - var altiora = IXplatAbstractions.INSTANCE.getAltiora(player); - // do a best effort to not render over other elytra, although we can never patch up everything - var chestSlot = player.getItemBySlot(EquipmentSlot.CHEST); - if (altiora != null && !chestSlot.is(Items.ELYTRA)) { - ps.pushPose(); - ps.translate(0.0, 0.0, 0.125); - - this.getParentModel().copyPropertiesTo(this.elytraModel); - this.elytraModel.setupAnim(player, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); - VertexConsumer verts = ItemRenderer.getArmorFoilBuffer( - buffer, RenderType.armorCutoutNoCull(TEX_LOC), false, true); - this.elytraModel.renderToBuffer(ps, verts, packedLight, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F); - - ps.popPose(); - } - } + ps.popPose(); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/model/HexModelLayers.java b/Common/src/main/java/at/petrak/hexcasting/client/model/HexModelLayers.java index 11dc412327..7f14ff97ca 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/model/HexModelLayers.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/model/HexModelLayers.java @@ -1,34 +1,33 @@ package at.petrak.hexcasting.client.model; -import net.minecraft.client.model.ElytraModel; -import net.minecraft.client.model.geom.ModelLayerLocation; -import net.minecraft.client.model.geom.builders.LayerDefinition; +import static at.petrak.hexcasting.api.HexAPI.modLoc; import java.util.function.BiConsumer; import java.util.function.Supplier; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; +import net.minecraft.client.model.ElytraModel; +import net.minecraft.client.model.geom.ModelLayerLocation; +import net.minecraft.client.model.geom.builders.LayerDefinition; // https://github.com/VazkiiMods/Botania/blob/1.19.x/Xplat/src/main/java/vazkii/botania/client/model/BotaniaModelLayers.java public class HexModelLayers { - public static final ModelLayerLocation ALTIORA = make("altiora"); - - public static final ModelLayerLocation ROBES = make("robes"); - - private static ModelLayerLocation make(String name) { - return make(name, "main"); - } - - private static ModelLayerLocation make(String name, String layer) { - // Don't add to vanilla's ModelLayers. It seems to only be used for error checking - // And would be annoying to do under Forge's parallel mod loading - return new ModelLayerLocation(modLoc(name), layer); - } - - // moving this stuff into the same file: - // https://github.com/VazkiiMods/Botania/blob/1.19.x/Xplat/src/main/java/vazkii/botania/client/model/BotaniaLayerDefinitions.java - public static void init(BiConsumer<ModelLayerLocation, Supplier<LayerDefinition>> consumer) { - consumer.accept(ALTIORA, ElytraModel::createLayer); - consumer.accept(ROBES, HexRobesModels::variant1); - } + public static final ModelLayerLocation ALTIORA = make("altiora"); + + public static final ModelLayerLocation ROBES = make("robes"); + + private static ModelLayerLocation make(String name) { + return make(name, "main"); + } + + private static ModelLayerLocation make(String name, String layer) { + // Don't add to vanilla's ModelLayers. It seems to only be used for error checking + // And would be annoying to do under Forge's parallel mod loading + return new ModelLayerLocation(modLoc(name), layer); + } + + // moving this stuff into the same file: + // https://github.com/VazkiiMods/Botania/blob/1.19.x/Xplat/src/main/java/vazkii/botania/client/model/BotaniaLayerDefinitions.java + public static void init(BiConsumer<ModelLayerLocation, Supplier<LayerDefinition>> consumer) { + consumer.accept(ALTIORA, ElytraModel::createLayer); + consumer.accept(ROBES, HexRobesModels::variant1); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/model/HexRobesModels.java b/Common/src/main/java/at/petrak/hexcasting/client/model/HexRobesModels.java index 7f35494cab..859ee1e366 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/model/HexRobesModels.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/model/HexRobesModels.java @@ -4,67 +4,99 @@ // Exported for Minecraft version 1.17 or later with Mojang mappings // Paste this class into your mod and generate all required imports +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import net.minecraft.client.model.geom.ModelLayerLocation; import net.minecraft.client.model.geom.PartPose; import net.minecraft.client.model.geom.builders.*; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class HexRobesModels { - // This layer location should be baked with EntityRendererProvider.Context in the entity renderer and passed into - // this model's constructor - public static final ModelLayerLocation LAYER_LOCATION = new ModelLayerLocation(modLoc("robes"), "main"); + // This layer location should be baked with EntityRendererProvider.Context in the entity renderer + // and passed into + // this model's constructor + public static final ModelLayerLocation LAYER_LOCATION = + new ModelLayerLocation(modLoc("robes"), "main"); - public static LayerDefinition variant1() { - MeshDefinition meshdefinition = new MeshDefinition(); - PartDefinition partdefinition = meshdefinition.getRoot(); + public static LayerDefinition variant1() { + MeshDefinition meshdefinition = new MeshDefinition(); + PartDefinition partdefinition = meshdefinition.getRoot(); - PartDefinition Hood = partdefinition.addOrReplaceChild("Hood", - CubeListBuilder.create() - .texOffs(0, 0).addBox(-8.0F, 0.0F, 0.0F, 8.0F, 8.0F, 8.0F, new CubeDeformation(0.0F)) - .texOffs(0, 16).addBox(-8.0F, 0.0F, 0.0F, 8.0F, 8.0F, 8.0F, new CubeDeformation(0.0F)), - PartPose.offset(4.0F, -8.0F, -4.0F)); + PartDefinition Hood = + partdefinition.addOrReplaceChild( + "Hood", + CubeListBuilder.create() + .texOffs(0, 0) + .addBox(-8.0F, 0.0F, 0.0F, 8.0F, 8.0F, 8.0F, new CubeDeformation(0.0F)) + .texOffs(0, 16) + .addBox(-8.0F, 0.0F, 0.0F, 8.0F, 8.0F, 8.0F, new CubeDeformation(0.0F)), + PartPose.offset(4.0F, -8.0F, -4.0F)); - PartDefinition Horns = partdefinition.addOrReplaceChild("Horns", - CubeListBuilder.create() - .texOffs(24, 0).addBox(-8.0F, 0.0F, 0.0F, 8.0F, 4.0F, 0.0F, new CubeDeformation(0.0F)) - .texOffs(24, 0).mirror().addBox(9.5F, 0.0F, 0.0F, 8.0F, 4.0F, 0.0F, new CubeDeformation(0.0F)) - .mirror(false), - PartPose.offset(-4.8F, -8.2F, 0.0F)); + PartDefinition Horns = + partdefinition.addOrReplaceChild( + "Horns", + CubeListBuilder.create() + .texOffs(24, 0) + .addBox(-8.0F, 0.0F, 0.0F, 8.0F, 4.0F, 0.0F, new CubeDeformation(0.0F)) + .texOffs(24, 0) + .mirror() + .addBox(9.5F, 0.0F, 0.0F, 8.0F, 4.0F, 0.0F, new CubeDeformation(0.0F)) + .mirror(false), + PartPose.offset(-4.8F, -8.2F, 0.0F)); - PartDefinition Torso = partdefinition.addOrReplaceChild("Torso", - CubeListBuilder.create() - .texOffs(40, 0).addBox(-8.0F, 0.0F, 0.0F, 8.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)) - .texOffs(40, 16).addBox(-8.0F, 0.0F, 0.0F, 8.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)), - PartPose.offset(4.0F, 0.0F, -2.0F)); + PartDefinition Torso = + partdefinition.addOrReplaceChild( + "Torso", + CubeListBuilder.create() + .texOffs(40, 0) + .addBox(-8.0F, 0.0F, 0.0F, 8.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)) + .texOffs(40, 16) + .addBox(-8.0F, 0.0F, 0.0F, 8.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)), + PartPose.offset(4.0F, 0.0F, -2.0F)); - PartDefinition Arms = partdefinition.addOrReplaceChild("Arms", - CubeListBuilder.create() - .texOffs(0, 32).addBox(-4.0F, 0.0F, 0.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)) - .texOffs(0, 32).mirror().addBox(8.0F, 0.0F, 0.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)) - .mirror(false), - PartPose.offset(-4.0F, 0.0F, -2.0F)); + PartDefinition Arms = + partdefinition.addOrReplaceChild( + "Arms", + CubeListBuilder.create() + .texOffs(0, 32) + .addBox(-4.0F, 0.0F, 0.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)) + .texOffs(0, 32) + .mirror() + .addBox(8.0F, 0.0F, 0.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)) + .mirror(false), + PartPose.offset(-4.0F, 0.0F, -2.0F)); - PartDefinition Skirt = partdefinition.addOrReplaceChild("Skirt", CubeListBuilder.create(), - PartPose.offset(0.0F, 12.0F, -2.0F)); + PartDefinition Skirt = + partdefinition.addOrReplaceChild( + "Skirt", CubeListBuilder.create(), PartPose.offset(0.0F, 12.0F, -2.0F)); - PartDefinition Left_r1 = Skirt.addOrReplaceChild("Left_r1", - CubeListBuilder.create() - .texOffs(48, 32).mirror().addBox(0.1F, 0.0F, -4.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)) - .mirror(false), - PartPose.offsetAndRotation(0.0F, 0.0F, 4.0F, 0.0F, 0.0F, -0.1309F)); + PartDefinition Left_r1 = + Skirt.addOrReplaceChild( + "Left_r1", + CubeListBuilder.create() + .texOffs(48, 32) + .mirror() + .addBox(0.1F, 0.0F, -4.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)) + .mirror(false), + PartPose.offsetAndRotation(0.0F, 0.0F, 4.0F, 0.0F, 0.0F, -0.1309F)); - PartDefinition Right_r1 = Skirt.addOrReplaceChild("Right_r1", - CubeListBuilder.create() - .texOffs(48, 32).addBox(-4.0F, 0.0F, -4.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)), - PartPose.offsetAndRotation(0.0F, 0.0F, 4.0F, 0.0F, 0.0F, 0.1309F)); + PartDefinition Right_r1 = + Skirt.addOrReplaceChild( + "Right_r1", + CubeListBuilder.create() + .texOffs(48, 32) + .addBox(-4.0F, 0.0F, -4.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)), + PartPose.offsetAndRotation(0.0F, 0.0F, 4.0F, 0.0F, 0.0F, 0.1309F)); - PartDefinition Legs = partdefinition.addOrReplaceChild("Legs", - CubeListBuilder.create().texOffs(16, 41) - .addBox(-4.0F, 0.0F, 0.0F, 4.0F, 3.0F, 4.0F, new CubeDeformation(0.0F)) - .texOffs(16, 41).addBox(0.0F, 0.0F, 0.0F, 4.0F, 3.0F, 4.0F, new CubeDeformation(0.0F)), - PartPose.offset(0.0F, 21.0F, -2.0F)); + PartDefinition Legs = + partdefinition.addOrReplaceChild( + "Legs", + CubeListBuilder.create() + .texOffs(16, 41) + .addBox(-4.0F, 0.0F, 0.0F, 4.0F, 3.0F, 4.0F, new CubeDeformation(0.0F)) + .texOffs(16, 41) + .addBox(0.0F, 0.0F, 0.0F, 4.0F, 3.0F, 4.0F, new CubeDeformation(0.0F)), + PartPose.offset(0.0F, 21.0F, -2.0F)); - return LayerDefinition.create(meshdefinition, 64, 64); - } -} \ No newline at end of file + return LayerDefinition.create(meshdefinition, 64, 64); + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/client/model/MyOwnArmorModelWithBlackjackAndHookers.java b/Common/src/main/java/at/petrak/hexcasting/client/model/MyOwnArmorModelWithBlackjackAndHookers.java index fc63fcdf72..5c69725b76 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/model/MyOwnArmorModelWithBlackjackAndHookers.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/model/MyOwnArmorModelWithBlackjackAndHookers.java @@ -10,76 +10,88 @@ // https://github.com/VazkiiMods/Botania/blob/1.19.x/Xplat/src/main/java/vazkii/botania/client/model/armor/ArmorModel.java public class MyOwnArmorModelWithBlackjackAndHookers extends HumanoidModel<LivingEntity> { - protected final EquipmentSlot slot; + protected final EquipmentSlot slot; - public MyOwnArmorModelWithBlackjackAndHookers(ModelPart root, EquipmentSlot slot) { - super(root); - this.slot = slot; - } + public MyOwnArmorModelWithBlackjackAndHookers(ModelPart root, EquipmentSlot slot) { + super(root); + this.slot = slot; + } - // [VanillaCopy] ArmorStandArmorModel.setupAnim because armor stands are dumb - // This fixes the armor "breathing" and helmets always facing south on armor stands - @Override - public void setupAnim(LivingEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, - float netHeadYaw, float headPitch) { - if (!(entity instanceof ArmorStand entityIn)) { - super.setupAnim(entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); - return; - } + // [VanillaCopy] ArmorStandArmorModel.setupAnim because armor stands are dumb + // This fixes the armor "breathing" and helmets always facing south on armor stands + @Override + public void setupAnim( + LivingEntity entity, + float limbSwing, + float limbSwingAmount, + float ageInTicks, + float netHeadYaw, + float headPitch) { + if (!(entity instanceof ArmorStand entityIn)) { + super.setupAnim(entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); + return; + } - this.head.xRot = ((float) Math.PI / 180F) * entityIn.getHeadPose().getX(); - this.head.yRot = ((float) Math.PI / 180F) * entityIn.getHeadPose().getY(); - this.head.zRot = ((float) Math.PI / 180F) * entityIn.getHeadPose().getZ(); - this.head.setPos(0.0F, 1.0F, 0.0F); - this.body.xRot = ((float) Math.PI / 180F) * entityIn.getBodyPose().getX(); - this.body.yRot = ((float) Math.PI / 180F) * entityIn.getBodyPose().getY(); - this.body.zRot = ((float) Math.PI / 180F) * entityIn.getBodyPose().getZ(); - this.leftArm.xRot = ((float) Math.PI / 180F) * entityIn.getLeftArmPose().getX(); - this.leftArm.yRot = ((float) Math.PI / 180F) * entityIn.getLeftArmPose().getY(); - this.leftArm.zRot = ((float) Math.PI / 180F) * entityIn.getLeftArmPose().getZ(); - this.rightArm.xRot = ((float) Math.PI / 180F) * entityIn.getRightArmPose().getX(); - this.rightArm.yRot = ((float) Math.PI / 180F) * entityIn.getRightArmPose().getY(); - this.rightArm.zRot = ((float) Math.PI / 180F) * entityIn.getRightArmPose().getZ(); - this.leftLeg.xRot = ((float) Math.PI / 180F) * entityIn.getLeftLegPose().getX(); - this.leftLeg.yRot = ((float) Math.PI / 180F) * entityIn.getLeftLegPose().getY(); - this.leftLeg.zRot = ((float) Math.PI / 180F) * entityIn.getLeftLegPose().getZ(); - this.leftLeg.setPos(1.9F, 11.0F, 0.0F); - this.rightLeg.xRot = ((float) Math.PI / 180F) * entityIn.getRightLegPose().getX(); - this.rightLeg.yRot = ((float) Math.PI / 180F) * entityIn.getRightLegPose().getY(); - this.rightLeg.zRot = ((float) Math.PI / 180F) * entityIn.getRightLegPose().getZ(); - this.rightLeg.setPos(-1.9F, 11.0F, 0.0F); - this.hat.copyFrom(this.head); - } + this.head.xRot = ((float) Math.PI / 180F) * entityIn.getHeadPose().getX(); + this.head.yRot = ((float) Math.PI / 180F) * entityIn.getHeadPose().getY(); + this.head.zRot = ((float) Math.PI / 180F) * entityIn.getHeadPose().getZ(); + this.head.setPos(0.0F, 1.0F, 0.0F); + this.body.xRot = ((float) Math.PI / 180F) * entityIn.getBodyPose().getX(); + this.body.yRot = ((float) Math.PI / 180F) * entityIn.getBodyPose().getY(); + this.body.zRot = ((float) Math.PI / 180F) * entityIn.getBodyPose().getZ(); + this.leftArm.xRot = ((float) Math.PI / 180F) * entityIn.getLeftArmPose().getX(); + this.leftArm.yRot = ((float) Math.PI / 180F) * entityIn.getLeftArmPose().getY(); + this.leftArm.zRot = ((float) Math.PI / 180F) * entityIn.getLeftArmPose().getZ(); + this.rightArm.xRot = ((float) Math.PI / 180F) * entityIn.getRightArmPose().getX(); + this.rightArm.yRot = ((float) Math.PI / 180F) * entityIn.getRightArmPose().getY(); + this.rightArm.zRot = ((float) Math.PI / 180F) * entityIn.getRightArmPose().getZ(); + this.leftLeg.xRot = ((float) Math.PI / 180F) * entityIn.getLeftLegPose().getX(); + this.leftLeg.yRot = ((float) Math.PI / 180F) * entityIn.getLeftLegPose().getY(); + this.leftLeg.zRot = ((float) Math.PI / 180F) * entityIn.getLeftLegPose().getZ(); + this.leftLeg.setPos(1.9F, 11.0F, 0.0F); + this.rightLeg.xRot = ((float) Math.PI / 180F) * entityIn.getRightLegPose().getX(); + this.rightLeg.yRot = ((float) Math.PI / 180F) * entityIn.getRightLegPose().getY(); + this.rightLeg.zRot = ((float) Math.PI / 180F) * entityIn.getRightLegPose().getZ(); + this.rightLeg.setPos(-1.9F, 11.0F, 0.0F); + this.hat.copyFrom(this.head); + } - @Override - public void renderToBuffer(PoseStack ms, VertexConsumer buffer, int light, int overlay, float r, float g, float b - , float a) { - setPartVisibility(slot); - super.renderToBuffer(ms, buffer, light, overlay, r, g, b, a); - } + @Override + public void renderToBuffer( + PoseStack ms, + VertexConsumer buffer, + int light, + int overlay, + float r, + float g, + float b, + float a) { + setPartVisibility(slot); + super.renderToBuffer(ms, buffer, light, overlay, r, g, b, a); + } - // [VanillaCopy] HumanoidArmorLayer - private void setPartVisibility(EquipmentSlot slot) { - setAllVisible(false); - switch (slot) { - case HEAD -> { - head.visible = true; - hat.visible = true; - } - case CHEST -> { - body.visible = true; - rightArm.visible = true; - leftArm.visible = true; - } - case LEGS -> { - body.visible = true; - rightLeg.visible = true; - leftLeg.visible = true; - } - case FEET -> { - rightLeg.visible = true; - leftLeg.visible = true; - } - } - } + // [VanillaCopy] HumanoidArmorLayer + private void setPartVisibility(EquipmentSlot slot) { + setAllVisible(false); + switch (slot) { + case HEAD -> { + head.visible = true; + hat.visible = true; + } + case CHEST -> { + body.visible = true; + rightArm.visible = true; + leftArm.visible = true; + } + case LEGS -> { + body.visible = true; + rightLeg.visible = true; + leftLeg.visible = true; + } + case FEET -> { + rightLeg.visible = true; + leftLeg.visible = true; + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/particles/ConjureParticle.java b/Common/src/main/java/at/petrak/hexcasting/client/particles/ConjureParticle.java index 122e536e75..289fd18f9f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/particles/ConjureParticle.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/particles/ConjureParticle.java @@ -9,6 +9,7 @@ import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.Tesselator; import com.mojang.blaze3d.vertex.VertexFormat; +import java.util.Random; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.particle.*; @@ -18,107 +19,118 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Random; - public class ConjureParticle extends TextureSheetParticle { - private static final Random RANDOM = new Random(); - - private final SpriteSet sprites; - - ConjureParticle(ClientLevel pLevel, double x, double y, double z, double dx, double dy, double dz, - SpriteSet pSprites, int color) { - super(pLevel, x, y, z, dx, dy, dz); - this.quadSize *= 0.9f; - this.setParticleSpeed(dx, dy, dz); - - var r = FastColor.ARGB32.red(color); - var g = FastColor.ARGB32.green(color); - var b = FastColor.ARGB32.blue(color); - this.setColor(r / 255f, g / 255f, b / 255f); - this.setAlpha(0.3f); - - this.friction = 0.96F; - this.gravity = dy != 0 && dx != 0 && dz != 0 ? -0.01F : 0F; - this.speedUpWhenYMotionIsBlocked = true; - this.sprites = pSprites; - - this.roll = RANDOM.nextFloat(360); - this.oRoll = this.roll; - - this.lifetime = (int) (64.0 / ((Math.random() + 3f) * 0.25f)); - this.hasPhysics = false; - this.setSpriteFromAge(pSprites); - } - - public @NotNull ParticleRenderType getRenderType() { - return CONJURE_RENDER_TYPE; - } - - public void tick() { - super.tick(); - this.setSpriteFromAge(this.sprites); - this.alpha = 1.0f - ((float) this.age / (float) this.lifetime); - this.alpha *= 0.3f; - this.quadSize *= 0.96f; - } - - public void setSpriteFromAge(@NotNull SpriteSet pSprite) { - if (!this.removed) { - int age = this.age * 4; - if (age > this.lifetime) { - age /= 4; - } - this.setSprite(pSprite.get(age, this.lifetime)); - } - } - - public static class Provider implements ParticleProvider<ConjureParticleOptions> { - private final SpriteSet sprite; - - public Provider(SpriteSet pSprites) { - this.sprite = pSprites; - } - - @Nullable - @Override - public Particle createParticle(ConjureParticleOptions type, ClientLevel level, - double pX, double pY, double pZ, - double pXSpeed, double pYSpeed, double pZSpeed) { - return new ConjureParticle(level, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed, this.sprite, type.color()); - } - } - - // https://github.com/VazkiiMods/Botania/blob/db85d778ab23f44c11181209319066d1f04a9e3d/Xplat/src/main/java/vazkii/botania/client/fx/FXWisp.java - private record ConjureRenderType() implements ParticleRenderType { - @Override - public void begin(BufferBuilder buf, TextureManager texMan) { - Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer(); - RenderSystem.depthMask(false); - RenderSystem.enableBlend(); - RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE); - - RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_PARTICLES); - var tex = texMan.getTexture(TextureAtlas.LOCATION_PARTICLES); - IClientXplatAbstractions.INSTANCE.setFilterSave(tex, true, false); - buf.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.PARTICLE); - RenderSystem.enableDepthTest(); - } - - @Override - public void end(Tesselator tess) { - tess.end(); - IClientXplatAbstractions.INSTANCE.restoreLastFilter( - Minecraft.getInstance().getTextureManager().getTexture(TextureAtlas.LOCATION_PARTICLES) - ); - RenderSystem.disableBlend(); - RenderSystem.depthMask(true); - } - - @Override - public String toString() { - return HexAPI.MOD_ID + ":conjure"; - } - } - - public static final ConjureRenderType CONJURE_RENDER_TYPE = new ConjureRenderType(); + private static final Random RANDOM = new Random(); + + private final SpriteSet sprites; + + ConjureParticle( + ClientLevel pLevel, + double x, + double y, + double z, + double dx, + double dy, + double dz, + SpriteSet pSprites, + int color) { + super(pLevel, x, y, z, dx, dy, dz); + this.quadSize *= 0.9f; + this.setParticleSpeed(dx, dy, dz); + + var r = FastColor.ARGB32.red(color); + var g = FastColor.ARGB32.green(color); + var b = FastColor.ARGB32.blue(color); + this.setColor(r / 255f, g / 255f, b / 255f); + this.setAlpha(0.3f); + + this.friction = 0.96F; + this.gravity = dy != 0 && dx != 0 && dz != 0 ? -0.01F : 0F; + this.speedUpWhenYMotionIsBlocked = true; + this.sprites = pSprites; + + this.roll = RANDOM.nextFloat(360); + this.oRoll = this.roll; + + this.lifetime = (int) (64.0 / ((Math.random() + 3f) * 0.25f)); + this.hasPhysics = false; + this.setSpriteFromAge(pSprites); + } + + public @NotNull ParticleRenderType getRenderType() { + return CONJURE_RENDER_TYPE; + } + + public void tick() { + super.tick(); + this.setSpriteFromAge(this.sprites); + this.alpha = 1.0f - ((float) this.age / (float) this.lifetime); + this.alpha *= 0.3f; + this.quadSize *= 0.96f; + } + + public void setSpriteFromAge(@NotNull SpriteSet pSprite) { + if (!this.removed) { + int age = this.age * 4; + if (age > this.lifetime) { + age /= 4; + } + this.setSprite(pSprite.get(age, this.lifetime)); + } + } + + public static class Provider implements ParticleProvider<ConjureParticleOptions> { + private final SpriteSet sprite; + + public Provider(SpriteSet pSprites) { + this.sprite = pSprites; + } + + @Nullable @Override + public Particle createParticle( + ConjureParticleOptions type, + ClientLevel level, + double pX, + double pY, + double pZ, + double pXSpeed, + double pYSpeed, + double pZSpeed) { + return new ConjureParticle( + level, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed, this.sprite, type.color()); + } + } + + // https://github.com/VazkiiMods/Botania/blob/db85d778ab23f44c11181209319066d1f04a9e3d/Xplat/src/main/java/vazkii/botania/client/fx/FXWisp.java + private record ConjureRenderType() implements ParticleRenderType { + @Override + public void begin(BufferBuilder buf, TextureManager texMan) { + Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer(); + RenderSystem.depthMask(false); + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE); + + RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_PARTICLES); + var tex = texMan.getTexture(TextureAtlas.LOCATION_PARTICLES); + IClientXplatAbstractions.INSTANCE.setFilterSave(tex, true, false); + buf.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.PARTICLE); + RenderSystem.enableDepthTest(); + } + + @Override + public void end(Tesselator tess) { + tess.end(); + IClientXplatAbstractions.INSTANCE.restoreLastFilter( + Minecraft.getInstance().getTextureManager().getTexture(TextureAtlas.LOCATION_PARTICLES)); + RenderSystem.disableBlend(); + RenderSystem.depthMask(true); + } + + @Override + public String toString() { + return HexAPI.MOD_ID + ":conjure"; + } + } + + public static final ConjureRenderType CONJURE_RENDER_TYPE = new ConjureRenderType(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/GaslightingTracker.java b/Common/src/main/java/at/petrak/hexcasting/client/render/GaslightingTracker.java index c57a5abd49..8d05682f84 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/GaslightingTracker.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/GaslightingTracker.java @@ -1,27 +1,27 @@ package at.petrak.hexcasting.client.render; -import net.minecraft.resources.ResourceLocation; - import static at.petrak.hexcasting.api.HexAPI.modLoc; +import net.minecraft.resources.ResourceLocation; + // *nothing* that changes can be looked at for changes public class GaslightingTracker { - private static int GASLIGHTING_AMOUNT = 0; - private static int LOOKING_COOLDOWN_MAX = 40; - private static int LOOKING_COOLDOWN = LOOKING_COOLDOWN_MAX; + private static int GASLIGHTING_AMOUNT = 0; + private static int LOOKING_COOLDOWN_MAX = 40; + private static int LOOKING_COOLDOWN = LOOKING_COOLDOWN_MAX; - public static ResourceLocation GASLIGHTING_PRED = modLoc("variant"); + public static ResourceLocation GASLIGHTING_PRED = modLoc("variant"); - public static int getGaslightingAmount() { - LOOKING_COOLDOWN = LOOKING_COOLDOWN_MAX; - return GASLIGHTING_AMOUNT; - } + public static int getGaslightingAmount() { + LOOKING_COOLDOWN = LOOKING_COOLDOWN_MAX; + return GASLIGHTING_AMOUNT; + } - public static void postFrameCheckRendered() { - if (LOOKING_COOLDOWN > 0) { - LOOKING_COOLDOWN -= 1; - } else { - GASLIGHTING_AMOUNT += 1; - } - } + public static void postFrameCheckRendered() { + if (LOOKING_COOLDOWN > 0) { + LOOKING_COOLDOWN -= 1; + } else { + GASLIGHTING_AMOUNT += 1; + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/HexAdditionalRenderers.java b/Common/src/main/java/at/petrak/hexcasting/client/render/HexAdditionalRenderers.java index 1861a9b8fb..29ceb53d81 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/HexAdditionalRenderers.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/HexAdditionalRenderers.java @@ -14,6 +14,8 @@ import com.mojang.blaze3d.vertex.Tesselator; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.datafixers.util.Pair; +import java.util.List; +import java.util.function.BiConsumer; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.multiplayer.ClientLevel; @@ -29,195 +31,192 @@ import net.minecraft.world.phys.Vec3; import org.joml.Vector3f; -import java.util.List; -import java.util.function.BiConsumer; - public class HexAdditionalRenderers { - public static void overlayLevel(PoseStack ps, float partialTick) { - var player = Minecraft.getInstance().player; - if (player != null) { - var sentinel = IXplatAbstractions.INSTANCE.getSentinel(player); - if (sentinel != null && player.level().dimension().equals(sentinel.dimension())) { - renderSentinel(sentinel, player, ps, partialTick); - } - } - } - - public static void overlayGui(GuiGraphics graphics, float partialTicks) { - tryRenderScryingLensOverlay(graphics, partialTicks); - } - - private static void renderSentinel(Sentinel sentinel, LocalPlayer owner, - PoseStack ps, float partialTicks) { - ps.pushPose(); - - // zero vector is the player - var mc = Minecraft.getInstance(); - var camera = mc.gameRenderer.getMainCamera(); - var playerPos = camera.getPosition(); - ps.translate( - sentinel.position().x - playerPos.x, - sentinel.position().y - playerPos.y, - sentinel.position().z - playerPos.z); - - var time = ClientTickCounter.getTotal() / 2; - var bobSpeed = 1f / 20; - var magnitude = 0.1f; - ps.translate(0, Mth.sin(bobSpeed * time) * magnitude, 0); - var spinSpeed = 1f / 30; - ps.mulPose(QuaternionfUtils.fromXYZ(new Vector3f(0, spinSpeed * time, 0))); - if (sentinel.extendsRange()) { - ps.mulPose(QuaternionfUtils.fromXYZ(new Vector3f(spinSpeed * time / 8f, 0, 0))); - } - - float scale = 0.5f; - ps.scale(scale, scale, scale); - - - var tess = Tesselator.getInstance(); - var buf = tess.getBuilder(); - var neo = ps.last().pose(); - RenderSystem.enableBlend(); - RenderSystem.setShader(GameRenderer::getRendertypeLinesShader); - RenderSystem.disableDepthTest(); - RenderSystem.disableCull(); - RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); - RenderSystem.lineWidth(5f); - - var pigment = IXplatAbstractions.INSTANCE.getPigment(owner); - var colProvider = pigment.getColorProvider(); - BiConsumer<float[], float[]> v = (l, r) -> { - int lcolor = colProvider.getColor(time, new Vec3(l[0], l[1], l[2])), - rcolor = colProvider.getColor(time, new Vec3(r[0], r[1], r[2])); - var normal = new Vector3f(r[0] - l[0], r[1] - l[1], r[2] - l[2]); - normal.normalize(); - buf.vertex(neo, l[0], l[1], l[2]) - .color(lcolor) - .normal(ps.last().normal(), normal.x(), normal.y(), normal.z()) - .endVertex(); - buf.vertex(neo, r[0], r[1], r[2]) - .color(rcolor) - .normal(ps.last().normal(), -normal.x(), -normal.y(), -normal.z()) - .endVertex(); - }; - - // Icosahedron inscribed inside the unit sphere - buf.begin(VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR_NORMAL); - for (int side = 0; side <= 1; side++) { - var ring = (side == 0) ? Icos.BOTTOM_RING : Icos.TOP_RING; - var apex = (side == 0) ? Icos.BOTTOM : Icos.TOP; - - // top & bottom spider - for (int i = 0; i < 5; i++) { - v.accept(apex, ring[i]); - } - - // ring around - for (int i = 0; i < 5; i++) { - v.accept(ring[i % 5], ring[(i + 1) % 5]); - } - } - // center band - for (int i = 0; i < 5; i++) { - var bottom = Icos.BOTTOM_RING[i]; - v.accept(Icos.TOP_RING[(i + 2) % 5], bottom); - v.accept(bottom, Icos.TOP_RING[(i + 3) % 5]); - } - tess.end(); - - RenderSystem.enableDepthTest(); - RenderSystem.enableCull(); - ps.popPose(); - } - - private static class Icos { - public static float[] TOP = {0, 1, 0}; - public static float[] BOTTOM = {0, -1, 0}; - public static float[][] TOP_RING = new float[5][]; - public static float[][] BOTTOM_RING = new float[5][]; - - static { - var theta = (float) Mth.atan2(0.5, 1); - for (int i = 0; i < 5; i++) { - var phi = (float) i / 5f * Mth.TWO_PI; - var x = Mth.cos(theta) * Mth.cos(phi); - var y = Mth.sin(theta); - var z = Mth.cos(theta) * Mth.sin(phi); - TOP_RING[i] = new float[]{x, y, z}; - BOTTOM_RING[i] = new float[]{-x, -y, -z}; - } - } - } - - private static void tryRenderScryingLensOverlay(GuiGraphics graphics, float partialTicks) { - var mc = Minecraft.getInstance(); - var ps = graphics.pose(); - - LocalPlayer player = mc.player; - ClientLevel level = mc.level; - if (player == null || level == null) { - return; - } - - if (player.getAttributeValue(HexAttributes.SCRY_SIGHT) <= 0.0) - return; - - var hitRes = mc.hitResult; - if (hitRes != null && hitRes.getType() == HitResult.Type.BLOCK) { - var bhr = (BlockHitResult) hitRes; - var pos = bhr.getBlockPos(); - var bs = level.getBlockState(pos); - - var lines = ScryingLensOverlayRegistry.getLines(bs, pos, player, level, bhr.getDirection()); - - int totalHeight = 8; - List<Pair<ItemStack, List<FormattedText>>> actualLines = Lists.newArrayList(); - - var window = mc.getWindow(); - var maxWidth = (int) (window.getGuiScaledWidth() / 2f * 0.8f); - - for (var pair : lines) { - totalHeight += mc.font.lineHeight + 6; - var text = pair.getSecond(); - var textLines = mc.font.getSplitter().splitLines(text, maxWidth, Style.EMPTY); - - actualLines.add(Pair.of(pair.getFirst(), textLines)); - - if (textLines.size() > 1) { - totalHeight += mc.font.lineHeight * (textLines.size() - 1); - } - } - - if (!lines.isEmpty()) { - var x = window.getGuiScaledWidth() / 2f + 8f; - var y = window.getGuiScaledHeight() / 2f - totalHeight; - ps.pushPose(); - ps.translate(x, y, 0); - - for (var pair : actualLines) { - var stack = pair.getFirst(); - if (!stack.isEmpty()) { - // this draws centered in the Y ... - graphics.renderItem(pair.getFirst(), 0, 0); - } - int tx = stack.isEmpty() ? 0 : 18; - int ty = 5; - // but this draws where y=0 is the baseline - var text = pair.getSecond(); - - for (var line : text) { - var actualLine = Language.getInstance().getVisualOrder(line); - graphics.drawString(mc.font, actualLine, tx, ty, 0xffffffff); - ps.translate(0, mc.font.lineHeight, 0); - } - if (text.isEmpty()) { - ps.translate(0, mc.font.lineHeight, 0); - } - ps.translate(0, 6, 0); - } - - ps.popPose(); - } - } - } + public static void overlayLevel(PoseStack ps, float partialTick) { + var player = Minecraft.getInstance().player; + if (player != null) { + var sentinel = IXplatAbstractions.INSTANCE.getSentinel(player); + if (sentinel != null && player.level().dimension().equals(sentinel.dimension())) { + renderSentinel(sentinel, player, ps, partialTick); + } + } + } + + public static void overlayGui(GuiGraphics graphics, float partialTicks) { + tryRenderScryingLensOverlay(graphics, partialTicks); + } + + private static void renderSentinel( + Sentinel sentinel, LocalPlayer owner, PoseStack ps, float partialTicks) { + ps.pushPose(); + + // zero vector is the player + var mc = Minecraft.getInstance(); + var camera = mc.gameRenderer.getMainCamera(); + var playerPos = camera.getPosition(); + ps.translate( + sentinel.position().x - playerPos.x, + sentinel.position().y - playerPos.y, + sentinel.position().z - playerPos.z); + + var time = ClientTickCounter.getTotal() / 2; + var bobSpeed = 1f / 20; + var magnitude = 0.1f; + ps.translate(0, Mth.sin(bobSpeed * time) * magnitude, 0); + var spinSpeed = 1f / 30; + ps.mulPose(QuaternionfUtils.fromXYZ(new Vector3f(0, spinSpeed * time, 0))); + if (sentinel.extendsRange()) { + ps.mulPose(QuaternionfUtils.fromXYZ(new Vector3f(spinSpeed * time / 8f, 0, 0))); + } + + float scale = 0.5f; + ps.scale(scale, scale, scale); + + var tess = Tesselator.getInstance(); + var buf = tess.getBuilder(); + var neo = ps.last().pose(); + RenderSystem.enableBlend(); + RenderSystem.setShader(GameRenderer::getRendertypeLinesShader); + RenderSystem.disableDepthTest(); + RenderSystem.disableCull(); + RenderSystem.blendFunc( + GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + RenderSystem.lineWidth(5f); + + var pigment = IXplatAbstractions.INSTANCE.getPigment(owner); + var colProvider = pigment.getColorProvider(); + BiConsumer<float[], float[]> v = + (l, r) -> { + int lcolor = colProvider.getColor(time, new Vec3(l[0], l[1], l[2])), + rcolor = colProvider.getColor(time, new Vec3(r[0], r[1], r[2])); + var normal = new Vector3f(r[0] - l[0], r[1] - l[1], r[2] - l[2]); + normal.normalize(); + buf.vertex(neo, l[0], l[1], l[2]) + .color(lcolor) + .normal(ps.last().normal(), normal.x(), normal.y(), normal.z()) + .endVertex(); + buf.vertex(neo, r[0], r[1], r[2]) + .color(rcolor) + .normal(ps.last().normal(), -normal.x(), -normal.y(), -normal.z()) + .endVertex(); + }; + + // Icosahedron inscribed inside the unit sphere + buf.begin(VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR_NORMAL); + for (int side = 0; side <= 1; side++) { + var ring = (side == 0) ? Icos.BOTTOM_RING : Icos.TOP_RING; + var apex = (side == 0) ? Icos.BOTTOM : Icos.TOP; + + // top & bottom spider + for (int i = 0; i < 5; i++) { + v.accept(apex, ring[i]); + } + + // ring around + for (int i = 0; i < 5; i++) { + v.accept(ring[i % 5], ring[(i + 1) % 5]); + } + } + // center band + for (int i = 0; i < 5; i++) { + var bottom = Icos.BOTTOM_RING[i]; + v.accept(Icos.TOP_RING[(i + 2) % 5], bottom); + v.accept(bottom, Icos.TOP_RING[(i + 3) % 5]); + } + tess.end(); + + RenderSystem.enableDepthTest(); + RenderSystem.enableCull(); + ps.popPose(); + } + + private static class Icos { + public static float[] TOP = {0, 1, 0}; + public static float[] BOTTOM = {0, -1, 0}; + public static float[][] TOP_RING = new float[5][]; + public static float[][] BOTTOM_RING = new float[5][]; + + static { + var theta = (float) Mth.atan2(0.5, 1); + for (int i = 0; i < 5; i++) { + var phi = (float) i / 5f * Mth.TWO_PI; + var x = Mth.cos(theta) * Mth.cos(phi); + var y = Mth.sin(theta); + var z = Mth.cos(theta) * Mth.sin(phi); + TOP_RING[i] = new float[] {x, y, z}; + BOTTOM_RING[i] = new float[] {-x, -y, -z}; + } + } + } + + private static void tryRenderScryingLensOverlay(GuiGraphics graphics, float partialTicks) { + var mc = Minecraft.getInstance(); + var ps = graphics.pose(); + + LocalPlayer player = mc.player; + ClientLevel level = mc.level; + if (player == null || level == null) { + return; + } + + if (player.getAttributeValue(HexAttributes.SCRY_SIGHT) <= 0.0) return; + + var hitRes = mc.hitResult; + if (hitRes != null && hitRes.getType() == HitResult.Type.BLOCK) { + var bhr = (BlockHitResult) hitRes; + var pos = bhr.getBlockPos(); + var bs = level.getBlockState(pos); + + var lines = ScryingLensOverlayRegistry.getLines(bs, pos, player, level, bhr.getDirection()); + + int totalHeight = 8; + List<Pair<ItemStack, List<FormattedText>>> actualLines = Lists.newArrayList(); + + var window = mc.getWindow(); + var maxWidth = (int) (window.getGuiScaledWidth() / 2f * 0.8f); + + for (var pair : lines) { + totalHeight += mc.font.lineHeight + 6; + var text = pair.getSecond(); + var textLines = mc.font.getSplitter().splitLines(text, maxWidth, Style.EMPTY); + + actualLines.add(Pair.of(pair.getFirst(), textLines)); + + if (textLines.size() > 1) { + totalHeight += mc.font.lineHeight * (textLines.size() - 1); + } + } + + if (!lines.isEmpty()) { + var x = window.getGuiScaledWidth() / 2f + 8f; + var y = window.getGuiScaledHeight() / 2f - totalHeight; + ps.pushPose(); + ps.translate(x, y, 0); + + for (var pair : actualLines) { + var stack = pair.getFirst(); + if (!stack.isEmpty()) { + // this draws centered in the Y ... + graphics.renderItem(pair.getFirst(), 0, 0); + } + int tx = stack.isEmpty() ? 0 : 18; + int ty = 5; + // but this draws where y=0 is the baseline + var text = pair.getSecond(); + + for (var line : text) { + var actualLine = Language.getInstance().getVisualOrder(line); + graphics.drawString(mc.font, actualLine, tx, ty, 0xffffffff); + ps.translate(0, mc.font.lineHeight, 0); + } + if (text.isEmpty()) { + ps.translate(0, mc.font.lineHeight, 0); + } + ps.translate(0, 6, 0); + } + + ps.popPose(); + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/HexPatternLike.java b/Common/src/main/java/at/petrak/hexcasting/client/render/HexPatternLike.java index 1b82992398..97015f37d6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/HexPatternLike.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/HexPatternLike.java @@ -1,70 +1,75 @@ package at.petrak.hexcasting.client.render; import at.petrak.hexcasting.api.casting.math.HexPattern; -import net.minecraft.world.phys.Vec2; - import java.util.List; import java.util.Objects; import java.util.Set; +import net.minecraft.world.phys.Vec2; /** * A simple wrapper around the parts of HexPattern that are actually used for rendering. * - * This lets the pattern renderer work on arbitrary lists of vecs - this is never used in base hex but is included - * to future-proof and for if addons or something wants to use it. + * <p>This lets the pattern renderer work on arbitrary lists of vecs - this is never used in base + * hex but is included to future-proof and for if addons or something wants to use it. */ public interface HexPatternLike { - List<Vec2> getNonZappyPoints(); + List<Vec2> getNonZappyPoints(); - String getName(); + String getName(); - Set<Integer> getDups(); + Set<Integer> getDups(); - static HexPatternLike of(HexPattern pat){ - return new HexPatternLikeBecauseItsActuallyAHexPattern(pat); - } + static HexPatternLike of(HexPattern pat) { + return new HexPatternLikeBecauseItsActuallyAHexPattern(pat); + } - static HexPatternLike of(List<Vec2> lines, String name){ - return new PureLines(lines, name); - } + static HexPatternLike of(List<Vec2> lines, String name) { + return new PureLines(lines, name); + } - record HexPatternLikeBecauseItsActuallyAHexPattern(HexPattern pat) implements HexPatternLike{ - public List<Vec2> getNonZappyPoints(){ - return pat.toLines(1, Vec2.ZERO); - } + record HexPatternLikeBecauseItsActuallyAHexPattern(HexPattern pat) implements HexPatternLike { + public List<Vec2> getNonZappyPoints() { + return pat.toLines(1, Vec2.ZERO); + } - public String getName(){ - return pat.getStartDir() + "-" + pat.anglesSignature(); - } + public String getName() { + return pat.getStartDir() + "-" + pat.anglesSignature(); + } - public Set<Integer> getDups(){ - return RenderLib.findDupIndices(pat.positions()); - } - } + public Set<Integer> getDups() { + return RenderLib.findDupIndices(pat.positions()); + } + } - record PureLines(List<Vec2> lines, String name) implements HexPatternLike{ + record PureLines(List<Vec2> lines, String name) implements HexPatternLike { - public List<Vec2> getNonZappyPoints(){ - return lines; - } + public List<Vec2> getNonZappyPoints() { + return lines; + } - public String getName(){ - return name; - } + public String getName() { + return name; + } - public Set<Integer> getDups(){ - return RenderLib.findDupIndices( - lines().stream().map(p -> - // I hate mojang - new Vec2(p.x, p.y){ - @Override public boolean equals(Object other){ - if(other instanceof Vec2 otherVec) return p.equals(otherVec); - return false; - } + public Set<Integer> getDups() { + return RenderLib.findDupIndices( + lines().stream() + .map( + p -> + // I hate mojang + new Vec2(p.x, p.y) { + @Override + public boolean equals(Object other) { + if (other instanceof Vec2 otherVec) return p.equals(otherVec); + return false; + } - @Override public int hashCode(){ return Objects.hash(p.x, p.y); } - }).toList() - ); - } - } + @Override + public int hashCode() { + return Objects.hash(p.x, p.y); + } + }) + .toList()); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/HexPatternPoints.java b/Common/src/main/java/at/petrak/hexcasting/client/render/HexPatternPoints.java index 1a55d06b5e..7ff0f86e21 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/HexPatternPoints.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/HexPatternPoints.java @@ -1,134 +1,158 @@ package at.petrak.hexcasting.client.render; import com.google.common.collect.ImmutableList; -import net.minecraft.world.phys.Vec2; - import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import net.minecraft.world.phys.Vec2; /** - * static points making up a hex pattern to be rendered. It's used primarily for positioning, so we keep a - * number of extra values here to avoid recomputing them. + * static points making up a hex pattern to be rendered. It's used primarily for positioning, so we + * keep a number of extra values here to avoid recomputing them. */ public class HexPatternPoints { - public final ImmutableList<Vec2> zappyPoints; - public final ImmutableList<Vec2> zappyPointsScaled; - - public final ImmutableList<Vec2> dotsScaled; - - public final double rangeX; - public final double rangeY; - public final double finalScale; - - public final double fullWidth; - public final double fullHeight; - - private double minX = Double.MAX_VALUE; - private double minY = Double.MAX_VALUE; - - private final double offsetX; - private final double offsetY; - - private static final ConcurrentMap<String, HexPatternPoints> CACHED_STATIC_POINTS = new ConcurrentHashMap<>(); - - private HexPatternPoints(HexPatternLike patternlike, PatternSettings patSets, double seed) { - - List<Vec2> dots = patternlike.getNonZappyPoints(); - - // always do space calculations with the static version of the pattern - // so that it doesn't jump around resizing itself. - List<Vec2> zappyPoints = RenderLib.makeZappy(dots, patternlike.getDups(), - patSets.getHops(), patSets.getVariance(), 0f, patSets.getFlowIrregular(), - patSets.getReadabilityOffset(), patSets.getLastSegmentProp(), seed); - - - this.zappyPoints = ImmutableList.copyOf(zappyPoints); - double maxY = Double.MIN_VALUE; - double maxX = Double.MIN_VALUE; - for (Vec2 point : zappyPoints) { - minX = Math.min(minX, point.x); - maxX = Math.max(maxX, point.x); - minY = Math.min(minY, point.y); - maxY = Math.max(maxY, point.y); - } - rangeX = maxX - minX; - rangeY = maxY - minY; - - // scales the patterns so that each point is patSets.baseScale units apart - double baseScale = patSets.getBaseScale() / 1.5; - - // size of the pattern in pose space with no other adjustments - double baseWidth = rangeX * baseScale; - double baseHeight = rangeY * baseScale; - - // make sure that the scale fits within our min sizes - double scale = Math.max(1.0, Math.max( - (patSets.getMinWidth() - patSets.getStrokeWidthGuess()) / baseWidth, - (patSets.getMinHeight() - patSets.getStrokeWidthGuess()) / baseHeight) - ); - - boolean vertFit = patSets.getVertAlignment().fit; - boolean horFit = patSets.getHorAlignment().fit; - - // scale down if needed to fit in vertical space - if(vertFit){ - scale = Math.min(scale, (patSets.getTargetHeight() - 2 * patSets.getVertPadding() - patSets.getStrokeWidthGuess())/(baseHeight)); - } - - // scale down if needed to fit in horizontal space - if(horFit){ - scale = Math.min(scale, (patSets.getTargetWidth() - 2 * patSets.getHorPadding() - patSets.getStrokeWidthGuess())/(baseWidth)); - } - - finalScale = baseScale * scale; - double finalStroke = patSets.getStrokeWidth(finalScale); - - double inherentWidth = (baseWidth * scale) + 2 * patSets.getHorPadding() + finalStroke; - double inherentHeight = (baseHeight * scale) + 2 * patSets.getVertPadding() + finalStroke; - - // this is the amount of actual wiggle room we have for configurable position-ing. - double widthDiff = Math.max(patSets.getTargetWidth() - inherentWidth, 0); - double heightDiff = Math.max(patSets.getTargetHeight() - inherentHeight, 0); - - this.fullWidth = inherentWidth + widthDiff; - this.fullHeight = inherentHeight + heightDiff; - - // center in inherent space and put extra space according to alignment stuff - offsetX = ((inherentWidth - baseWidth * scale) / 2) + (widthDiff * patSets.getHorAlignment().amtInFront / 2); - offsetY = ((inherentHeight - baseHeight * scale) / 2) + (heightDiff * patSets.getVertAlignment().amtInFront / 2); - - this.zappyPointsScaled = ImmutableList.copyOf(scaleVecs(zappyPoints)); - this.dotsScaled = ImmutableList.copyOf(scaleVecs(dots)); - } - - public Vec2 scaleVec(Vec2 point){ - return new Vec2( - (float) (((point.x - this.minX) * this.finalScale) + this.offsetX), - (float) (((point.y - this.minY) * this.finalScale) + this.offsetY) - ); - } - - public List<Vec2> scaleVecs(List<Vec2> points){ - List<Vec2> scaledPoints = new ArrayList<>(); - for (Vec2 point : points) { - scaledPoints.add(scaleVec(point)); - } - return scaledPoints; - } - - - /** - * Gets the static points for the given pattern, settings, and seed. This is cached. - * - * This is used in rendering static patterns and positioning non-static patterns. - * - */ - public static HexPatternPoints getStaticPoints(HexPatternLike patternlike, PatternSettings patSets, double seed){ - - String cacheKey = patSets.getCacheKey(patternlike, seed); - - return CACHED_STATIC_POINTS.computeIfAbsent(cacheKey, (key) -> new HexPatternPoints(patternlike, patSets, seed) ); - } -} \ No newline at end of file + public final ImmutableList<Vec2> zappyPoints; + public final ImmutableList<Vec2> zappyPointsScaled; + + public final ImmutableList<Vec2> dotsScaled; + + public final double rangeX; + public final double rangeY; + public final double finalScale; + + public final double fullWidth; + public final double fullHeight; + + private double minX = Double.MAX_VALUE; + private double minY = Double.MAX_VALUE; + + private final double offsetX; + private final double offsetY; + + private static final ConcurrentMap<String, HexPatternPoints> CACHED_STATIC_POINTS = + new ConcurrentHashMap<>(); + + private HexPatternPoints(HexPatternLike patternlike, PatternSettings patSets, double seed) { + + List<Vec2> dots = patternlike.getNonZappyPoints(); + + // always do space calculations with the static version of the pattern + // so that it doesn't jump around resizing itself. + List<Vec2> zappyPoints = + RenderLib.makeZappy( + dots, + patternlike.getDups(), + patSets.getHops(), + patSets.getVariance(), + 0f, + patSets.getFlowIrregular(), + patSets.getReadabilityOffset(), + patSets.getLastSegmentProp(), + seed); + + this.zappyPoints = ImmutableList.copyOf(zappyPoints); + double maxY = Double.MIN_VALUE; + double maxX = Double.MIN_VALUE; + for (Vec2 point : zappyPoints) { + minX = Math.min(minX, point.x); + maxX = Math.max(maxX, point.x); + minY = Math.min(minY, point.y); + maxY = Math.max(maxY, point.y); + } + rangeX = maxX - minX; + rangeY = maxY - minY; + + // scales the patterns so that each point is patSets.baseScale units apart + double baseScale = patSets.getBaseScale() / 1.5; + + // size of the pattern in pose space with no other adjustments + double baseWidth = rangeX * baseScale; + double baseHeight = rangeY * baseScale; + + // make sure that the scale fits within our min sizes + double scale = + Math.max( + 1.0, + Math.max( + (patSets.getMinWidth() - patSets.getStrokeWidthGuess()) / baseWidth, + (patSets.getMinHeight() - patSets.getStrokeWidthGuess()) / baseHeight)); + + boolean vertFit = patSets.getVertAlignment().fit; + boolean horFit = patSets.getHorAlignment().fit; + + // scale down if needed to fit in vertical space + if (vertFit) { + scale = + Math.min( + scale, + (patSets.getTargetHeight() + - 2 * patSets.getVertPadding() + - patSets.getStrokeWidthGuess()) + / (baseHeight)); + } + + // scale down if needed to fit in horizontal space + if (horFit) { + scale = + Math.min( + scale, + (patSets.getTargetWidth() + - 2 * patSets.getHorPadding() + - patSets.getStrokeWidthGuess()) + / (baseWidth)); + } + + finalScale = baseScale * scale; + double finalStroke = patSets.getStrokeWidth(finalScale); + + double inherentWidth = (baseWidth * scale) + 2 * patSets.getHorPadding() + finalStroke; + double inherentHeight = (baseHeight * scale) + 2 * patSets.getVertPadding() + finalStroke; + + // this is the amount of actual wiggle room we have for configurable position-ing. + double widthDiff = Math.max(patSets.getTargetWidth() - inherentWidth, 0); + double heightDiff = Math.max(patSets.getTargetHeight() - inherentHeight, 0); + + this.fullWidth = inherentWidth + widthDiff; + this.fullHeight = inherentHeight + heightDiff; + + // center in inherent space and put extra space according to alignment stuff + offsetX = + ((inherentWidth - baseWidth * scale) / 2) + + (widthDiff * patSets.getHorAlignment().amtInFront / 2); + offsetY = + ((inherentHeight - baseHeight * scale) / 2) + + (heightDiff * patSets.getVertAlignment().amtInFront / 2); + + this.zappyPointsScaled = ImmutableList.copyOf(scaleVecs(zappyPoints)); + this.dotsScaled = ImmutableList.copyOf(scaleVecs(dots)); + } + + public Vec2 scaleVec(Vec2 point) { + return new Vec2( + (float) (((point.x - this.minX) * this.finalScale) + this.offsetX), + (float) (((point.y - this.minY) * this.finalScale) + this.offsetY)); + } + + public List<Vec2> scaleVecs(List<Vec2> points) { + List<Vec2> scaledPoints = new ArrayList<>(); + for (Vec2 point : points) { + scaledPoints.add(scaleVec(point)); + } + return scaledPoints; + } + + /** + * Gets the static points for the given pattern, settings, and seed. This is cached. + * + * <p>This is used in rendering static patterns and positioning non-static patterns. + */ + public static HexPatternPoints getStaticPoints( + HexPatternLike patternlike, PatternSettings patSets, double seed) { + + String cacheKey = patSets.getCacheKey(patternlike, seed); + + return CACHED_STATIC_POINTS.computeIfAbsent( + cacheKey, (key) -> new HexPatternPoints(patternlike, patSets, seed)); + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/PatternColors.java b/Common/src/main/java/at/petrak/hexcasting/client/render/PatternColors.java index fb64669834..6936c8d3e8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/PatternColors.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/PatternColors.java @@ -2,67 +2,89 @@ /** * An immutable wrapper for pattern colors. - * <p> - * This is separate from PatternRenderSettings because it does not affect the shape of the pattern, so we can re-use - * those parts for different colors. + * + * <p>This is separate from PatternRenderSettings because it does not affect the shape of the + * pattern, so we can re-use those parts for different colors. */ -public record PatternColors(int innerStartColor, int innerEndColor, int outerStartColor, int outerEndColor, - int startingDotColor, int gridDotsColor){ +public record PatternColors( + int innerStartColor, + int innerEndColor, + int outerStartColor, + int outerEndColor, + int startingDotColor, + int gridDotsColor) { - // keep some handy frequently used colors here. - public static final PatternColors DEFAULT_PATTERN_COLOR = new PatternColors(0xff_554d54, 0xff_d2c8c8); - public static final PatternColors DIMMED_COLOR = new PatternColors(0xFF_B4AAAA, 0xff_d2c8c8); - public static final PatternColors DEFAULT_GRADIENT_COLOR = DEFAULT_PATTERN_COLOR.withGradientEnds(DIMMED_COLOR); + // keep some handy frequently used colors here. + public static final PatternColors DEFAULT_PATTERN_COLOR = + new PatternColors(0xff_554d54, 0xff_d2c8c8); + public static final PatternColors DIMMED_COLOR = new PatternColors(0xFF_B4AAAA, 0xff_d2c8c8); + public static final PatternColors DEFAULT_GRADIENT_COLOR = + DEFAULT_PATTERN_COLOR.withGradientEnds(DIMMED_COLOR); - public static final int STARTING_DOT = 0xff_5b7bd7; - public static final int GRID_DOTS = 0x80_d2c8c8; + public static final int STARTING_DOT = 0xff_5b7bd7; + public static final int GRID_DOTS = 0x80_d2c8c8; - public static final PatternColors READABLE_SCROLL_COLORS = DEFAULT_PATTERN_COLOR.withDots(true, false); - public static final PatternColors READABLE_GRID_SCROLL_COLORS = DEFAULT_PATTERN_COLOR.withDots(true, true); + public static final PatternColors READABLE_SCROLL_COLORS = + DEFAULT_PATTERN_COLOR.withDots(true, false); + public static final PatternColors READABLE_GRID_SCROLL_COLORS = + DEFAULT_PATTERN_COLOR.withDots(true, true); - public static final PatternColors SLATE_WOBBLY_COLOR = glowyStroke( 0xff_64c8ff); // old blue color - public static final PatternColors SLATE_WOBBLY_PURPLE_COLOR = glowyStroke(0xff_cfa0f3); // shiny new purple one :) + public static final PatternColors SLATE_WOBBLY_COLOR = glowyStroke(0xff_64c8ff); // old blue color + public static final PatternColors SLATE_WOBBLY_PURPLE_COLOR = + glowyStroke(0xff_cfa0f3); // shiny new purple one :) - // no gradient - public PatternColors(int innerColor, int outerColor){ - this(innerColor, innerColor, outerColor, outerColor, 0, 0); - } + // no gradient + public PatternColors(int innerColor, int outerColor) { + this(innerColor, innerColor, outerColor, outerColor, 0, 0); + } - // single color -- no inner layer - public static PatternColors singleStroke(int color){ - return new PatternColors(0, color); - } + // single color -- no inner layer + public static PatternColors singleStroke(int color) { + return new PatternColors(0, color); + } - // makes a stroke color similar to the glowy effect that slates have. - public static PatternColors glowyStroke(int color){ - return new PatternColors(RenderLib.screenCol(color), color); - } + // makes a stroke color similar to the glowy effect that slates have. + public static PatternColors glowyStroke(int color) { + return new PatternColors(RenderLib.screenCol(color), color); + } - public static PatternColors gradientStrokes(int innerStartColor, int innerEndColor, int outerStartColor, int outerEndColor){ - return new PatternColors(innerStartColor, innerEndColor, outerStartColor, outerEndColor, 0, 0); - } + public static PatternColors gradientStrokes( + int innerStartColor, int innerEndColor, int outerStartColor, int outerEndColor) { + return new PatternColors(innerStartColor, innerEndColor, outerStartColor, outerEndColor, 0, 0); + } - // a single stroke with a gradient -- no inner layer. - public static PatternColors gradientStroke(int startColor, int endColor){ - return PatternColors.gradientStrokes(0, 0, startColor, endColor); - } + // a single stroke with a gradient -- no inner layer. + public static PatternColors gradientStroke(int startColor, int endColor) { + return PatternColors.gradientStrokes(0, 0, startColor, endColor); + } - public PatternColors withGradientEnds(int endColorInner, int endColorOuter){ - return new PatternColors(this.innerStartColor, endColorInner, this.outerStartColor, endColorOuter, this.startingDotColor, this.gridDotsColor); - } + public PatternColors withGradientEnds(int endColorInner, int endColorOuter) { + return new PatternColors( + this.innerStartColor, + endColorInner, + this.outerStartColor, + endColorOuter, + this.startingDotColor, + this.gridDotsColor); + } - public PatternColors withGradientEnds(PatternColors end){ - return withGradientEnds(end.innerEndColor, end.outerEndColor); - } + public PatternColors withGradientEnds(PatternColors end) { + return withGradientEnds(end.innerEndColor, end.outerEndColor); + } - // add dots -- note, this is how you tell the renderer to make dots - public PatternColors withDotColors(int startingDotColor, int gridDotsColor){ - return new PatternColors(this.innerStartColor, this.innerEndColor, this.outerStartColor, this.outerEndColor, - startingDotColor, gridDotsColor); - } + // add dots -- note, this is how you tell the renderer to make dots + public PatternColors withDotColors(int startingDotColor, int gridDotsColor) { + return new PatternColors( + this.innerStartColor, + this.innerEndColor, + this.outerStartColor, + this.outerEndColor, + startingDotColor, + gridDotsColor); + } - // adds dots with the default colors. - public PatternColors withDots(boolean startingDot, boolean gridDots){ - return withDotColors(startingDot ? STARTING_DOT : 0, gridDots ? GRID_DOTS : 0); - } + // adds dots with the default colors. + public PatternColors withDots(boolean startingDot, boolean gridDots) { + return withDotColors(startingDot ? STARTING_DOT : 0, gridDots ? GRID_DOTS : 0); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/PatternRenderer.java b/Common/src/main/java/at/petrak/hexcasting/client/render/PatternRenderer.java index 8fd307a9a4..be510ab733 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/PatternRenderer.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/PatternRenderer.java @@ -1,11 +1,15 @@ package at.petrak.hexcasting.client.render; - import at.petrak.hexcasting.api.casting.math.HexPattern; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexFormat; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import javax.annotation.Nullable; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.resources.ResourceLocation; @@ -13,139 +17,213 @@ import net.minecraft.world.phys.Vec2; import net.minecraft.world.phys.Vec3; -import javax.annotation.Nullable; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - public class PatternRenderer { - public static void renderPattern(HexPattern pattern, PoseStack ps, PatternSettings patSets, PatternColors patColors, double seed, int resPerUnit) { - renderPattern(pattern, ps, null, patSets, patColors, seed, resPerUnit); - } - - public static void renderPattern(HexPattern pattern, PoseStack ps, @Nullable WorldlyBits worldlyBits, PatternSettings patSets, PatternColors patColors, double seed, int resPerUnit) { - renderPattern(HexPatternLike.of(pattern), ps, worldlyBits, patSets, patColors, seed, resPerUnit); - } - - /** - * Renders a pattern (or rather a pattern-like) according to the given settings. - * @param patternlike the pattern (or more generally the lines) to render. - * @param ps pose/matrix stack to render based on. (0,0) is treated as the top left corner. The size of the render is determined by patSets. - * @param worldlyBits used for rendering with light/normals/render-layers if possible. This is optional and probably shouldn't be used for UI rendering. - * @param patSets settings that control how the pattern is drawn. - * @param patColors colors to use for drawing the pattern and dots. - * @param seed seed to use for zappy wobbles. - * @param resPerUnit the texture resolution per pose unit space to be used *if* the texture renderer is used. - */ - public static void renderPattern(HexPatternLike patternlike, PoseStack ps, @Nullable WorldlyBits worldlyBits, PatternSettings patSets, PatternColors patColors, double seed, int resPerUnit){ - var oldShader = RenderSystem.getShader(); - HexPatternPoints staticPoints = HexPatternPoints.getStaticPoints(patternlike, patSets, seed); - - boolean shouldRenderDynamic = true; - - // only do texture rendering if it's static and has solid colors - if(patSets.getSpeed() == 0 && PatternTextureManager.useTextures && patColors.innerStartColor() == patColors.innerEndColor() - && patColors.outerStartColor() == patColors.outerEndColor()){ - boolean didRender = renderPatternTexture(patternlike, ps, worldlyBits, patSets, patColors, seed, resPerUnit); - if(didRender) shouldRenderDynamic = false; - } - if(shouldRenderDynamic){ - List<Vec2> zappyPattern; - - if(patSets.getSpeed() == 0) { - // re-use our static points if we're rendering a static pattern anyway - zappyPattern = staticPoints.zappyPoints; - } else { - List<Vec2> nonzappyLines = patternlike.getNonZappyPoints(); - Set<Integer> dupIndices = RenderLib.findDupIndices(nonzappyLines); - zappyPattern = RenderLib.makeZappy(nonzappyLines, dupIndices, - patSets.getHops(), patSets.getVariance(), patSets.getSpeed(), patSets.getFlowIrregular(), - patSets.getReadabilityOffset(), patSets.getLastSegmentProp(), seed); - } - - List<Vec2> zappyRenderSpace = staticPoints.scaleVecs(zappyPattern); - - if(FastColor.ARGB32.alpha(patColors.outerEndColor()) != 0 && FastColor.ARGB32.alpha(patColors.outerStartColor()) != 0){ - RenderLib.drawLineSeq(ps.last().pose(), zappyRenderSpace, (float)patSets.getOuterWidth(staticPoints.finalScale), - patColors.outerStartColor(), patColors.outerEndColor(), VCDrawHelper.getHelper(worldlyBits, ps,outerZ)); - } - if(FastColor.ARGB32.alpha(patColors.innerEndColor()) != 0 && FastColor.ARGB32.alpha(patColors.innerStartColor()) != 0) { - RenderLib.drawLineSeq(ps.last().pose(), zappyRenderSpace, (float)patSets.getInnerWidth(staticPoints.finalScale), - patColors.innerStartColor(), patColors.innerEndColor(), VCDrawHelper.getHelper(worldlyBits, ps,innerZ)); - } - } - - // render dots and grid dynamically - - float dotZ = 0.0011f; - - if(FastColor.ARGB32.alpha(patColors.startingDotColor()) != 0) { - RenderLib.drawSpot(ps.last().pose(), staticPoints.dotsScaled.get(0), (float)patSets.getStartDotRadius(staticPoints.finalScale), - patColors.startingDotColor(), VCDrawHelper.getHelper(worldlyBits, ps, dotZ)); - } - - if(FastColor.ARGB32.alpha(patColors.gridDotsColor()) != 0) { - for(int i = 1; i < staticPoints.dotsScaled.size(); i++){ - Vec2 gridDot = staticPoints.dotsScaled.get(i); - RenderLib.drawSpot(ps.last().pose(), gridDot, (float)patSets.getGridDotsRadius(staticPoints.finalScale), - patColors.gridDotsColor(), VCDrawHelper.getHelper(worldlyBits, ps, dotZ)); - } - } - - RenderSystem.setShader(() -> oldShader); - } - - private static final float outerZ = 0.0005f; - private static final float innerZ = 0.001f; - - private static boolean renderPatternTexture(HexPatternLike patternlike, PoseStack ps, @Nullable WorldlyBits worldlyBits, PatternSettings patSets, PatternColors patColors, double seed, int resPerUnit){ - Optional<Map<String, ResourceLocation>> maybeTextures = PatternTextureManager.getTextures(patternlike, patSets, seed, resPerUnit); - if(maybeTextures.isEmpty()){ - return false; - } - - Map<String, ResourceLocation> textures = maybeTextures.get(); - HexPatternPoints staticPoints = HexPatternPoints.getStaticPoints(patternlike, patSets, seed); - - VertexConsumer vc; - - if(FastColor.ARGB32.alpha(patColors.outerStartColor()) != 0) { - VCDrawHelper vcHelper = VCDrawHelper.getHelper(worldlyBits, ps, outerZ, textures.get("outer")); - vc = vcHelper.vcSetupAndSupply(VertexFormat.Mode.QUADS); - - int cl = patColors.outerStartColor(); - - vcHelper.vertex(vc, cl, new Vec2(0, 0), new Vec2(0, 0), ps.last().pose()); - vcHelper.vertex(vc, cl, new Vec2(0, (float) staticPoints.fullHeight), new Vec2(0, 1), ps.last().pose()); - vcHelper.vertex(vc, cl, new Vec2((float) staticPoints.fullWidth, (float) staticPoints.fullHeight), new Vec2(1, 1), ps.last().pose()); - vcHelper.vertex(vc, cl, new Vec2((float) staticPoints.fullWidth, 0), new Vec2(1, 0), ps.last().pose()); - - vcHelper.vcEndDrawer(vc); - } - - if(FastColor.ARGB32.alpha(patColors.innerStartColor()) != 0) { - VCDrawHelper vcHelper = VCDrawHelper.getHelper(worldlyBits, ps, innerZ, textures.get("inner")); - vc = vcHelper.vcSetupAndSupply(VertexFormat.Mode.QUADS); - - int cl = patColors.innerStartColor(); - - vcHelper.vertex(vc, cl, new Vec2(0, 0), new Vec2(0, 0), ps.last().pose()); - vcHelper.vertex(vc, cl, new Vec2(0, (float) staticPoints.fullHeight), new Vec2(0, 1), ps.last().pose()); - vcHelper.vertex(vc, cl, new Vec2((float) staticPoints.fullWidth, (float) staticPoints.fullHeight), new Vec2(1, 1), ps.last().pose()); - vcHelper.vertex(vc, cl, new Vec2((float) staticPoints.fullWidth, 0), new Vec2(1, 0), ps.last().pose()); - - vcHelper.vcEndDrawer(vc); - } - - return true; - } - - // TODO did we want to un-hardcode this for accessibility reasons ? - public static boolean shouldDoStrokeGradient(){ - return Screen.hasControlDown(); - } - - public record WorldlyBits(@Nullable MultiBufferSource provider, Integer light, Vec3 normal){} + public static void renderPattern( + HexPattern pattern, + PoseStack ps, + PatternSettings patSets, + PatternColors patColors, + double seed, + int resPerUnit) { + renderPattern(pattern, ps, null, patSets, patColors, seed, resPerUnit); + } + + public static void renderPattern( + HexPattern pattern, + PoseStack ps, + @Nullable WorldlyBits worldlyBits, + PatternSettings patSets, + PatternColors patColors, + double seed, + int resPerUnit) { + renderPattern( + HexPatternLike.of(pattern), ps, worldlyBits, patSets, patColors, seed, resPerUnit); + } + + /** + * Renders a pattern (or rather a pattern-like) according to the given settings. + * + * @param patternlike the pattern (or more generally the lines) to render. + * @param ps pose/matrix stack to render based on. (0,0) is treated as the top left corner. The + * size of the render is determined by patSets. + * @param worldlyBits used for rendering with light/normals/render-layers if possible. This is + * optional and probably shouldn't be used for UI rendering. + * @param patSets settings that control how the pattern is drawn. + * @param patColors colors to use for drawing the pattern and dots. + * @param seed seed to use for zappy wobbles. + * @param resPerUnit the texture resolution per pose unit space to be used *if* the texture + * renderer is used. + */ + public static void renderPattern( + HexPatternLike patternlike, + PoseStack ps, + @Nullable WorldlyBits worldlyBits, + PatternSettings patSets, + PatternColors patColors, + double seed, + int resPerUnit) { + var oldShader = RenderSystem.getShader(); + HexPatternPoints staticPoints = HexPatternPoints.getStaticPoints(patternlike, patSets, seed); + + boolean shouldRenderDynamic = true; + + // only do texture rendering if it's static and has solid colors + if (patSets.getSpeed() == 0 + && PatternTextureManager.useTextures + && patColors.innerStartColor() == patColors.innerEndColor() + && patColors.outerStartColor() == patColors.outerEndColor()) { + boolean didRender = + renderPatternTexture(patternlike, ps, worldlyBits, patSets, patColors, seed, resPerUnit); + if (didRender) shouldRenderDynamic = false; + } + if (shouldRenderDynamic) { + List<Vec2> zappyPattern; + + if (patSets.getSpeed() == 0) { + // re-use our static points if we're rendering a static pattern anyway + zappyPattern = staticPoints.zappyPoints; + } else { + List<Vec2> nonzappyLines = patternlike.getNonZappyPoints(); + Set<Integer> dupIndices = RenderLib.findDupIndices(nonzappyLines); + zappyPattern = + RenderLib.makeZappy( + nonzappyLines, + dupIndices, + patSets.getHops(), + patSets.getVariance(), + patSets.getSpeed(), + patSets.getFlowIrregular(), + patSets.getReadabilityOffset(), + patSets.getLastSegmentProp(), + seed); + } + + List<Vec2> zappyRenderSpace = staticPoints.scaleVecs(zappyPattern); + + if (FastColor.ARGB32.alpha(patColors.outerEndColor()) != 0 + && FastColor.ARGB32.alpha(patColors.outerStartColor()) != 0) { + RenderLib.drawLineSeq( + ps.last().pose(), + zappyRenderSpace, + (float) patSets.getOuterWidth(staticPoints.finalScale), + patColors.outerStartColor(), + patColors.outerEndColor(), + VCDrawHelper.getHelper(worldlyBits, ps, outerZ)); + } + if (FastColor.ARGB32.alpha(patColors.innerEndColor()) != 0 + && FastColor.ARGB32.alpha(patColors.innerStartColor()) != 0) { + RenderLib.drawLineSeq( + ps.last().pose(), + zappyRenderSpace, + (float) patSets.getInnerWidth(staticPoints.finalScale), + patColors.innerStartColor(), + patColors.innerEndColor(), + VCDrawHelper.getHelper(worldlyBits, ps, innerZ)); + } + } + + // render dots and grid dynamically + + float dotZ = 0.0011f; + + if (FastColor.ARGB32.alpha(patColors.startingDotColor()) != 0) { + RenderLib.drawSpot( + ps.last().pose(), + staticPoints.dotsScaled.get(0), + (float) patSets.getStartDotRadius(staticPoints.finalScale), + patColors.startingDotColor(), + VCDrawHelper.getHelper(worldlyBits, ps, dotZ)); + } + + if (FastColor.ARGB32.alpha(patColors.gridDotsColor()) != 0) { + for (int i = 1; i < staticPoints.dotsScaled.size(); i++) { + Vec2 gridDot = staticPoints.dotsScaled.get(i); + RenderLib.drawSpot( + ps.last().pose(), + gridDot, + (float) patSets.getGridDotsRadius(staticPoints.finalScale), + patColors.gridDotsColor(), + VCDrawHelper.getHelper(worldlyBits, ps, dotZ)); + } + } + + RenderSystem.setShader(() -> oldShader); + } + + private static final float outerZ = 0.0005f; + private static final float innerZ = 0.001f; + + private static boolean renderPatternTexture( + HexPatternLike patternlike, + PoseStack ps, + @Nullable WorldlyBits worldlyBits, + PatternSettings patSets, + PatternColors patColors, + double seed, + int resPerUnit) { + Optional<Map<String, ResourceLocation>> maybeTextures = + PatternTextureManager.getTextures(patternlike, patSets, seed, resPerUnit); + if (maybeTextures.isEmpty()) { + return false; + } + + Map<String, ResourceLocation> textures = maybeTextures.get(); + HexPatternPoints staticPoints = HexPatternPoints.getStaticPoints(patternlike, patSets, seed); + + VertexConsumer vc; + + if (FastColor.ARGB32.alpha(patColors.outerStartColor()) != 0) { + VCDrawHelper vcHelper = + VCDrawHelper.getHelper(worldlyBits, ps, outerZ, textures.get("outer")); + vc = vcHelper.vcSetupAndSupply(VertexFormat.Mode.QUADS); + + int cl = patColors.outerStartColor(); + + vcHelper.vertex(vc, cl, new Vec2(0, 0), new Vec2(0, 0), ps.last().pose()); + vcHelper.vertex( + vc, cl, new Vec2(0, (float) staticPoints.fullHeight), new Vec2(0, 1), ps.last().pose()); + vcHelper.vertex( + vc, + cl, + new Vec2((float) staticPoints.fullWidth, (float) staticPoints.fullHeight), + new Vec2(1, 1), + ps.last().pose()); + vcHelper.vertex( + vc, cl, new Vec2((float) staticPoints.fullWidth, 0), new Vec2(1, 0), ps.last().pose()); + + vcHelper.vcEndDrawer(vc); + } + + if (FastColor.ARGB32.alpha(patColors.innerStartColor()) != 0) { + VCDrawHelper vcHelper = + VCDrawHelper.getHelper(worldlyBits, ps, innerZ, textures.get("inner")); + vc = vcHelper.vcSetupAndSupply(VertexFormat.Mode.QUADS); + + int cl = patColors.innerStartColor(); + + vcHelper.vertex(vc, cl, new Vec2(0, 0), new Vec2(0, 0), ps.last().pose()); + vcHelper.vertex( + vc, cl, new Vec2(0, (float) staticPoints.fullHeight), new Vec2(0, 1), ps.last().pose()); + vcHelper.vertex( + vc, + cl, + new Vec2((float) staticPoints.fullWidth, (float) staticPoints.fullHeight), + new Vec2(1, 1), + ps.last().pose()); + vcHelper.vertex( + vc, cl, new Vec2((float) staticPoints.fullWidth, 0), new Vec2(1, 0), ps.last().pose()); + + vcHelper.vcEndDrawer(vc); + } + + return true; + } + + // TODO did we want to un-hardcode this for accessibility reasons ? + public static boolean shouldDoStrokeGradient() { + return Screen.hasControlDown(); + } + + public record WorldlyBits(@Nullable MultiBufferSource provider, Integer light, Vec3 normal) {} } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/PatternSettings.java b/Common/src/main/java/at/petrak/hexcasting/client/render/PatternSettings.java index 4cb223f6f6..9ee5b4167f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/PatternSettings.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/PatternSettings.java @@ -3,140 +3,225 @@ /** * A class holding settings for shaping and positioning patterns. * - * By default, it's a simple wrapper of 3 records, however some use cases may require extending and overriding getters. - * This is done to keep the complexity of the records a bit lower. + * <p>By default, it's a simple wrapper of 3 records, however some use cases may require extending + * and overriding getters. This is done to keep the complexity of the records a bit lower. */ public class PatternSettings { - public PatternSettings(String name, PositionSettings posSets, StrokeSettings strokeSets, ZappySettings zapSets){ - this.name = name; - this.posSets = posSets; - this.strokeSets = strokeSets; - this.zapSets = zapSets; - } - - /** - * Settings for positioning the pattern and defining its general size/render area. All values are in 'pose units', - * meaning we use them directly with the pose/matrix stack given to the renderer. - * - * <p> - * We do a first pass at the pattern scale using baseScale. We then make sure it's larger than minWidth and - * minHeight. Then on each axis, if that axis is has a FIT alignment then we may scale down the pattern to make sure it - * fits. Note that the padding is not scaled and is always respected. - * </p> - */ - public record PositionSettings(double spaceWidth, double spaceHeight, double hPadding, double vPadding, - AxisAlignment hAxis, AxisAlignment vAxis, double baseScale, double minWidth, double minHeight){ - /** - * Makes settings ideal for rendering in a square. This helper exists because this is the most common positioning - * pattern. - * @param padding a value 0-0.5 for how much padding should go on each side. - * @return a PositionSettings object in a 1x1 space with the given padding value such that the pattern is centered - */ - public static PositionSettings paddedSquare(double padding){ - return paddedSquare(padding, 0.25, 0); - } - - public static PositionSettings paddedSquare(double padding, double baseScale, double minSize){ - return new PositionSettings(1.0, 1.0, padding, padding, AxisAlignment.CENTER_FIT, AxisAlignment.CENTER_FIT, baseScale, minSize, minSize); - } - } - - /** - * Settings for stroke and dot sizings. If you want to *not* render dots or inner/outer you should prefer setting - * alpha to 0 in PatternColors. - */ - public record StrokeSettings(double innerWidth, double outerWidth, - double startDotRadius, double gridDotsRadius){ - public static StrokeSettings fromStroke(double stroke){ - return new StrokeSettings(stroke * 2.0/5.0, stroke, 0.8 * stroke * 2.0 / 5.0, 0.4 * stroke * 2.0 / 5.0); - } - } - - /** - * Controls how the pattern is zappified. - * - * @param hops number of little pulses - * @param variance how jumpy/distorting the pulses are - * @param speed how fast the pulses go - * @param flowIrregular randomness of pulse travel - * @param readabilityOffset how curved inward the corners are - * @param lastSegmentLenProportion length of the last segment relative to the others. used for increased readability. - */ - public record ZappySettings(int hops, float variance, float speed, float flowIrregular, float readabilityOffset, float lastSegmentLenProportion){ - public static float READABLE_OFFSET = 0.2f; - public static float READABLE_SEGMENT = 0.8f; - public static ZappySettings STATIC = new ZappySettings(10, 0.5f, 0f, 0.2f, 0, 1f); - public static ZappySettings READABLE = new ZappySettings(10, 0.5f, 0f, 0.2f, READABLE_OFFSET, READABLE_SEGMENT); - public static ZappySettings WOBBLY = new ZappySettings(10, 2.5f, 0.1f, 0.2f, 0, 1f); - } - - public String getCacheKey(HexPatternLike patternlike, double seed){ - return (patternlike.getName() + "-" + getName() + "-" + seed).toLowerCase(); - } - - // determines how the pattern is fit and aligned on a given axis - public enum AxisAlignment{ - // These 3 scale the pattern down to fit if needed. - BEGIN_FIT(true, 0), - CENTER_FIT(true, 1), - END_FIT(true, 2), - // these 3 do *not* scale the pattern down, it will overflow if needed. - BEGIN(false, 0), - CENTER(false, 1), - END(false, 2); - - public final boolean fit; - public final int amtInFront; // how many halves go in front. yes it's a weird way to do it. - - AxisAlignment(boolean fit, int amtInFront){ - this.fit = fit; - this.amtInFront = amtInFront; - } - } - - private final String name; - // leaving these public for more convenient chaining. Should prefer using the getters for overrideability. - public final PositionSettings posSets; - public final StrokeSettings strokeSets; - public final ZappySettings zapSets; - - public String getName(){ return name; } - - public double getTargetWidth(){ return posSets.spaceWidth; } - public double getTargetHeight(){ return posSets.spaceHeight; } - - public double getHorPadding(){ return posSets.hPadding; } - public double getVertPadding(){ return posSets.vPadding; } - - public AxisAlignment getHorAlignment(){ return posSets.hAxis; } - public AxisAlignment getVertAlignment(){ return posSets.vAxis; } - - public double getBaseScale(){ return posSets.baseScale; } - public double getMinWidth(){ return posSets.minWidth; } - public double getMinHeight(){ return posSets.minHeight; } - - /* these sizing getters take in the final pattern scale so that patterns can vary their stroke width when squished. - * the records keep a static value since that's fine for *most* use cases, override these methods if you need to use them. - * note that these widths are still in pose space units. - */ - - public double getInnerWidth(double scale){ return strokeSets.innerWidth; } - public double getOuterWidth(double scale){ return strokeSets.outerWidth; } - - public double getStartDotRadius(double scale){ return strokeSets.startDotRadius; } - public double getGridDotsRadius(double scale){ return strokeSets.gridDotsRadius; } - - public double getStrokeWidth(double scale){ return Math.max(getOuterWidth(scale), getInnerWidth(scale)); } - - // we have a stroke guess getter so that we can *try* to account for the stroke size when fitting the pattern. - public double getStrokeWidthGuess(){ return Math.max(strokeSets.outerWidth, strokeSets.innerWidth); } - - public int getHops(){ return zapSets.hops; } - public float getVariance(){ return zapSets.variance; } - public float getFlowIrregular(){ return zapSets.flowIrregular; } - public float getReadabilityOffset(){ return zapSets.readabilityOffset; } - public float getLastSegmentProp(){ return zapSets.lastSegmentLenProportion; } - - public float getSpeed(){ return zapSets.speed; } + public PatternSettings( + String name, PositionSettings posSets, StrokeSettings strokeSets, ZappySettings zapSets) { + this.name = name; + this.posSets = posSets; + this.strokeSets = strokeSets; + this.zapSets = zapSets; + } + + /** + * Settings for positioning the pattern and defining its general size/render area. All values are + * in 'pose units', meaning we use them directly with the pose/matrix stack given to the renderer. + * + * <p>We do a first pass at the pattern scale using baseScale. We then make sure it's larger than + * minWidth and minHeight. Then on each axis, if that axis is has a FIT alignment then we may + * scale down the pattern to make sure it fits. Note that the padding is not scaled and is always + * respected. + */ + public record PositionSettings( + double spaceWidth, + double spaceHeight, + double hPadding, + double vPadding, + AxisAlignment hAxis, + AxisAlignment vAxis, + double baseScale, + double minWidth, + double minHeight) { + /** + * Makes settings ideal for rendering in a square. This helper exists because this is the most + * common positioning pattern. + * + * @param padding a value 0-0.5 for how much padding should go on each side. + * @return a PositionSettings object in a 1x1 space with the given padding value such that the + * pattern is centered + */ + public static PositionSettings paddedSquare(double padding) { + return paddedSquare(padding, 0.25, 0); + } + + public static PositionSettings paddedSquare(double padding, double baseScale, double minSize) { + return new PositionSettings( + 1.0, + 1.0, + padding, + padding, + AxisAlignment.CENTER_FIT, + AxisAlignment.CENTER_FIT, + baseScale, + minSize, + minSize); + } + } + + /** + * Settings for stroke and dot sizings. If you want to *not* render dots or inner/outer you should + * prefer setting alpha to 0 in PatternColors. + */ + public record StrokeSettings( + double innerWidth, double outerWidth, double startDotRadius, double gridDotsRadius) { + public static StrokeSettings fromStroke(double stroke) { + return new StrokeSettings( + stroke * 2.0 / 5.0, stroke, 0.8 * stroke * 2.0 / 5.0, 0.4 * stroke * 2.0 / 5.0); + } + } + + /** + * Controls how the pattern is zappified. + * + * @param hops number of little pulses + * @param variance how jumpy/distorting the pulses are + * @param speed how fast the pulses go + * @param flowIrregular randomness of pulse travel + * @param readabilityOffset how curved inward the corners are + * @param lastSegmentLenProportion length of the last segment relative to the others. used for + * increased readability. + */ + public record ZappySettings( + int hops, + float variance, + float speed, + float flowIrregular, + float readabilityOffset, + float lastSegmentLenProportion) { + public static float READABLE_OFFSET = 0.2f; + public static float READABLE_SEGMENT = 0.8f; + public static ZappySettings STATIC = new ZappySettings(10, 0.5f, 0f, 0.2f, 0, 1f); + public static ZappySettings READABLE = + new ZappySettings(10, 0.5f, 0f, 0.2f, READABLE_OFFSET, READABLE_SEGMENT); + public static ZappySettings WOBBLY = new ZappySettings(10, 2.5f, 0.1f, 0.2f, 0, 1f); + } + + public String getCacheKey(HexPatternLike patternlike, double seed) { + return (patternlike.getName() + "-" + getName() + "-" + seed).toLowerCase(); + } + + // determines how the pattern is fit and aligned on a given axis + public enum AxisAlignment { + // These 3 scale the pattern down to fit if needed. + BEGIN_FIT(true, 0), + CENTER_FIT(true, 1), + END_FIT(true, 2), + // these 3 do *not* scale the pattern down, it will overflow if needed. + BEGIN(false, 0), + CENTER(false, 1), + END(false, 2); + + public final boolean fit; + public final int amtInFront; // how many halves go in front. yes it's a weird way to do it. + + AxisAlignment(boolean fit, int amtInFront) { + this.fit = fit; + this.amtInFront = amtInFront; + } + } + + private final String name; + // leaving these public for more convenient chaining. Should prefer using the getters for + // overrideability. + public final PositionSettings posSets; + public final StrokeSettings strokeSets; + public final ZappySettings zapSets; + + public String getName() { + return name; + } + + public double getTargetWidth() { + return posSets.spaceWidth; + } + + public double getTargetHeight() { + return posSets.spaceHeight; + } + + public double getHorPadding() { + return posSets.hPadding; + } + + public double getVertPadding() { + return posSets.vPadding; + } + + public AxisAlignment getHorAlignment() { + return posSets.hAxis; + } + + public AxisAlignment getVertAlignment() { + return posSets.vAxis; + } + + public double getBaseScale() { + return posSets.baseScale; + } + + public double getMinWidth() { + return posSets.minWidth; + } + + public double getMinHeight() { + return posSets.minHeight; + } + + /* these sizing getters take in the final pattern scale so that patterns can vary their stroke width when squished. + * the records keep a static value since that's fine for *most* use cases, override these methods if you need to use them. + * note that these widths are still in pose space units. + */ + + public double getInnerWidth(double scale) { + return strokeSets.innerWidth; + } + + public double getOuterWidth(double scale) { + return strokeSets.outerWidth; + } + + public double getStartDotRadius(double scale) { + return strokeSets.startDotRadius; + } + + public double getGridDotsRadius(double scale) { + return strokeSets.gridDotsRadius; + } + + public double getStrokeWidth(double scale) { + return Math.max(getOuterWidth(scale), getInnerWidth(scale)); + } + + // we have a stroke guess getter so that we can *try* to account for the stroke size when fitting + // the pattern. + public double getStrokeWidthGuess() { + return Math.max(strokeSets.outerWidth, strokeSets.innerWidth); + } + + public int getHops() { + return zapSets.hops; + } + + public float getVariance() { + return zapSets.variance; + } + + public float getFlowIrregular() { + return zapSets.flowIrregular; + } + + public float getReadabilityOffset() { + return zapSets.readabilityOffset; + } + + public float getLastSegmentProp() { + return zapSets.lastSegmentLenProportion; + } + + public float getSpeed() { + return zapSets.speed; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/PatternTextureManager.java b/Common/src/main/java/at/petrak/hexcasting/client/render/PatternTextureManager.java index 8486124920..f4fe73f78e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/PatternTextureManager.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/PatternTextureManager.java @@ -1,134 +1,174 @@ package at.petrak.hexcasting.client.render; import com.mojang.blaze3d.platform.NativeImage; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.*; +import java.util.List; +import java.util.concurrent.*; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Tuple; import net.minecraft.world.phys.Vec2; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.util.List; -import java.util.*; -import java.util.concurrent.*; - public class PatternTextureManager { - //TODO: remove if not needed anymore for comparison - public static boolean useTextures = true; - public static int repaintIndex = 0; - - private static final ConcurrentMap<String, Map<String, ResourceLocation>> patternTexturesToAdd = new ConcurrentHashMap<>(); - private static final Set<String> inProgressPatterns = new HashSet<>(); - // basically newCachedThreadPool, but with a max pool size - private static final ExecutorService executor = new ThreadPoolExecutor(0, 16, 60L, TimeUnit.SECONDS, new LinkedBlockingDeque<>()); - - private static final HashMap<String, Map<String, ResourceLocation>> patternTextures = new HashMap<>(); - - public static Optional<Map<String, ResourceLocation>> getTextures(HexPatternLike patternlike, PatternSettings patSets, double seed, int resPerUnit) { - String patCacheKey = patSets.getCacheKey(patternlike, seed) + "_" + resPerUnit; - - // move textures from concurrent map to normal hashmap as needed - if (patternTexturesToAdd.containsKey(patCacheKey)) { - var patternTexture = patternTexturesToAdd.remove(patCacheKey); - var oldPatternTexture = patternTextures.put(patCacheKey, patternTexture); - inProgressPatterns.remove(patCacheKey); - if (oldPatternTexture != null) // TODO: is this needed? when does this ever happen? - for(ResourceLocation oldPatternTextureSingle : oldPatternTexture.values()) - Minecraft.getInstance().getTextureManager().getTexture(oldPatternTextureSingle).close(); - - return Optional.empty(); // try not giving it immediately to avoid flickering? - } - if (patternTextures.containsKey(patCacheKey)) - return Optional.of(patternTextures.get(patCacheKey)); - - // render a higher-resolution texture in a background thread so it eventually becomes all nice nice and pretty - if(!inProgressPatterns.contains(patCacheKey)){ - inProgressPatterns.add(patCacheKey); - executor.submit(() -> { - var slowTextures = createTextures(patternlike, patSets, seed, resPerUnit); - - // TextureManager#register doesn't look very thread-safe, so move back to the main thread after the slow part is done - Minecraft.getInstance().execute(() -> { - registerTextures(patCacheKey, slowTextures); - }); - }); - } - return Optional.empty(); - } - - private static Map<String, DynamicTexture> createTextures(HexPatternLike patternlike, PatternSettings patSets, double seed, int resPerUnit) { - HexPatternPoints staticPoints = HexPatternPoints.getStaticPoints(patternlike, patSets, seed); - - List<Vec2> zappyRenderSpace = staticPoints.scaleVecs(staticPoints.zappyPoints); - - Map<String, DynamicTexture> patTexts = new HashMap<>(); - - NativeImage innerLines = drawLines(zappyRenderSpace, staticPoints, (float)patSets.getInnerWidth((staticPoints.finalScale)), resPerUnit); - patTexts.put("inner", new DynamicTexture(innerLines)); - - NativeImage outerLines = drawLines(zappyRenderSpace, staticPoints, (float)patSets.getOuterWidth((staticPoints.finalScale)), resPerUnit); - patTexts.put("outer", new DynamicTexture(outerLines)); - - return patTexts; - } - - private static Map<String, ResourceLocation> registerTextures(String patTextureKeyBase, Map<String, DynamicTexture> dynamicTextures) { - Map<String, ResourceLocation> resLocs = new HashMap<>(); - for(Map.Entry<String, DynamicTexture> textureEntry : dynamicTextures.entrySet()){ - String name = "hex_pattern_texture_" + patTextureKeyBase + "_" + textureEntry.getKey() + "_" + repaintIndex + ".png"; - ResourceLocation resourceLocation = Minecraft.getInstance().getTextureManager().register(name, textureEntry.getValue()); - resLocs.put(textureEntry.getKey(), resourceLocation); - } - patternTexturesToAdd.put(patTextureKeyBase, resLocs); - return resLocs; - } - - private static NativeImage drawLines(List<Vec2> points, HexPatternPoints staticPoints, float unscaledLineWidth, int resPerUnit) { - BufferedImage img = new BufferedImage((int)(staticPoints.fullWidth*resPerUnit), (int)(staticPoints.fullHeight*resPerUnit), BufferedImage.TYPE_INT_ARGB); - Graphics2D g2d = img.createGraphics(); - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - g2d.setColor(new Color(0xFF_FFFFFF)); // set it to white so we can reuse the texture with different colors - g2d.setStroke(new BasicStroke(unscaledLineWidth * resPerUnit, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); - for (int i = 0; i < points.size() - 1; i++) { - Tuple<Integer, Integer> pointFrom = getTextureCoordinates(points.get(i), staticPoints, resPerUnit); - Tuple<Integer, Integer> pointTo = getTextureCoordinates(points.get(i+1), staticPoints, resPerUnit); - g2d.drawLine(pointFrom.getA(), pointFrom.getB(), pointTo.getA(), pointTo.getB()); - } - g2d.dispose(); - NativeImage nativeImage = new NativeImage(img.getWidth(), img.getHeight(), true); - for (int y = 0; y < img.getHeight(); y++) - for (int x = 0; x < img.getWidth(); x++) - nativeImage.setPixelRGBA(x, y, img.getRGB(x, y)); - return nativeImage; - } - - private static Tuple<Integer, Integer> getTextureCoordinates(Vec2 point, HexPatternPoints staticPoints, int resPerUnit) { - int x = (int) ( point.x * resPerUnit); - int y = (int) ( point.y * resPerUnit); - return new Tuple<>(x, y); - } - - // keeping this around just in case we ever decide to put the dots in the textures instead of dynamic - private static void drawHexagon(Graphics2D g2d, int x, int y, int radius) { - int fracOfCircle = 6; - Polygon hexagon = new Polygon(); - - for (int i = 0; i < fracOfCircle; i++) { - double theta = (i / (double) fracOfCircle) * Math.PI * 2; - int hx = (int) (x + Math.cos(theta) * radius); - int hy = (int) (y + Math.sin(theta) * radius); - hexagon.addPoint(hx, hy); - } - - g2d.fill(hexagon); - } - - public static void repaint() { - repaintIndex++; - patternTexturesToAdd.clear(); - patternTextures.clear(); - } -} \ No newline at end of file + // TODO: remove if not needed anymore for comparison + public static boolean useTextures = true; + public static int repaintIndex = 0; + + private static final ConcurrentMap<String, Map<String, ResourceLocation>> patternTexturesToAdd = + new ConcurrentHashMap<>(); + private static final Set<String> inProgressPatterns = new HashSet<>(); + // basically newCachedThreadPool, but with a max pool size + private static final ExecutorService executor = + new ThreadPoolExecutor(0, 16, 60L, TimeUnit.SECONDS, new LinkedBlockingDeque<>()); + + private static final HashMap<String, Map<String, ResourceLocation>> patternTextures = + new HashMap<>(); + + public static Optional<Map<String, ResourceLocation>> getTextures( + HexPatternLike patternlike, PatternSettings patSets, double seed, int resPerUnit) { + String patCacheKey = patSets.getCacheKey(patternlike, seed) + "_" + resPerUnit; + + // move textures from concurrent map to normal hashmap as needed + if (patternTexturesToAdd.containsKey(patCacheKey)) { + var patternTexture = patternTexturesToAdd.remove(patCacheKey); + var oldPatternTexture = patternTextures.put(patCacheKey, patternTexture); + inProgressPatterns.remove(patCacheKey); + if (oldPatternTexture != null) // TODO: is this needed? when does this ever happen? + for (ResourceLocation oldPatternTextureSingle : oldPatternTexture.values()) + Minecraft.getInstance().getTextureManager().getTexture(oldPatternTextureSingle).close(); + + return Optional.empty(); // try not giving it immediately to avoid flickering? + } + if (patternTextures.containsKey(patCacheKey)) + return Optional.of(patternTextures.get(patCacheKey)); + + // render a higher-resolution texture in a background thread so it eventually becomes all nice + // nice and pretty + if (!inProgressPatterns.contains(patCacheKey)) { + inProgressPatterns.add(patCacheKey); + executor.submit( + () -> { + var slowTextures = createTextures(patternlike, patSets, seed, resPerUnit); + + // TextureManager#register doesn't look very thread-safe, so move back to the main + // thread after the slow part is done + Minecraft.getInstance() + .execute( + () -> { + registerTextures(patCacheKey, slowTextures); + }); + }); + } + return Optional.empty(); + } + + private static Map<String, DynamicTexture> createTextures( + HexPatternLike patternlike, PatternSettings patSets, double seed, int resPerUnit) { + HexPatternPoints staticPoints = HexPatternPoints.getStaticPoints(patternlike, patSets, seed); + + List<Vec2> zappyRenderSpace = staticPoints.scaleVecs(staticPoints.zappyPoints); + + Map<String, DynamicTexture> patTexts = new HashMap<>(); + + NativeImage innerLines = + drawLines( + zappyRenderSpace, + staticPoints, + (float) patSets.getInnerWidth((staticPoints.finalScale)), + resPerUnit); + patTexts.put("inner", new DynamicTexture(innerLines)); + + NativeImage outerLines = + drawLines( + zappyRenderSpace, + staticPoints, + (float) patSets.getOuterWidth((staticPoints.finalScale)), + resPerUnit); + patTexts.put("outer", new DynamicTexture(outerLines)); + + return patTexts; + } + + private static Map<String, ResourceLocation> registerTextures( + String patTextureKeyBase, Map<String, DynamicTexture> dynamicTextures) { + Map<String, ResourceLocation> resLocs = new HashMap<>(); + for (Map.Entry<String, DynamicTexture> textureEntry : dynamicTextures.entrySet()) { + String name = + "hex_pattern_texture_" + + patTextureKeyBase + + "_" + + textureEntry.getKey() + + "_" + + repaintIndex + + ".png"; + ResourceLocation resourceLocation = + Minecraft.getInstance().getTextureManager().register(name, textureEntry.getValue()); + resLocs.put(textureEntry.getKey(), resourceLocation); + } + patternTexturesToAdd.put(patTextureKeyBase, resLocs); + return resLocs; + } + + private static NativeImage drawLines( + List<Vec2> points, HexPatternPoints staticPoints, float unscaledLineWidth, int resPerUnit) { + BufferedImage img = + new BufferedImage( + (int) (staticPoints.fullWidth * resPerUnit), + (int) (staticPoints.fullHeight * resPerUnit), + BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = img.createGraphics(); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + g2d.setColor( + new Color( + 0xFF_FFFFFF)); // set it to white so we can reuse the texture with different colors + g2d.setStroke( + new BasicStroke( + unscaledLineWidth * resPerUnit, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + for (int i = 0; i < points.size() - 1; i++) { + Tuple<Integer, Integer> pointFrom = + getTextureCoordinates(points.get(i), staticPoints, resPerUnit); + Tuple<Integer, Integer> pointTo = + getTextureCoordinates(points.get(i + 1), staticPoints, resPerUnit); + g2d.drawLine(pointFrom.getA(), pointFrom.getB(), pointTo.getA(), pointTo.getB()); + } + g2d.dispose(); + NativeImage nativeImage = new NativeImage(img.getWidth(), img.getHeight(), true); + for (int y = 0; y < img.getHeight(); y++) + for (int x = 0; x < img.getWidth(); x++) nativeImage.setPixelRGBA(x, y, img.getRGB(x, y)); + return nativeImage; + } + + private static Tuple<Integer, Integer> getTextureCoordinates( + Vec2 point, HexPatternPoints staticPoints, int resPerUnit) { + int x = (int) (point.x * resPerUnit); + int y = (int) (point.y * resPerUnit); + return new Tuple<>(x, y); + } + + // keeping this around just in case we ever decide to put the dots in the textures instead of + // dynamic + private static void drawHexagon(Graphics2D g2d, int x, int y, int radius) { + int fracOfCircle = 6; + Polygon hexagon = new Polygon(); + + for (int i = 0; i < fracOfCircle; i++) { + double theta = (i / (double) fracOfCircle) * Math.PI * 2; + int hx = (int) (x + Math.cos(theta) * radius); + int hy = (int) (y + Math.sin(theta) * radius); + hexagon.addPoint(hx, hy); + } + + g2d.fill(hexagon); + } + + public static void repaint() { + repaintIndex++; + patternTexturesToAdd.clear(); + patternTextures.clear(); + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/RenderLib.kt b/Common/src/main/java/at/petrak/hexcasting/client/render/RenderLib.kt index 823068439f..f144bcc335 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/RenderLib.kt +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/RenderLib.kt @@ -12,6 +12,10 @@ import com.mojang.blaze3d.vertex.PoseStack import com.mojang.blaze3d.vertex.Tesselator import com.mojang.blaze3d.vertex.VertexFormat import com.mojang.math.Axis +import kotlin.math.abs +import kotlin.math.min +import kotlin.math.roundToInt +import kotlin.math.sin import net.minecraft.client.Minecraft import net.minecraft.client.gui.GuiGraphics import net.minecraft.client.gui.screens.Screen @@ -25,33 +29,22 @@ import net.minecraft.world.level.levelgen.SingleThreadedRandomSource import net.minecraft.world.level.levelgen.synth.SimplexNoise import net.minecraft.world.phys.Vec2 import org.joml.Matrix4f -import kotlin.math.abs -import kotlin.math.min -import kotlin.math.roundToInt -import kotlin.math.sin val NOISE: SimplexNoise = SimplexNoise(SingleThreadedRandomSource(9001L)) // see the test; perlin noise seems to output almost exclusively between -0.5 and 0.5 -// i could probably impl this "properly" with some kind of exponent but it's faster and easier to divide +// i could probably impl this "properly" with some kind of exponent but it's faster and easier to +// divide fun getNoise(x: Double, y: Double, z: Double): Double = - NOISE.getValue(x * 0.6, y * 0.6, z * 0.6) / 2.0 + NOISE.getValue(x * 0.6, y * 0.6, z * 0.6) / 2.0 // how many degrees are between each triangle on the smooth caps of the lines const val CAP_THETA = 180f / 10f const val DEFAULT_READABILITY_OFFSET = 0.2f const val DEFAULT_LAST_SEGMENT_LEN_PROP = 0.8f - -fun drawLineSeq( - mat: Matrix4f, - points: List<Vec2>, - width: Float, - z: Float, - tail: Int, - head: Int -) { - return drawLineSeq(mat, points, width, tail, head, VCDrawHelper.Basic(z)) +fun drawLineSeq(mat: Matrix4f, points: List<Vec2>, width: Float, z: Float, tail: Int, head: Int) { + return drawLineSeq(mat, points, width, tail, head, VCDrawHelper.Basic(z)) } /** @@ -60,148 +53,157 @@ fun drawLineSeq( * Please make sure to enable the right asinine shaders; see [GuiSpellcasting] */ fun drawLineSeq( - mat: Matrix4f, - points: List<Vec2>, - width: Float, - tail: Int, - head: Int, - vcHelper: VCDrawHelper + mat: Matrix4f, + points: List<Vec2>, + width: Float, + tail: Int, + head: Int, + vcHelper: VCDrawHelper ) { - if (points.size <= 1) return - - val r1 = FastColor.ARGB32.red(tail).toFloat() - val g1 = FastColor.ARGB32.green(tail).toFloat() - val b1 = FastColor.ARGB32.blue(tail).toFloat() - val a = FastColor.ARGB32.alpha(tail) - val a1 = a.toFloat() - val headSource = if (Screen.hasControlDown() != HexConfig.client().ctrlTogglesOffStrokeOrder()) - head - else - tail - val r2 = FastColor.ARGB32.red(headSource).toFloat() - val g2 = FastColor.ARGB32.green(headSource).toFloat() - val b2 = FastColor.ARGB32.blue(headSource).toFloat() - val a2 = FastColor.ARGB32.alpha(headSource).toFloat() - - var vc = vcHelper.vcSetupAndSupply(VertexFormat.Mode.TRIANGLES) - - val n = points.size - val joinAngles = FloatArray(n) - val joinOffsets = FloatArray(n) - for (i in 2 until n) { - val p0 = points[i - 2] - val p1 = points[i - 1] - val p2 = points[i] - val prev = p1.add(p0.negated()) - val next = p2.add(p1.negated()) - val angle = - Mth.atan2((prev.x * next.y - prev.y * next.x).toDouble(), (prev.x * next.x + prev.y * next.y).toDouble()) - .toFloat() - joinAngles[i - 1] = angle - val clamp = prev.length().coerceAtMost(next.length()) / (width * 0.5f) - joinOffsets[i - 1] = Mth.clamp(Mth.sin(angle) / (1 + Mth.cos(angle)), -clamp, clamp) - } - - for (i in 0 until points.size - 1) { - val p1 = points[i] - val p2 = points[i + 1] - // https://github.com/not-fl3/macroquad/blob/master/src/shapes.rs#L163 - // GuiComponent::innerFill line 52 - // fedor have useful variable names challenge (99% can't beat) - val tangent = p2.add(p1.negated()).normalized().scale(width * 0.5f) - val normal = Vec2(-tangent.y, tangent.x) - - fun color(time: Float): Int = - FastColor.ARGB32.color(Mth.lerp(time, a1, a2).toInt(), Mth.lerp(time, r1, r2).toInt(), - Mth.lerp(time, g1, g2).toInt(), Mth.lerp(time, b1, b2).toInt()) - - val color1 = color(i.toFloat() / n) - val color2 = color((i + 1f) / n) - val jlow = joinOffsets[i] - val jhigh = joinOffsets[i + 1] - // Draw the line segment as a hexagon, sort of - // I can't imagine what the hell alwinfy is up to but this is implementing what TRIANGLE_FAN does - // using normal triangles so we can send the entire segment to the buffer at once - val p1Down = p1.add(tangent.scale(Math.max(0f, jlow))).add(normal) - val p1Up = p1.add(tangent.scale(Math.max(0f, -jlow))).add(normal.negated()) - val p2Down = p2.add(tangent.scale(Math.max(0f, jhigh)).negated()).add(normal) - val p2Up = p2.add(tangent.scale(Math.max(0f, -jhigh)).negated()).add(normal.negated()) - - vcHelper.vertex(vc, color1, p1Down, mat) - vcHelper.vertex(vc, color1, p1, mat) - vcHelper.vertex(vc, color1, p1Up, mat) - - vcHelper.vertex(vc, color1, p1Down, mat) - vcHelper.vertex(vc, color1, p1Up, mat) - vcHelper.vertex(vc, color2, p2Up, mat) - - vcHelper.vertex(vc, color1, p1Down, mat) - vcHelper.vertex(vc, color2, p2Up, mat) - vcHelper.vertex(vc, color2, p2, mat) - - vcHelper.vertex(vc, color1, p1Down, mat) - vcHelper.vertex(vc, color2, p2, mat) - vcHelper.vertex(vc, color2, p2Down, mat) - - if (i > 0) { - // Draw the connector to the next line segment - val sangle = joinAngles[i] - val angle = Math.abs(sangle) - val rnormal = normal.negated() - val joinSteps = Mth.ceil(angle * 180 / (CAP_THETA * Mth.PI)) - if (joinSteps < 1) { - continue - } - - if (sangle < 0) { - var prevVert = Vec2(p1.x - rnormal.x, p1.y - rnormal.y) - for (j in 1..joinSteps) { - val fan = rotate(rnormal, -sangle * (j.toFloat() / joinSteps)) - val fanShift = Vec2(p1.x - fan.x, p1.y - fan.y) - - vcHelper.vertex(vc, color1, p1, mat) - vcHelper.vertex(vc, color1, prevVert, mat) - vcHelper.vertex(vc, color1, fanShift, mat) - prevVert = fanShift - } - } else { - val startFan = rotate(normal, -sangle) - var prevVert = Vec2(p1.x - startFan.x, p1.y - startFan.y) - for (j in joinSteps - 1 downTo 0) { - val fan = rotate(normal, -sangle * (j.toFloat() / joinSteps)) - val fanShift = Vec2(p1.x - fan.x, p1.y - fan.y) - - vcHelper.vertex(vc, color1, p1, mat) - vcHelper.vertex(vc, color1, prevVert, mat) - vcHelper.vertex(vc, color1, fanShift, mat) - prevVert = fanShift - } - } - } - } - vcHelper.vcEndDrawer(vc) - - fun drawCaps(color: Int, point: Vec2, prev: Vec2) { - val tangent = point.add(prev.negated()).normalized().scale(0.5f * width) - val normal = Vec2(-tangent.y, tangent.x) - val joinSteps = Mth.ceil(180f / CAP_THETA) - vc = vcHelper.vcSetupAndSupply(VertexFormat.Mode.TRIANGLE_FAN) - vcHelper.vertex(vc, color, point, mat) - for (j in joinSteps downTo 0) { - val fan = rotate(normal, -Mth.PI * (j.toFloat() / joinSteps)) - vcHelper.vertex(vc, color, Vec2(point.x + fan.x, point.y + fan.y), mat) - } - vcHelper.vcEndDrawer(vc) - } - drawCaps(ARGB32.color(a1.toInt(), r1.toInt(), g1.toInt(), b1.toInt()), points[0], points[1]) - drawCaps(ARGB32.color(a2.toInt(), r2.toInt(), g2.toInt(), b2.toInt()), points[n - 1], points[n - 2]) + if (points.size <= 1) return + + val r1 = FastColor.ARGB32.red(tail).toFloat() + val g1 = FastColor.ARGB32.green(tail).toFloat() + val b1 = FastColor.ARGB32.blue(tail).toFloat() + val a = FastColor.ARGB32.alpha(tail) + val a1 = a.toFloat() + val headSource = + if (Screen.hasControlDown() != HexConfig.client().ctrlTogglesOffStrokeOrder()) head else tail + val r2 = FastColor.ARGB32.red(headSource).toFloat() + val g2 = FastColor.ARGB32.green(headSource).toFloat() + val b2 = FastColor.ARGB32.blue(headSource).toFloat() + val a2 = FastColor.ARGB32.alpha(headSource).toFloat() + + var vc = vcHelper.vcSetupAndSupply(VertexFormat.Mode.TRIANGLES) + + val n = points.size + val joinAngles = FloatArray(n) + val joinOffsets = FloatArray(n) + for (i in 2 until n) { + val p0 = points[i - 2] + val p1 = points[i - 1] + val p2 = points[i] + val prev = p1.add(p0.negated()) + val next = p2.add(p1.negated()) + val angle = + Mth.atan2( + (prev.x * next.y - prev.y * next.x).toDouble(), + (prev.x * next.x + prev.y * next.y).toDouble() + ) + .toFloat() + joinAngles[i - 1] = angle + val clamp = prev.length().coerceAtMost(next.length()) / (width * 0.5f) + joinOffsets[i - 1] = Mth.clamp(Mth.sin(angle) / (1 + Mth.cos(angle)), -clamp, clamp) + } + + for (i in 0 until points.size - 1) { + val p1 = points[i] + val p2 = points[i + 1] + // https://github.com/not-fl3/macroquad/blob/master/src/shapes.rs#L163 + // GuiComponent::innerFill line 52 + // fedor have useful variable names challenge (99% can't beat) + val tangent = p2.add(p1.negated()).normalized().scale(width * 0.5f) + val normal = Vec2(-tangent.y, tangent.x) + + fun color(time: Float): Int = + FastColor.ARGB32.color( + Mth.lerp(time, a1, a2).toInt(), + Mth.lerp(time, r1, r2).toInt(), + Mth.lerp(time, g1, g2).toInt(), + Mth.lerp(time, b1, b2).toInt() + ) + + val color1 = color(i.toFloat() / n) + val color2 = color((i + 1f) / n) + val jlow = joinOffsets[i] + val jhigh = joinOffsets[i + 1] + // Draw the line segment as a hexagon, sort of + // I can't imagine what the hell alwinfy is up to but this is implementing what TRIANGLE_FAN + // does + // using normal triangles so we can send the entire segment to the buffer at once + val p1Down = p1.add(tangent.scale(Math.max(0f, jlow))).add(normal) + val p1Up = p1.add(tangent.scale(Math.max(0f, -jlow))).add(normal.negated()) + val p2Down = p2.add(tangent.scale(Math.max(0f, jhigh)).negated()).add(normal) + val p2Up = p2.add(tangent.scale(Math.max(0f, -jhigh)).negated()).add(normal.negated()) + + vcHelper.vertex(vc, color1, p1Down, mat) + vcHelper.vertex(vc, color1, p1, mat) + vcHelper.vertex(vc, color1, p1Up, mat) + + vcHelper.vertex(vc, color1, p1Down, mat) + vcHelper.vertex(vc, color1, p1Up, mat) + vcHelper.vertex(vc, color2, p2Up, mat) + + vcHelper.vertex(vc, color1, p1Down, mat) + vcHelper.vertex(vc, color2, p2Up, mat) + vcHelper.vertex(vc, color2, p2, mat) + + vcHelper.vertex(vc, color1, p1Down, mat) + vcHelper.vertex(vc, color2, p2, mat) + vcHelper.vertex(vc, color2, p2Down, mat) + + if (i > 0) { + // Draw the connector to the next line segment + val sangle = joinAngles[i] + val angle = Math.abs(sangle) + val rnormal = normal.negated() + val joinSteps = Mth.ceil(angle * 180 / (CAP_THETA * Mth.PI)) + if (joinSteps < 1) { + continue + } + + if (sangle < 0) { + var prevVert = Vec2(p1.x - rnormal.x, p1.y - rnormal.y) + for (j in 1..joinSteps) { + val fan = rotate(rnormal, -sangle * (j.toFloat() / joinSteps)) + val fanShift = Vec2(p1.x - fan.x, p1.y - fan.y) + + vcHelper.vertex(vc, color1, p1, mat) + vcHelper.vertex(vc, color1, prevVert, mat) + vcHelper.vertex(vc, color1, fanShift, mat) + prevVert = fanShift + } + } else { + val startFan = rotate(normal, -sangle) + var prevVert = Vec2(p1.x - startFan.x, p1.y - startFan.y) + for (j in joinSteps - 1 downTo 0) { + val fan = rotate(normal, -sangle * (j.toFloat() / joinSteps)) + val fanShift = Vec2(p1.x - fan.x, p1.y - fan.y) + + vcHelper.vertex(vc, color1, p1, mat) + vcHelper.vertex(vc, color1, prevVert, mat) + vcHelper.vertex(vc, color1, fanShift, mat) + prevVert = fanShift + } + } + } + } + vcHelper.vcEndDrawer(vc) + + fun drawCaps(color: Int, point: Vec2, prev: Vec2) { + val tangent = point.add(prev.negated()).normalized().scale(0.5f * width) + val normal = Vec2(-tangent.y, tangent.x) + val joinSteps = Mth.ceil(180f / CAP_THETA) + vc = vcHelper.vcSetupAndSupply(VertexFormat.Mode.TRIANGLE_FAN) + vcHelper.vertex(vc, color, point, mat) + for (j in joinSteps downTo 0) { + val fan = rotate(normal, -Mth.PI * (j.toFloat() / joinSteps)) + vcHelper.vertex(vc, color, Vec2(point.x + fan.x, point.y + fan.y), mat) + } + vcHelper.vcEndDrawer(vc) + } + drawCaps(ARGB32.color(a1.toInt(), r1.toInt(), g1.toInt(), b1.toInt()), points[0], points[1]) + drawCaps( + ARGB32.color(a2.toInt(), r2.toInt(), g2.toInt(), b2.toInt()), + points[n - 1], + points[n - 2] + ) } - fun rotate(vec: Vec2, theta: Float): Vec2 { - val cos = Mth.cos(theta) - val sin = Mth.sin(theta) - return Vec2(vec.x * cos - vec.y * sin, vec.y * cos + vec.x * sin) + val cos = Mth.cos(theta) + val sin = Mth.sin(theta) + return Vec2(vec.x * cos - vec.y * sin, vec.y * cos + vec.x * sin) } /** @@ -209,257 +211,276 @@ fun rotate(vec: Vec2, theta: Float): Vec2 { * you have to do the conversion yourself.) */ fun drawPatternFromPoints( - mat: Matrix4f, - points: List<Vec2>, - dupIndices: Set<Int>?, - drawLast: Boolean, - tail: Int, - head: Int, - flowIrregular: Float, - readabilityOffset: Float, - lastSegmentLenProportion: Float, - seed: Double + mat: Matrix4f, + points: List<Vec2>, + dupIndices: Set<Int>?, + drawLast: Boolean, + tail: Int, + head: Int, + flowIrregular: Float, + readabilityOffset: Float, + lastSegmentLenProportion: Float, + seed: Double ) { - val zappyPts = makeZappy(points, dupIndices, 10, 2.5f, 0.1f, flowIrregular, readabilityOffset, lastSegmentLenProportion, seed) - val nodes = if (drawLast) { - points - } else { - points.dropLast(1) - } - drawLineSeq(mat, zappyPts, 5f, 0f, tail, head) - drawLineSeq(mat, zappyPts, 2f, 1f, screenCol(tail), screenCol(head)) - for (node in nodes) { - drawSpot( - mat, - node, - 2f, - dodge(FastColor.ARGB32.red(head)) / 255f, - dodge(FastColor.ARGB32.green(head)) / 255f, - dodge(FastColor.ARGB32.blue(head)) / 255f, - FastColor.ARGB32.alpha(head) / 255f - ) - } + val zappyPts = + makeZappy( + points, + dupIndices, + 10, + 2.5f, + 0.1f, + flowIrregular, + readabilityOffset, + lastSegmentLenProportion, + seed + ) + val nodes = + if (drawLast) { + points + } else { + points.dropLast(1) + } + drawLineSeq(mat, zappyPts, 5f, 0f, tail, head) + drawLineSeq(mat, zappyPts, 2f, 1f, screenCol(tail), screenCol(head)) + for (node in nodes) { + drawSpot( + mat, + node, + 2f, + dodge(FastColor.ARGB32.red(head)) / 255f, + dodge(FastColor.ARGB32.green(head)) / 255f, + dodge(FastColor.ARGB32.blue(head)) / 255f, + FastColor.ARGB32.alpha(head) / 255f + ) + } } /** * Split up a sequence of linePoints with a lightning effect + * * @param hops: rough number of points to subdivide each segment into * @param speed: rate at which the lightning effect should move/shake/etc */ fun makeZappy( - barePoints: List<Vec2>, dupIndices: Set<Int>?, hops: Int, variance: Float, speed: Float, flowIrregular: Float, - readabilityOffset: Float, lastSegmentLenProportion: Float, seed: Double + barePoints: List<Vec2>, + dupIndices: Set<Int>?, + hops: Int, + variance: Float, + speed: Float, + flowIrregular: Float, + readabilityOffset: Float, + lastSegmentLenProportion: Float, + seed: Double ): List<Vec2> { - // Nothing in, nothing out - if (barePoints.isEmpty()) { - return emptyList() - } - fun zappify(points: List<Vec2>, truncateLast: Boolean): List<Vec2> { - val scaleVariance = { it: Double -> 1.0.coerceAtMost(8 * (0.5 - abs(0.5 - it))) } - val zSeed = ClientTickCounter.getTotal().toDouble() * speed - // Create our output list of zap points - val zappyPts = ArrayList<Vec2>(points.size * hops) - zappyPts.add(points[0]) - // For each segment in the original... - for ((i, pair) in points.zipWithNext().withIndex()) { - val (src, target) = pair - val delta = target.add(src.negated()) - // Take hop distance - val hopDist = Mth.sqrt(src.distanceToSqr(target)) / hops - // Compute how big the radius of variance should be - val maxVariance = hopDist * variance - - // for a list of length n, there will be n-1 pairs, - // and so the last index will be (n-1)-1 - val maxJ = if (truncateLast && i == points.size - 2) { - (lastSegmentLenProportion * hops.toFloat()).roundToInt() - } else hops - - for (j in 1..maxJ) { - val progress = j.toDouble() / (hops + 1) - // Add the next hop... - val pos = src.add(delta.scale(progress.toFloat())) - // as well as some random variance... - // (We use i, j (segment #, subsegment #) as seeds for the Perlin noise, - // and zSeed (i.e. time elapsed) to perturb the shape gradually over time) - val minorPerturb = getNoise(i.toDouble(), j.toDouble(), sin(zSeed)) * flowIrregular - val theta = (3 * getNoise( - i + progress + minorPerturb - zSeed, - 1337.0, - seed - ) * TAU).toFloat() - val r = (getNoise( - i + progress - zSeed, - 69420.0, - seed - ) * maxVariance * scaleVariance(progress)).toFloat() - val randomHop = Vec2(r * Mth.cos(theta), r * Mth.sin(theta)) - // Then record the new location. - zappyPts.add(pos.add(randomHop)) - - if (j == hops) { - // Finally, we hit the destination, add that too - // but we might not hit the destination if we want to stop short - zappyPts.add(target) - } - } - } - return zappyPts - } - - val points = mutableListOf<Vec2>() - val daisyChain = mutableListOf<Vec2>() - return if (dupIndices != null) { - for ((i, pair) in barePoints.zipWithNext().withIndex()) { - val (head, tail) = pair - val tangent = tail.add(head.negated()).scale(readabilityOffset) - if (i != 0 && dupIndices.contains(i)) { - daisyChain.add(head.add(tangent)) - } else { - daisyChain.add(head) - } - if (i == barePoints.size - 2) { - daisyChain.add(tail) - points.addAll(zappify(daisyChain, true)) - } else if (dupIndices.contains(i + 1)) { - daisyChain.add(tail.add(tangent.negated())) - points.addAll(zappify(daisyChain, false)) - daisyChain.clear() - } - } - points - } else { - zappify(barePoints, true) - } + // Nothing in, nothing out + if (barePoints.isEmpty()) { + return emptyList() + } + fun zappify(points: List<Vec2>, truncateLast: Boolean): List<Vec2> { + val scaleVariance = { it: Double -> 1.0.coerceAtMost(8 * (0.5 - abs(0.5 - it))) } + val zSeed = ClientTickCounter.getTotal().toDouble() * speed + // Create our output list of zap points + val zappyPts = ArrayList<Vec2>(points.size * hops) + zappyPts.add(points[0]) + // For each segment in the original... + for ((i, pair) in points.zipWithNext().withIndex()) { + val (src, target) = pair + val delta = target.add(src.negated()) + // Take hop distance + val hopDist = Mth.sqrt(src.distanceToSqr(target)) / hops + // Compute how big the radius of variance should be + val maxVariance = hopDist * variance + + // for a list of length n, there will be n-1 pairs, + // and so the last index will be (n-1)-1 + val maxJ = + if (truncateLast && i == points.size - 2) { + (lastSegmentLenProportion * hops.toFloat()).roundToInt() + } else hops + + for (j in 1..maxJ) { + val progress = j.toDouble() / (hops + 1) + // Add the next hop... + val pos = src.add(delta.scale(progress.toFloat())) + // as well as some random variance... + // (We use i, j (segment #, subsegment #) as seeds for the Perlin noise, + // and zSeed (i.e. time elapsed) to perturb the shape gradually over time) + val minorPerturb = getNoise(i.toDouble(), j.toDouble(), sin(zSeed)) * flowIrregular + val theta = + (3 * getNoise(i + progress + minorPerturb - zSeed, 1337.0, seed) * TAU).toFloat() + val r = + (getNoise(i + progress - zSeed, 69420.0, seed) * maxVariance * scaleVariance(progress)) + .toFloat() + val randomHop = Vec2(r * Mth.cos(theta), r * Mth.sin(theta)) + // Then record the new location. + zappyPts.add(pos.add(randomHop)) + + if (j == hops) { + // Finally, we hit the destination, add that too + // but we might not hit the destination if we want to stop short + zappyPts.add(target) + } + } + } + return zappyPts + } + + val points = mutableListOf<Vec2>() + val daisyChain = mutableListOf<Vec2>() + return if (dupIndices != null) { + for ((i, pair) in barePoints.zipWithNext().withIndex()) { + val (head, tail) = pair + val tangent = tail.add(head.negated()).scale(readabilityOffset) + if (i != 0 && dupIndices.contains(i)) { + daisyChain.add(head.add(tangent)) + } else { + daisyChain.add(head) + } + if (i == barePoints.size - 2) { + daisyChain.add(tail) + points.addAll(zappify(daisyChain, true)) + } else if (dupIndices.contains(i + 1)) { + daisyChain.add(tail.add(tangent.negated())) + points.addAll(zappify(daisyChain, false)) + daisyChain.clear() + } + } + points + } else { + zappify(barePoints, true) + } } fun <T> findDupIndices(pts: Iterable<T>): Set<Int> { - val dedup = HashMap<T, Int>() - val found = HashSet<Int>() - for ((i, pt) in pts.withIndex()) { - val ix = dedup[pt] - if (ix != null) { - found.add(i) - found.add(ix) - } else { - dedup.put(pt, i) - } - } - return found + val dedup = HashMap<T, Int>() + val found = HashSet<Int>() + for ((i, pt) in pts.withIndex()) { + val ix = dedup[pt] + if (ix != null) { + found.add(i) + found.add(ix) + } else { + dedup.put(pt, i) + } + } + return found } /** - * Draw a little circle, because Minecraft rendering code is a nightmare and doesn't - * include primitive drawing code... + * Draw a little circle, because Minecraft rendering code is a nightmare and doesn't include + * primitive drawing code... */ fun drawSpot(mat: Matrix4f, point: Vec2, radius: Float, r: Float, g: Float, b: Float, a: Float) { - drawSpot(mat, point, radius, ARGB32.color((a*255).toInt(), (r*255).toInt(), (g*255).toInt(), (b*255).toInt()), VCDrawHelper.Basic(1f)) + drawSpot( + mat, + point, + radius, + ARGB32.color((a * 255).toInt(), (r * 255).toInt(), (g * 255).toInt(), (b * 255).toInt()), + VCDrawHelper.Basic(1f) + ) } fun drawSpot(mat: Matrix4f, point: Vec2, radius: Float, color: Int, vcHelper: VCDrawHelper) { - var vc = vcHelper.vcSetupAndSupply(VertexFormat.Mode.TRIANGLE_FAN); - vcHelper.vertex(vc, color, point, mat) - - // https://github.com/not-fl3/macroquad/blob/master/src/shapes.rs#L98 - // yes they are gonna be little hexagons fite me - val fracOfCircle = 6 - // run 0 AND last; this way the circle closes - for (i in 0..fracOfCircle) { - val theta = i.toFloat() / fracOfCircle * TAU.toFloat() - val rx = Mth.cos(theta) * radius + point.x - val ry = Mth.sin(theta) * radius + point.y - vcHelper.vertex(vc, color, Vec2(rx, ry), mat) - } - - vcHelper.vcEndDrawer(vc) + var vc = vcHelper.vcSetupAndSupply(VertexFormat.Mode.TRIANGLE_FAN) + vcHelper.vertex(vc, color, point, mat) + + // https://github.com/not-fl3/macroquad/blob/master/src/shapes.rs#L98 + // yes they are gonna be little hexagons fite me + val fracOfCircle = 6 + // run 0 AND last; this way the circle closes + for (i in 0..fracOfCircle) { + val theta = i.toFloat() / fracOfCircle * TAU.toFloat() + val rx = Mth.cos(theta) * radius + point.x + val ry = Mth.sin(theta) * radius + point.y + vcHelper.vertex(vc, color, Vec2(rx, ry), mat) + } + + vcHelper.vcEndDrawer(vc) } fun screenCol(n: Int): Int { - return FastColor.ARGB32.color( - FastColor.ARGB32.alpha(n), - screen(FastColor.ARGB32.red(n)), - screen(FastColor.ARGB32.green(n)), - screen(FastColor.ARGB32.blue(n)), - ) + return FastColor.ARGB32.color( + FastColor.ARGB32.alpha(n), + screen(FastColor.ARGB32.red(n)), + screen(FastColor.ARGB32.green(n)), + screen(FastColor.ARGB32.blue(n)), + ) } fun screen(n: Int) = (n + 255) / 2 + fun dodge(n: Int) = n * 0.9f -/** - * Return the scale and dots formed by the pattern when centered. - */ -fun getCenteredPattern(pattern: HexPattern, width: Float, height: Float, minSize: Float): Pair<Float, List<Vec2>> { - // Do two passes: one with a random size to find a good COM and one with the real calculation - val com1: Vec2 = pattern.getCenter(1f) - val lines1: List<Vec2> = pattern.toLines(1f, Vec2.ZERO) - var maxDx = -1f - var maxDy = -1f - for (dot in lines1) { - val dx = Mth.abs(dot.x - com1.x) - if (dx > maxDx) { - maxDx = dx - } - val dy = Mth.abs(dot.y - com1.y) - if (dy > maxDy) { - maxDy = dy - } - } - val scale = - min(minSize, min(width / 3f / maxDx, height / 3f / maxDy)) - val com2: Vec2 = pattern.getCenter(scale) - val lines2: List<Vec2> = pattern.toLines(scale, com2.negated()) - return scale to lines2 +/** Return the scale and dots formed by the pattern when centered. */ +fun getCenteredPattern( + pattern: HexPattern, + width: Float, + height: Float, + minSize: Float +): Pair<Float, List<Vec2>> { + // Do two passes: one with a random size to find a good COM and one with the real calculation + val com1: Vec2 = pattern.getCenter(1f) + val lines1: List<Vec2> = pattern.toLines(1f, Vec2.ZERO) + var maxDx = -1f + var maxDy = -1f + for (dot in lines1) { + val dx = Mth.abs(dot.x - com1.x) + if (dx > maxDx) { + maxDx = dx + } + val dy = Mth.abs(dot.y - com1.y) + if (dy > maxDy) { + maxDy = dy + } + } + val scale = min(minSize, min(width / 3f / maxDx, height / 3f / maxDy)) + val com2: Vec2 = pattern.getCenter(scale) + val lines2: List<Vec2> = pattern.toLines(scale, com2.negated()) + return scale to lines2 } @JvmOverloads fun renderEntity( - graphics: GuiGraphics, entity: Entity, world: Level, x: Float, y: Float, rotation: Float, - renderScale: Float, offset: Float, - bufferTransformer: (MultiBufferSource) -> MultiBufferSource = { it -> it } + graphics: GuiGraphics, + entity: Entity, + world: Level, + x: Float, + y: Float, + rotation: Float, + renderScale: Float, + offset: Float, + bufferTransformer: (MultiBufferSource) -> MultiBufferSource = { it -> it } ) { - val rotation = if (Screen.hasShiftDown()) 0.0f else rotation - - // TODO: Figure out why this is here and whether removing it will break things -// entity.level = world - val ps = graphics.pose() - - ps.pushPose() - ps.translate(x.toDouble(), y.toDouble(), 50.0) - ps.scale(renderScale, renderScale, renderScale) - ps.translate(0.0, offset.toDouble(), 0.0) - ps.mulPose(Axis.ZP.rotationDegrees(180.0f)) - ps.mulPose(Axis.YP.rotationDegrees(rotation)) - val erd = Minecraft.getInstance().entityRenderDispatcher - val immediate = Minecraft.getInstance().renderBuffers().bufferSource() - erd.setRenderShadow(false) - erd.render(entity, 0.0, 0.0, 0.0, 0.0f, 1.0f, ps, bufferTransformer(immediate), 0xf000f0) - erd.setRenderShadow(true) - immediate.endBatch() - ps.popPose() + val rotation = if (Screen.hasShiftDown()) 0.0f else rotation + + // TODO: Figure out why this is here and whether removing it will break things + // entity.level = world + val ps = graphics.pose() + + ps.pushPose() + ps.translate(x.toDouble(), y.toDouble(), 50.0) + ps.scale(renderScale, renderScale, renderScale) + ps.translate(0.0, offset.toDouble(), 0.0) + ps.mulPose(Axis.ZP.rotationDegrees(180.0f)) + ps.mulPose(Axis.YP.rotationDegrees(rotation)) + val erd = Minecraft.getInstance().entityRenderDispatcher + val immediate = Minecraft.getInstance().renderBuffers().bufferSource() + erd.setRenderShadow(false) + erd.render(entity, 0.0, 0.0, 0.0, 0.0f, 1.0f, ps, bufferTransformer(immediate), 0xf000f0) + erd.setRenderShadow(true) + immediate.endBatch() + ps.popPose() } -/** - * Make sure you have the `PositionColorShader` set - */ -fun renderQuad( - ps: PoseStack, x: Float, y: Float, w: Float, h: Float, color: Int -) { - val mat = ps.last().pose() - val tess = Tesselator.getInstance() - val buf = tess.builder - buf.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR) - buf.vertex(mat, x, y, 0f) - .color(color) - .endVertex() - buf.vertex(mat, x, y + h, 0f) - .color(color) - .endVertex() - buf.vertex(mat, x + w, y + h, 0f) - .color(color) - .endVertex() - buf.vertex(mat, x + w, y, 0f) - .color(color) - .endVertex() - tess.end() +/** Make sure you have the `PositionColorShader` set */ +fun renderQuad(ps: PoseStack, x: Float, y: Float, w: Float, h: Float, color: Int) { + val mat = ps.last().pose() + val tess = Tesselator.getInstance() + val buf = tess.builder + buf.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR) + buf.vertex(mat, x, y, 0f).color(color).endVertex() + buf.vertex(mat, x, y + h, 0f).color(color).endVertex() + buf.vertex(mat, x + w, y + h, 0f).color(color).endVertex() + buf.vertex(mat, x + w, y, 0f).color(color).endVertex() + tess.end() } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/ScryingLensOverlays.java b/Common/src/main/java/at/petrak/hexcasting/client/render/ScryingLensOverlays.java index 32aed05c7a..d3a6cb5e4c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/ScryingLensOverlays.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/ScryingLensOverlays.java @@ -7,6 +7,7 @@ import at.petrak.hexcasting.common.blocks.akashic.BlockEntityAkashicBookshelf; import at.petrak.hexcasting.common.lib.HexBlocks; import com.mojang.datafixers.util.Pair; +import java.util.function.UnaryOperator; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -24,243 +25,260 @@ import net.minecraft.world.level.block.state.properties.RailShape; import net.minecraft.world.level.material.MapColor; -import java.util.function.UnaryOperator; - public class ScryingLensOverlays { - public static void addScryingLensStuff() { - ScryingLensOverlayRegistry.addPredicateDisplayer( - (state, pos, observer, world, direction) -> state.getBlock() instanceof BlockAbstractImpetus, - (lines, state, pos, observer, world, direction) -> { - if (world.getBlockEntity(pos) instanceof BlockEntityAbstractImpetus beai) { - beai.applyScryingLensOverlay(lines, state, pos, observer, world, direction); - } - }); - - ScryingLensOverlayRegistry.addDisplayer(Blocks.NOTE_BLOCK, - (lines, state, pos, observer, world, direction) -> { - int note = state.getValue(NoteBlock.NOTE); + public static void addScryingLensStuff() { + ScryingLensOverlayRegistry.addPredicateDisplayer( + (state, pos, observer, world, direction) -> + state.getBlock() instanceof BlockAbstractImpetus, + (lines, state, pos, observer, world, direction) -> { + if (world.getBlockEntity(pos) instanceof BlockEntityAbstractImpetus beai) { + beai.applyScryingLensOverlay(lines, state, pos, observer, world, direction); + } + }); - float rCol = Math.max(0.0F, Mth.sin((note / 24F + 0.0F) * Mth.TWO_PI) * 0.65F + 0.35F); - float gCol = Math.max(0.0F, Mth.sin((note / 24F + 0.33333334F) * Mth.TWO_PI) * 0.65F + 0.35F); - float bCol = Math.max(0.0F, Mth.sin((note / 24F + 0.6666667F) * Mth.TWO_PI) * 0.65F + 0.35F); + ScryingLensOverlayRegistry.addDisplayer( + Blocks.NOTE_BLOCK, + (lines, state, pos, observer, world, direction) -> { + int note = state.getValue(NoteBlock.NOTE); - int noteColor = 0xFF_000000 | Mth.color(rCol, gCol, bCol); + float rCol = Math.max(0.0F, Mth.sin((note / 24F + 0.0F) * Mth.TWO_PI) * 0.65F + 0.35F); + float gCol = + Math.max(0.0F, Mth.sin((note / 24F + 0.33333334F) * Mth.TWO_PI) * 0.65F + 0.35F); + float bCol = + Math.max(0.0F, Mth.sin((note / 24F + 0.6666667F) * Mth.TWO_PI) * 0.65F + 0.35F); - var instrument = state.getValue(NoteBlock.INSTRUMENT); + int noteColor = 0xFF_000000 | Mth.color(rCol, gCol, bCol); - lines.add(new Pair<>( - new ItemStack(Items.MUSIC_DISC_CHIRP), - Component.literal(String.valueOf(instrument.ordinal())) - .withStyle(color(instrumentColor(instrument))))); - lines.add(new Pair<>( - new ItemStack(Items.NOTE_BLOCK), - Component.literal(String.valueOf(note)) - .withStyle(color(noteColor)))); - }); + var instrument = state.getValue(NoteBlock.INSTRUMENT); - ScryingLensOverlayRegistry.addDisplayer(HexBlocks.AKASHIC_BOOKSHELF, - (lines, state, pos, observer, world, direction) -> { - if (world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile) { - var iotaTag = tile.getIotaTag(); - if (iotaTag != null) { - var display = IotaType.getDisplay(iotaTag); - lines.add(new Pair<>(new ItemStack(Items.BOOK), display)); - } - } - }); + lines.add( + new Pair<>( + new ItemStack(Items.MUSIC_DISC_CHIRP), + Component.literal(String.valueOf(instrument.ordinal())) + .withStyle(color(instrumentColor(instrument))))); + lines.add( + new Pair<>( + new ItemStack(Items.NOTE_BLOCK), + Component.literal(String.valueOf(note)).withStyle(color(noteColor)))); + }); - ScryingLensOverlayRegistry.addDisplayer(Blocks.COMPARATOR, - (lines, state, pos, observer, world, direction) -> { - int comparatorValue = state.getAnalogOutputSignal(world, pos); - lines.add(new Pair<>( - new ItemStack(Items.REDSTONE), - Component.literal(comparatorValue == -1 ? "" : String.valueOf(comparatorValue)) - .withStyle(redstoneColor(comparatorValue)))); + ScryingLensOverlayRegistry.addDisplayer( + HexBlocks.AKASHIC_BOOKSHELF, + (lines, state, pos, observer, world, direction) -> { + if (world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile) { + var iotaTag = tile.getIotaTag(); + if (iotaTag != null) { + var display = IotaType.getDisplay(iotaTag); + lines.add(new Pair<>(new ItemStack(Items.BOOK), display)); + } + } + }); - boolean compare = state.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE; + ScryingLensOverlayRegistry.addDisplayer( + Blocks.COMPARATOR, + (lines, state, pos, observer, world, direction) -> { + int comparatorValue = state.getAnalogOutputSignal(world, pos); + lines.add( + new Pair<>( + new ItemStack(Items.REDSTONE), + Component.literal(comparatorValue == -1 ? "" : String.valueOf(comparatorValue)) + .withStyle(redstoneColor(comparatorValue)))); - lines.add(new Pair<>( - new ItemStack(Items.REDSTONE_TORCH), - Component.literal(compare ? ">=" : "-") - .withStyle(redstoneColor(compare ? 0 : 15)))); - }); + boolean compare = state.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE; - ScryingLensOverlayRegistry.addDisplayer(Blocks.POWERED_RAIL, - (lines, state, pos, observer, world, direction) -> { - int power = getPoweredRailStrength(world, pos, state); - lines.add(new Pair<>( - new ItemStack(Items.POWERED_RAIL), - Component.literal(String.valueOf(power)) - .withStyle(redstoneColor(power, 9)))); - }); + lines.add( + new Pair<>( + new ItemStack(Items.REDSTONE_TORCH), + Component.literal(compare ? ">=" : "-") + .withStyle(redstoneColor(compare ? 0 : 15)))); + }); - ScryingLensOverlayRegistry.addDisplayer(Blocks.REPEATER, - (lines, state, pos, observer, world, direction) -> lines.add(new Pair<>( - new ItemStack(Items.CLOCK), - Component.literal(String.valueOf(state.getValue(RepeaterBlock.DELAY))) - .withStyle(ChatFormatting.YELLOW)))); + ScryingLensOverlayRegistry.addDisplayer( + Blocks.POWERED_RAIL, + (lines, state, pos, observer, world, direction) -> { + int power = getPoweredRailStrength(world, pos, state); + lines.add( + new Pair<>( + new ItemStack(Items.POWERED_RAIL), + Component.literal(String.valueOf(power)).withStyle(redstoneColor(power, 9)))); + }); - ScryingLensOverlayRegistry.addPredicateDisplayer( - (state, pos, observer, world, direction) -> state.isSignalSource() && !state.is( - Blocks.COMPARATOR), - (lines, state, pos, observer, world, direction) -> { - int signalStrength = 0; - if (state.getBlock() instanceof RedStoneWireBlock) { - signalStrength = state.getValue(RedStoneWireBlock.POWER); - } else { - for (Direction dir : Direction.values()) { - signalStrength = Math.max(signalStrength, state.getSignal(world, pos, dir)); - } - } + ScryingLensOverlayRegistry.addDisplayer( + Blocks.REPEATER, + (lines, state, pos, observer, world, direction) -> + lines.add( + new Pair<>( + new ItemStack(Items.CLOCK), + Component.literal(String.valueOf(state.getValue(RepeaterBlock.DELAY))) + .withStyle(ChatFormatting.YELLOW)))); - lines.add(0, new Pair<>( - new ItemStack(Items.REDSTONE), - Component.literal(String.valueOf(signalStrength)) - .withStyle(redstoneColor(signalStrength)))); - }); - } + ScryingLensOverlayRegistry.addPredicateDisplayer( + (state, pos, observer, world, direction) -> + state.isSignalSource() && !state.is(Blocks.COMPARATOR), + (lines, state, pos, observer, world, direction) -> { + int signalStrength = 0; + if (state.getBlock() instanceof RedStoneWireBlock) { + signalStrength = state.getValue(RedStoneWireBlock.POWER); + } else { + for (Direction dir : Direction.values()) { + signalStrength = Math.max(signalStrength, state.getSignal(world, pos, dir)); + } + } - private static int getPoweredRailStrength(Level level, BlockPos pos, BlockState state) { - if (level.hasNeighborSignal(pos)) - return 9; - int positiveValue = findPoweredRailSignal(level, pos, state, true, 0); - int negativeValue = findPoweredRailSignal(level, pos, state, false, 0); - return Math.max(positiveValue, negativeValue); - } + lines.add( + 0, + new Pair<>( + new ItemStack(Items.REDSTONE), + Component.literal(String.valueOf(signalStrength)) + .withStyle(redstoneColor(signalStrength)))); + }); + } - // Copypasta from PoweredRailBlock.class - private static int findPoweredRailSignal(Level level, BlockPos pos, BlockState state, boolean travelPositive, - int depth) { - if (depth >= 8) { - return 0; - } else { - int x = pos.getX(); - int y = pos.getY(); - int z = pos.getZ(); - boolean descending = true; - RailShape shape = state.getValue(PoweredRailBlock.SHAPE); - switch (shape) { - case NORTH_SOUTH: - if (travelPositive) { - ++z; - } else { - --z; - } - break; - case EAST_WEST: - if (travelPositive) { - --x; - } else { - ++x; - } - break; - case ASCENDING_EAST: - if (travelPositive) { - --x; - } else { - ++x; - ++y; - descending = false; - } + private static int getPoweredRailStrength(Level level, BlockPos pos, BlockState state) { + if (level.hasNeighborSignal(pos)) return 9; + int positiveValue = findPoweredRailSignal(level, pos, state, true, 0); + int negativeValue = findPoweredRailSignal(level, pos, state, false, 0); + return Math.max(positiveValue, negativeValue); + } - shape = RailShape.EAST_WEST; - break; - case ASCENDING_WEST: - if (travelPositive) { - --x; - ++y; - descending = false; - } else { - ++x; - } + // Copypasta from PoweredRailBlock.class + private static int findPoweredRailSignal( + Level level, BlockPos pos, BlockState state, boolean travelPositive, int depth) { + if (depth >= 8) { + return 0; + } else { + int x = pos.getX(); + int y = pos.getY(); + int z = pos.getZ(); + boolean descending = true; + RailShape shape = state.getValue(PoweredRailBlock.SHAPE); + switch (shape) { + case NORTH_SOUTH: + if (travelPositive) { + ++z; + } else { + --z; + } + break; + case EAST_WEST: + if (travelPositive) { + --x; + } else { + ++x; + } + break; + case ASCENDING_EAST: + if (travelPositive) { + --x; + } else { + ++x; + ++y; + descending = false; + } - shape = RailShape.EAST_WEST; - break; - case ASCENDING_NORTH: - if (travelPositive) { - ++z; - } else { - --z; - ++y; - descending = false; - } + shape = RailShape.EAST_WEST; + break; + case ASCENDING_WEST: + if (travelPositive) { + --x; + ++y; + descending = false; + } else { + ++x; + } - shape = RailShape.NORTH_SOUTH; - break; - case ASCENDING_SOUTH: - if (travelPositive) { - ++z; - ++y; - descending = false; - } else { - --z; - } + shape = RailShape.EAST_WEST; + break; + case ASCENDING_NORTH: + if (travelPositive) { + ++z; + } else { + --z; + ++y; + descending = false; + } - shape = RailShape.NORTH_SOUTH; - } + shape = RailShape.NORTH_SOUTH; + break; + case ASCENDING_SOUTH: + if (travelPositive) { + ++z; + ++y; + descending = false; + } else { + --z; + } - int power = getPowerFromRail(level, new BlockPos(x, y, z), travelPositive, depth, - shape); + shape = RailShape.NORTH_SOUTH; + } - if (power > 0) { - return power; - } else if (descending) { - return getPowerFromRail(level, new BlockPos(x, y - 1, z), travelPositive, depth, - shape); - } else { - return 0; - } - } - } + int power = getPowerFromRail(level, new BlockPos(x, y, z), travelPositive, depth, shape); + if (power > 0) { + return power; + } else if (descending) { + return getPowerFromRail(level, new BlockPos(x, y - 1, z), travelPositive, depth, shape); + } else { + return 0; + } + } + } - private static UnaryOperator<Style> color(int color) { - return (style) -> style.withColor(TextColor.fromRgb(color)); - } + private static UnaryOperator<Style> color(int color) { + return (style) -> style.withColor(TextColor.fromRgb(color)); + } - private static UnaryOperator<Style> redstoneColor(int power) { - return redstoneColor(power, 15); - } + private static UnaryOperator<Style> redstoneColor(int power) { + return redstoneColor(power, 15); + } - private static UnaryOperator<Style> redstoneColor(int power, int max) { - return color(RedStoneWireBlock.getColorForPower(Mth.clamp((power * max) / 15, 0, 15))); - } + private static UnaryOperator<Style> redstoneColor(int power, int max) { + return color(RedStoneWireBlock.getColorForPower(Mth.clamp((power * max) / 15, 0, 15))); + } - private static int instrumentColor(NoteBlockInstrument instrument) { - return switch (instrument) { - case BASEDRUM -> MapColor.STONE.col; - case SNARE, XYLOPHONE, PLING -> MapColor.SAND.col; - case HAT -> MapColor.QUARTZ.col; - case BASS -> MapColor.WOOD.col; - case FLUTE -> MapColor.CLAY.col; - case BELL -> MapColor.GOLD.col; - case GUITAR -> MapColor.WOOL.col; - case CHIME -> MapColor.ICE.col; - case IRON_XYLOPHONE -> MapColor.METAL.col; - case COW_BELL -> MapColor.COLOR_BROWN.col; - case DIDGERIDOO -> MapColor.COLOR_ORANGE.col; - case BIT -> MapColor.EMERALD.col; - case BANJO -> MapColor.COLOR_YELLOW.col; - default -> -1; - }; - } + private static int instrumentColor(NoteBlockInstrument instrument) { + return switch (instrument) { + case BASEDRUM -> MapColor.STONE.col; + case SNARE, XYLOPHONE, PLING -> MapColor.SAND.col; + case HAT -> MapColor.QUARTZ.col; + case BASS -> MapColor.WOOD.col; + case FLUTE -> MapColor.CLAY.col; + case BELL -> MapColor.GOLD.col; + case GUITAR -> MapColor.WOOL.col; + case CHIME -> MapColor.ICE.col; + case IRON_XYLOPHONE -> MapColor.METAL.col; + case COW_BELL -> MapColor.COLOR_BROWN.col; + case DIDGERIDOO -> MapColor.COLOR_ORANGE.col; + case BIT -> MapColor.EMERALD.col; + case BANJO -> MapColor.COLOR_YELLOW.col; + default -> -1; + }; + } - private static int getPowerFromRail(Level level, BlockPos pos, boolean travelPositive, int depth, RailShape shape) { - BlockState otherState = level.getBlockState(pos); - if (!otherState.is(Blocks.POWERED_RAIL)) { - return 0; - } else { - RailShape otherShape = otherState.getValue(PoweredRailBlock.SHAPE); - if (shape == RailShape.EAST_WEST && (otherShape == RailShape.NORTH_SOUTH || otherShape == RailShape.ASCENDING_NORTH || otherShape == RailShape.ASCENDING_SOUTH)) { - return 0; - } else if (shape == RailShape.NORTH_SOUTH && (otherShape == RailShape.EAST_WEST || otherShape == RailShape.ASCENDING_EAST || otherShape == RailShape.ASCENDING_WEST)) { - return 0; - } else if (otherState.getValue(PoweredRailBlock.POWERED)) { - return level.hasNeighborSignal(pos) ? 8 - depth : findPoweredRailSignal(level, pos, otherState, - travelPositive, depth + 1); - } else { - return 0; - } - } - } + private static int getPowerFromRail( + Level level, BlockPos pos, boolean travelPositive, int depth, RailShape shape) { + BlockState otherState = level.getBlockState(pos); + if (!otherState.is(Blocks.POWERED_RAIL)) { + return 0; + } else { + RailShape otherShape = otherState.getValue(PoweredRailBlock.SHAPE); + if (shape == RailShape.EAST_WEST + && (otherShape == RailShape.NORTH_SOUTH + || otherShape == RailShape.ASCENDING_NORTH + || otherShape == RailShape.ASCENDING_SOUTH)) { + return 0; + } else if (shape == RailShape.NORTH_SOUTH + && (otherShape == RailShape.EAST_WEST + || otherShape == RailShape.ASCENDING_EAST + || otherShape == RailShape.ASCENDING_WEST)) { + return 0; + } else if (otherState.getValue(PoweredRailBlock.POWERED)) { + return level.hasNeighborSignal(pos) + ? 8 - depth + : findPoweredRailSignal(level, pos, otherState, travelPositive, depth + 1); + } else { + return 0; + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/VCDrawHelper.kt b/Common/src/main/java/at/petrak/hexcasting/client/render/VCDrawHelper.kt index fb6c734e5f..6ab90d89b5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/VCDrawHelper.kt +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/VCDrawHelper.kt @@ -17,128 +17,149 @@ import net.minecraft.world.phys.Vec2 import net.minecraft.world.phys.Vec3 import org.joml.Matrix4f - interface VCDrawHelper { - fun vcSetupAndSupply(vertMode: VertexFormat.Mode): VertexConsumer - fun vertex(vc: VertexConsumer, color: Int, pos: Vec2, matrix: Matrix4f){ - vertex(vc, color, pos, Vec2(0f,0f), matrix) - } - fun vertex(vc: VertexConsumer, color: Int, pos: Vec2, uv: Vec2, matrix: Matrix4f) - - fun vcEndDrawer(vc: VertexConsumer) - - companion object { - - @JvmStatic - val WHITE: ResourceLocation = HexAPI.modLoc("textures/entity/white.png") - - @JvmStatic - fun getHelper(worldlyBits: WorldlyBits?, ps: PoseStack, z: Float, texture: ResourceLocation) : VCDrawHelper{ - if(worldlyBits != null){ - return Worldly(worldlyBits, ps, z, texture) - } - return Basic(z, texture) - } - - @JvmStatic - fun getHelper(worldlyBits: WorldlyBits?, ps: PoseStack, z: Float) : VCDrawHelper{ - return getHelper(worldlyBits, ps, z, WHITE) - } - } - - class Basic(val z: Float, val texture: ResourceLocation = WHITE) : VCDrawHelper { - - override fun vcSetupAndSupply(vertMode: VertexFormat.Mode): VertexConsumer{ - val tess = Tesselator.getInstance() - val buf = tess.builder - buf.begin(vertMode, DefaultVertexFormat.POSITION_COLOR_TEX) - RenderSystem.setShader(GameRenderer::getPositionColorTexShader); - RenderSystem.disableCull() - RenderSystem.enableDepthTest() - RenderSystem.enableBlend() - RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, - GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA) - RenderSystem.setShaderTexture(0, texture) - return buf - } - override fun vertex(vc: VertexConsumer, color: Int, pos: Vec2, uv: Vec2, matrix: Matrix4f){ - vc.vertex(matrix, pos.x, pos.y, z).color(color).uv(uv.x, uv.y).endVertex() - } - override fun vcEndDrawer(vc: VertexConsumer){ - Tesselator.getInstance().end() - } - } - - class Worldly(val worldlyBits: WorldlyBits, val ps: PoseStack, val z: Float, val texture: ResourceLocation) : VCDrawHelper { - - var lastVertMode: VertexFormat.Mode ?= null // i guess this assumes that the vcHelper is only used once at a time? maybe reconsider that - - override fun vcSetupAndSupply(vertMode: VertexFormat.Mode): VertexConsumer{ - val provider = worldlyBits.provider - if (provider is MultiBufferSource.BufferSource) { - // tells it to draw whatever was here before so that we don't get depth buffer weirdness - provider.endBatch() - } - lastVertMode = vertMode - val buf = Tesselator.getInstance().builder - if(vertMode == VertexFormat.Mode.QUADS){ - val layer = RenderType.entityTranslucentCull(texture) - layer.setupRenderState() - if (provider == null) { - buf.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.NEW_ENTITY) - RenderSystem.setShader { GameRenderer.getRendertypeEntityTranslucentCullShader() } - return buf - } else { - return provider.getBuffer(layer) - } - } - buf.begin( vertMode, DefaultVertexFormat.NEW_ENTITY ) - // Generally this would be handled by a RenderLayer, but that doesn't seem to actually work here,, - RenderSystem.setShaderTexture(0, texture) - RenderSystem.enableDepthTest() - RenderSystem.disableCull() - Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer() - RenderSystem.enableBlend() - RenderSystem.blendFuncSeparate( GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, - GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA ) - RenderSystem.setShaderColor(1f, 1f, 1f, 1f); - if (Minecraft.useShaderTransparency()) { - Minecraft.getInstance().levelRenderer.translucentTarget!!.bindWrite(false) - } - RenderSystem.setShader( GameRenderer::getRendertypeEntityTranslucentCullShader ) - return buf - } - - override fun vertex(vc: VertexConsumer, color: Int, pos: Vec2, uv: Vec2, matrix: Matrix4f){ - val nv = worldlyBits.normal?: Vec3(1.0, 1.0, 1.0) - vc.vertex(matrix, pos.x, pos.y, z) - .color(color) - .uv(uv.x, uv.y) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(worldlyBits.light?: LightTexture.FULL_BRIGHT ) - .normal(ps.last().normal(), nv.x.toFloat(), nv.y.toFloat(), nv.z.toFloat()) - - vc.endVertex() - } - override fun vcEndDrawer(vc: VertexConsumer){ - if(lastVertMode == VertexFormat.Mode.QUADS){ - if (provider == null) { - val layer = RenderType.entityTranslucentCull(texture) - layer.end(Tesselator.getInstance().builder, VertexSorting.ORTHOGRAPHIC_Z) - } - } else { - Tesselator.getInstance().end() - Minecraft.getInstance().gameRenderer.lightTexture().turnOffLightLayer() - RenderSystem.disableBlend() - RenderSystem.defaultBlendFunc() - if (Minecraft.useShaderTransparency()) { - Minecraft.getInstance().mainRenderTarget.bindWrite(false) - } - RenderSystem.enableCull() - } - lastVertMode = null - } - } - - -} \ No newline at end of file + fun vcSetupAndSupply(vertMode: VertexFormat.Mode): VertexConsumer + + fun vertex(vc: VertexConsumer, color: Int, pos: Vec2, matrix: Matrix4f) { + vertex(vc, color, pos, Vec2(0f, 0f), matrix) + } + + fun vertex(vc: VertexConsumer, color: Int, pos: Vec2, uv: Vec2, matrix: Matrix4f) + + fun vcEndDrawer(vc: VertexConsumer) + + companion object { + + @JvmStatic val WHITE: ResourceLocation = HexAPI.modLoc("textures/entity/white.png") + + @JvmStatic + fun getHelper( + worldlyBits: WorldlyBits?, + ps: PoseStack, + z: Float, + texture: ResourceLocation + ): VCDrawHelper { + if (worldlyBits != null) { + return Worldly(worldlyBits, ps, z, texture) + } + return Basic(z, texture) + } + + @JvmStatic + fun getHelper(worldlyBits: WorldlyBits?, ps: PoseStack, z: Float): VCDrawHelper { + return getHelper(worldlyBits, ps, z, WHITE) + } + } + + class Basic(val z: Float, val texture: ResourceLocation = WHITE) : VCDrawHelper { + + override fun vcSetupAndSupply(vertMode: VertexFormat.Mode): VertexConsumer { + val tess = Tesselator.getInstance() + val buf = tess.builder + buf.begin(vertMode, DefaultVertexFormat.POSITION_COLOR_TEX) + RenderSystem.setShader(GameRenderer::getPositionColorTexShader) + RenderSystem.disableCull() + RenderSystem.enableDepthTest() + RenderSystem.enableBlend() + RenderSystem.blendFunc( + GlStateManager.SourceFactor.SRC_ALPHA, + GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA + ) + RenderSystem.setShaderTexture(0, texture) + return buf + } + + override fun vertex(vc: VertexConsumer, color: Int, pos: Vec2, uv: Vec2, matrix: Matrix4f) { + vc.vertex(matrix, pos.x, pos.y, z).color(color).uv(uv.x, uv.y).endVertex() + } + + override fun vcEndDrawer(vc: VertexConsumer) { + Tesselator.getInstance().end() + } + } + + class Worldly( + val worldlyBits: WorldlyBits, + val ps: PoseStack, + val z: Float, + val texture: ResourceLocation + ) : VCDrawHelper { + + var lastVertMode: VertexFormat.Mode? = + null // i guess this assumes that the vcHelper is only used once at a time? maybe reconsider + // that + + override fun vcSetupAndSupply(vertMode: VertexFormat.Mode): VertexConsumer { + val provider = worldlyBits.provider + if (provider is MultiBufferSource.BufferSource) { + // tells it to draw whatever was here before so that we don't get depth buffer weirdness + provider.endBatch() + } + lastVertMode = vertMode + val buf = Tesselator.getInstance().builder + if (vertMode == VertexFormat.Mode.QUADS) { + val layer = RenderType.entityTranslucentCull(texture) + layer.setupRenderState() + if (provider == null) { + buf.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.NEW_ENTITY) + RenderSystem.setShader { GameRenderer.getRendertypeEntityTranslucentCullShader() } + return buf + } else { + return provider.getBuffer(layer) + } + } + buf.begin(vertMode, DefaultVertexFormat.NEW_ENTITY) + // Generally this would be handled by a RenderLayer, but that doesn't seem to actually work + // here,, + RenderSystem.setShaderTexture(0, texture) + RenderSystem.enableDepthTest() + RenderSystem.disableCull() + Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer() + RenderSystem.enableBlend() + RenderSystem.blendFuncSeparate( + GlStateManager.SourceFactor.SRC_ALPHA, + GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, + GlStateManager.SourceFactor.ONE, + GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA + ) + RenderSystem.setShaderColor(1f, 1f, 1f, 1f) + if (Minecraft.useShaderTransparency()) { + Minecraft.getInstance().levelRenderer.translucentTarget!!.bindWrite(false) + } + RenderSystem.setShader(GameRenderer::getRendertypeEntityTranslucentCullShader) + return buf + } + + override fun vertex(vc: VertexConsumer, color: Int, pos: Vec2, uv: Vec2, matrix: Matrix4f) { + val nv = worldlyBits.normal ?: Vec3(1.0, 1.0, 1.0) + vc + .vertex(matrix, pos.x, pos.y, z) + .color(color) + .uv(uv.x, uv.y) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(worldlyBits.light ?: LightTexture.FULL_BRIGHT) + .normal(ps.last().normal(), nv.x.toFloat(), nv.y.toFloat(), nv.z.toFloat()) + + vc.endVertex() + } + + override fun vcEndDrawer(vc: VertexConsumer) { + if (lastVertMode == VertexFormat.Mode.QUADS) { + if (provider == null) { + val layer = RenderType.entityTranslucentCull(texture) + layer.end(Tesselator.getInstance().builder, VertexSorting.ORTHOGRAPHIC_Z) + } + } else { + Tesselator.getInstance().end() + Minecraft.getInstance().gameRenderer.lightTexture().turnOffLightLayer() + RenderSystem.disableBlend() + RenderSystem.defaultBlendFunc() + if (Minecraft.useShaderTransparency()) { + Minecraft.getInstance().mainRenderTarget.bindWrite(false) + } + RenderSystem.enableCull() + } + lastVertMode = null + } + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/WorldlyPatternRenderHelpers.java b/Common/src/main/java/at/petrak/hexcasting/client/render/WorldlyPatternRenderHelpers.java index 68c00d5d92..25421096a8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/WorldlyPatternRenderHelpers.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/WorldlyPatternRenderHelpers.java @@ -8,6 +8,7 @@ import at.petrak.hexcasting.common.entities.EntityWallScroll; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; +import javax.annotation.Nullable; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.core.Vec3i; @@ -16,135 +17,198 @@ import net.minecraft.world.phys.Vec3; import org.joml.Matrix3f; -import javax.annotation.Nullable; - -/** - * Helper methods for rendering patterns in the world. - */ +/** Helper methods for rendering patterns in the world. */ public class WorldlyPatternRenderHelpers { - public static final PatternSettings SCROLL_SETTINGS = new PatternSettings("scroll", - PatternSettings.PositionSettings.paddedSquare(2.0/16), - PatternSettings.StrokeSettings.fromStroke(0.8/16), - PatternSettings.ZappySettings.STATIC - ); - - public static final PatternSettings READABLE_SCROLL_SETTINGS = new PatternSettings("scroll_readable", - PatternSettings.PositionSettings.paddedSquare(2.0/16), - PatternSettings.StrokeSettings.fromStroke(0.8/16), - PatternSettings.ZappySettings.READABLE - ); - - public static final PatternSettings WORLDLY_SETTINGS = new PatternSettings("worldly", - PatternSettings.PositionSettings.paddedSquare(2.0/16), - PatternSettings.StrokeSettings.fromStroke(0.8/16), - PatternSettings.ZappySettings.STATIC - ); - - public static final PatternSettings WORLDLY_SETTINGS_WOBBLY = new PatternSettings("wobbly_world", - PatternSettings.PositionSettings.paddedSquare(2.0/16), - PatternSettings.StrokeSettings.fromStroke(0.8/16), - PatternSettings.ZappySettings.WOBBLY - ); - - public static void renderPatternForScroll(HexPattern pattern, EntityWallScroll scroll, PoseStack ps, MultiBufferSource bufSource, int light, int blockSize, boolean showStrokeOrder) - { - ps.pushPose(); - ps.translate(-blockSize / 2f, -blockSize / 2f, 1f / 32f); - // there's almost certainly a better way to do this, but we're just flipping the y and z axes to fix normals - ps.last().normal().mul(new Matrix3f(1, 0, 0, 0, 0, 1, 0, 1, 0)); - renderPattern(pattern, showStrokeOrder ? READABLE_SCROLL_SETTINGS : SCROLL_SETTINGS, - showStrokeOrder ? PatternColors.READABLE_SCROLL_COLORS : PatternColors.DEFAULT_PATTERN_COLOR, - scroll.getPos().hashCode(), ps, bufSource, null, null, light, blockSize); - ps.popPose(); - } - - private static final int[] WALL_ROTATIONS = {180, 270, 0, 90}; - private static final Vec3i[] SLATE_FACINGS = {new Vec3i(0, -1, 0), new Vec3i(-1, -1, 0), new Vec3i(-1, -1, 1), new Vec3i(0, -1 , 1)}; - private static final Vec3[] WALL_NORMALS = {new Vec3(0, 0, -1), new Vec3(-1, 0, 0), new Vec3(0, 0, -1), new Vec3(-1, 0, 0)}; - private static final Vec3i[] SLATE_FLOORCEIL_FACINGS = {new Vec3i(0,0,0), new Vec3i(1,0,0), new Vec3i(1,0,1), new Vec3i(0,0,1)}; - - public static void renderPatternForSlate(BlockEntitySlate tile, HexPattern pattern, PoseStack ps, MultiBufferSource buffer, int light, BlockState bs) - { - - boolean isOnWall = bs.getValue(BlockSlate.ATTACH_FACE) == AttachFace.WALL; - boolean isOnCeiling = bs.getValue(BlockSlate.ATTACH_FACE) == AttachFace.CEILING; - int facing = bs.getValue(BlockSlate.FACING).get2DDataValue(); - - boolean wombly = bs.getValue(BlockSlate.ENERGIZED); - - ps.pushPose(); - - Vec3 normal = null; - if(isOnWall){ - ps.mulPose(Axis.ZP.rotationDegrees(180)); - Vec3i tV = SLATE_FACINGS[facing % 4]; - ps.translate(tV.getX(), tV.getY(), tV.getZ()); - ps.mulPose(Axis.YP.rotationDegrees(WALL_ROTATIONS[facing % 4])); - normal = WALL_NORMALS[facing % 4]; - } else { - Vec3i tV = SLATE_FLOORCEIL_FACINGS[facing % 4]; - ps.translate(tV.getX(), tV.getY(), tV.getZ()); - - ps.mulPose(Axis.YP.rotationDegrees(facing*-90)); - ps.mulPose(Axis.XP.rotationDegrees(90 * (isOnCeiling ? -1 : 1))); - if(isOnCeiling) ps.translate(0,-1,1); - } - - renderPattern(pattern, - wombly ? WORLDLY_SETTINGS_WOBBLY : WORLDLY_SETTINGS, - wombly ? PatternColors.SLATE_WOBBLY_PURPLE_COLOR : PatternColors.DEFAULT_PATTERN_COLOR, - tile.getBlockPos().hashCode(), ps, buffer, normal, null, light, 1); - ps.popPose(); - } - - private static final Vec3i[] BLOCK_FACINGS = {new Vec3i(0, -1, 1), new Vec3i(0, -1, 0), new Vec3i(-1, -1, 0), new Vec3i(-1, -1, 1)}; - - public static void renderPatternForAkashicBookshelf(BlockEntityAkashicBookshelf tile, HexPattern pattern, PoseStack ps, MultiBufferSource buffer, int light, BlockState bs) - { - - int facing = bs.getValue(BlockAkashicBookshelf.FACING).get2DDataValue(); - - ps.pushPose(); - ps.mulPose(Axis.ZP.rotationDegrees(180)); - - Vec3i tV = BLOCK_FACINGS[facing % 4]; - ps.translate(tV.getX(), tV.getY(), tV.getZ()); - ps.mulPose(Axis.YP.rotationDegrees(WALL_ROTATIONS[facing % 4])); - - int actualLight = LevelRenderer.getLightColor(tile.getLevel(), tile.getBlockPos().relative(bs.getValue(BlockAkashicBookshelf.FACING))); - - renderPattern(pattern, WORLDLY_SETTINGS , PatternColors.DEFAULT_PATTERN_COLOR, - tile.getBlockPos().hashCode(), ps, buffer, WALL_NORMALS[facing % 4].multiply(-1, -1, -1), -0.02f, actualLight, 1); - ps.popPose(); - } - - /** - * Renders a pattern in world space based on the given transform requirements - */ - public static void renderPattern(HexPattern pattern, PatternSettings patSets, PatternColors patColors, - double seed, PoseStack ps, MultiBufferSource bufSource, Vec3 normal, @Nullable Float zOffset, - int light, int blockSize) - { - - ps.pushPose(); - - - float z = zOffset != null ? zOffset : ((-1f / 16f) - 0.01f); - - normal = normal != null ? normal : new Vec3(0, 0, -1); - - ps.translate(0,0, z); - ps.scale(blockSize, blockSize, 1); - - - PoseStack noNormalInv = new PoseStack(); - noNormalInv.scale(1, 1, -1); - ps.mulPoseMatrix(noNormalInv.last().pose()); - - PatternRenderer.renderPattern(pattern, ps, new PatternRenderer.WorldlyBits(bufSource, light, normal), - patSets, patColors, seed, blockSize * 512); - - ps.popPose(); - } + public static final PatternSettings SCROLL_SETTINGS = + new PatternSettings( + "scroll", + PatternSettings.PositionSettings.paddedSquare(2.0 / 16), + PatternSettings.StrokeSettings.fromStroke(0.8 / 16), + PatternSettings.ZappySettings.STATIC); + + public static final PatternSettings READABLE_SCROLL_SETTINGS = + new PatternSettings( + "scroll_readable", + PatternSettings.PositionSettings.paddedSquare(2.0 / 16), + PatternSettings.StrokeSettings.fromStroke(0.8 / 16), + PatternSettings.ZappySettings.READABLE); + + public static final PatternSettings WORLDLY_SETTINGS = + new PatternSettings( + "worldly", + PatternSettings.PositionSettings.paddedSquare(2.0 / 16), + PatternSettings.StrokeSettings.fromStroke(0.8 / 16), + PatternSettings.ZappySettings.STATIC); + + public static final PatternSettings WORLDLY_SETTINGS_WOBBLY = + new PatternSettings( + "wobbly_world", + PatternSettings.PositionSettings.paddedSquare(2.0 / 16), + PatternSettings.StrokeSettings.fromStroke(0.8 / 16), + PatternSettings.ZappySettings.WOBBLY); + + public static void renderPatternForScroll( + HexPattern pattern, + EntityWallScroll scroll, + PoseStack ps, + MultiBufferSource bufSource, + int light, + int blockSize, + boolean showStrokeOrder) { + ps.pushPose(); + ps.translate(-blockSize / 2f, -blockSize / 2f, 1f / 32f); + // there's almost certainly a better way to do this, but we're just flipping the y and z axes to + // fix normals + ps.last().normal().mul(new Matrix3f(1, 0, 0, 0, 0, 1, 0, 1, 0)); + renderPattern( + pattern, + showStrokeOrder ? READABLE_SCROLL_SETTINGS : SCROLL_SETTINGS, + showStrokeOrder + ? PatternColors.READABLE_SCROLL_COLORS + : PatternColors.DEFAULT_PATTERN_COLOR, + scroll.getPos().hashCode(), + ps, + bufSource, + null, + null, + light, + blockSize); + ps.popPose(); + } + + private static final int[] WALL_ROTATIONS = {180, 270, 0, 90}; + private static final Vec3i[] SLATE_FACINGS = { + new Vec3i(0, -1, 0), new Vec3i(-1, -1, 0), new Vec3i(-1, -1, 1), new Vec3i(0, -1, 1) + }; + private static final Vec3[] WALL_NORMALS = { + new Vec3(0, 0, -1), new Vec3(-1, 0, 0), new Vec3(0, 0, -1), new Vec3(-1, 0, 0) + }; + private static final Vec3i[] SLATE_FLOORCEIL_FACINGS = { + new Vec3i(0, 0, 0), new Vec3i(1, 0, 0), new Vec3i(1, 0, 1), new Vec3i(0, 0, 1) + }; + + public static void renderPatternForSlate( + BlockEntitySlate tile, + HexPattern pattern, + PoseStack ps, + MultiBufferSource buffer, + int light, + BlockState bs) { + + boolean isOnWall = bs.getValue(BlockSlate.ATTACH_FACE) == AttachFace.WALL; + boolean isOnCeiling = bs.getValue(BlockSlate.ATTACH_FACE) == AttachFace.CEILING; + int facing = bs.getValue(BlockSlate.FACING).get2DDataValue(); + + boolean wombly = bs.getValue(BlockSlate.ENERGIZED); + + ps.pushPose(); + + Vec3 normal = null; + if (isOnWall) { + ps.mulPose(Axis.ZP.rotationDegrees(180)); + Vec3i tV = SLATE_FACINGS[facing % 4]; + ps.translate(tV.getX(), tV.getY(), tV.getZ()); + ps.mulPose(Axis.YP.rotationDegrees(WALL_ROTATIONS[facing % 4])); + normal = WALL_NORMALS[facing % 4]; + } else { + Vec3i tV = SLATE_FLOORCEIL_FACINGS[facing % 4]; + ps.translate(tV.getX(), tV.getY(), tV.getZ()); + + ps.mulPose(Axis.YP.rotationDegrees(facing * -90)); + ps.mulPose(Axis.XP.rotationDegrees(90 * (isOnCeiling ? -1 : 1))); + if (isOnCeiling) ps.translate(0, -1, 1); + } + + renderPattern( + pattern, + wombly ? WORLDLY_SETTINGS_WOBBLY : WORLDLY_SETTINGS, + wombly ? PatternColors.SLATE_WOBBLY_PURPLE_COLOR : PatternColors.DEFAULT_PATTERN_COLOR, + tile.getBlockPos().hashCode(), + ps, + buffer, + normal, + null, + light, + 1); + ps.popPose(); + } + + private static final Vec3i[] BLOCK_FACINGS = { + new Vec3i(0, -1, 1), new Vec3i(0, -1, 0), new Vec3i(-1, -1, 0), new Vec3i(-1, -1, 1) + }; + + public static void renderPatternForAkashicBookshelf( + BlockEntityAkashicBookshelf tile, + HexPattern pattern, + PoseStack ps, + MultiBufferSource buffer, + int light, + BlockState bs) { + + int facing = bs.getValue(BlockAkashicBookshelf.FACING).get2DDataValue(); + + ps.pushPose(); + ps.mulPose(Axis.ZP.rotationDegrees(180)); + + Vec3i tV = BLOCK_FACINGS[facing % 4]; + ps.translate(tV.getX(), tV.getY(), tV.getZ()); + ps.mulPose(Axis.YP.rotationDegrees(WALL_ROTATIONS[facing % 4])); + + int actualLight = + LevelRenderer.getLightColor( + tile.getLevel(), + tile.getBlockPos().relative(bs.getValue(BlockAkashicBookshelf.FACING))); + + renderPattern( + pattern, + WORLDLY_SETTINGS, + PatternColors.DEFAULT_PATTERN_COLOR, + tile.getBlockPos().hashCode(), + ps, + buffer, + WALL_NORMALS[facing % 4].multiply(-1, -1, -1), + -0.02f, + actualLight, + 1); + ps.popPose(); + } + + /** Renders a pattern in world space based on the given transform requirements */ + public static void renderPattern( + HexPattern pattern, + PatternSettings patSets, + PatternColors patColors, + double seed, + PoseStack ps, + MultiBufferSource bufSource, + Vec3 normal, + @Nullable Float zOffset, + int light, + int blockSize) { + + ps.pushPose(); + + float z = zOffset != null ? zOffset : ((-1f / 16f) - 0.01f); + + normal = normal != null ? normal : new Vec3(0, 0, -1); + + ps.translate(0, 0, z); + ps.scale(blockSize, blockSize, 1); + + PoseStack noNormalInv = new PoseStack(); + noNormalInv.scale(1, 1, -1); + ps.mulPoseMatrix(noNormalInv.last().pose()); + + PatternRenderer.renderPattern( + pattern, + ps, + new PatternRenderer.WorldlyBits(bufSource, light, normal), + patSets, + patColors, + seed, + blockSize * 512); + + ps.popPose(); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/be/BlockEntityAkashicBookshelfRenderer.java b/Common/src/main/java/at/petrak/hexcasting/client/render/be/BlockEntityAkashicBookshelfRenderer.java index 5bc52dc211..1426521aef 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/be/BlockEntityAkashicBookshelfRenderer.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/be/BlockEntityAkashicBookshelfRenderer.java @@ -8,21 +8,28 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -public class BlockEntityAkashicBookshelfRenderer implements BlockEntityRenderer<BlockEntityAkashicBookshelf> { - public BlockEntityAkashicBookshelfRenderer(BlockEntityRendererProvider.Context ctx) { - // NO-OP - } +public class BlockEntityAkashicBookshelfRenderer + implements BlockEntityRenderer<BlockEntityAkashicBookshelf> { + public BlockEntityAkashicBookshelfRenderer(BlockEntityRendererProvider.Context ctx) { + // NO-OP + } - @Override - public void render(BlockEntityAkashicBookshelf tile, float pPartialTick, PoseStack ps, - MultiBufferSource buffer, int light, int overlay) { - HexPattern pattern = tile.getPattern(); - if (pattern == null) { - return; - } + @Override + public void render( + BlockEntityAkashicBookshelf tile, + float pPartialTick, + PoseStack ps, + MultiBufferSource buffer, + int light, + int overlay) { + HexPattern pattern = tile.getPattern(); + if (pattern == null) { + return; + } - var bs = tile.getBlockState(); + var bs = tile.getBlockState(); - WorldlyPatternRenderHelpers.renderPatternForAkashicBookshelf(tile, pattern, ps, buffer, light, bs); - } + WorldlyPatternRenderHelpers.renderPatternForAkashicBookshelf( + tile, pattern, ps, buffer, light, bs); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/be/BlockEntityQuenchedAllayRenderer.java b/Common/src/main/java/at/petrak/hexcasting/client/render/be/BlockEntityQuenchedAllayRenderer.java index 15f89ad049..8821f0c7b1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/be/BlockEntityQuenchedAllayRenderer.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/be/BlockEntityQuenchedAllayRenderer.java @@ -11,46 +11,66 @@ import net.minecraft.client.renderer.block.BlockRenderDispatcher; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.phys.AABB; // TODO: this doesn't cover the block being *behind* something. Is it possible to cleanly do that? // it would probably require some depth-texture bullshit that I don't want to worry about -public class BlockEntityQuenchedAllayRenderer implements BlockEntityRenderer<BlockEntityQuenchedAllay> { - private final BlockEntityRendererProvider.Context ctx; - - public BlockEntityQuenchedAllayRenderer(BlockEntityRendererProvider.Context ctx) { - this.ctx = ctx; - } - - private static void doRender(BlockQuenchedAllay block, BlockRenderDispatcher dispatcher, PoseStack ps, MultiBufferSource bufSource, - int packedLight, int packedOverlay) { - var buffer = bufSource.getBuffer(RenderType.translucent()); - var pose = ps.last(); - - var idx = Math.abs(GaslightingTracker.getGaslightingAmount() % BlockQuenchedAllay.VARIANTS); - var model = RegisterClientStuff.QUENCHED_ALLAY_VARIANTS.get(BuiltInRegistries.BLOCK.getKey(block)).get(idx); - - dispatcher.getModelRenderer().renderModel(pose, buffer, null, model, 1f, 1f, 1f, packedLight, packedOverlay); - } - - @Override - public void render(BlockEntityQuenchedAllay blockEntity, float partialTick, PoseStack poseStack, - MultiBufferSource bufferSource, int packedLight, int packedOverlay) { - // https://github.com/MinecraftForge/MinecraftForge/blob/79dfdb0ace9694f9dd0f1d9e8c5c24a0ae2d77f8/patches/minecraft/net/minecraft/client/renderer/LevelRenderer.java.patch#L68 - // Forge fixes BEs rendering offscreen; Fabric doesn't! - // So we do a special check on Fabric only - var pos = blockEntity.getBlockPos(); - var aabb = new AABB(pos.offset(-1, 0, -1), pos.offset(1, 1, 1)); - if (IClientXplatAbstractions.INSTANCE.fabricAdditionalQuenchFrustumCheck(aabb)) { - doRender((BlockQuenchedAllay) blockEntity.getBlockState().getBlock(), this.ctx.getBlockRenderDispatcher(), poseStack, bufferSource, packedLight, packedOverlay); - } - } - - @Override - public boolean shouldRenderOffScreen(BlockEntityQuenchedAllay blockEntity) { - return false; - } +public class BlockEntityQuenchedAllayRenderer + implements BlockEntityRenderer<BlockEntityQuenchedAllay> { + private final BlockEntityRendererProvider.Context ctx; + public BlockEntityQuenchedAllayRenderer(BlockEntityRendererProvider.Context ctx) { + this.ctx = ctx; + } + + private static void doRender( + BlockQuenchedAllay block, + BlockRenderDispatcher dispatcher, + PoseStack ps, + MultiBufferSource bufSource, + int packedLight, + int packedOverlay) { + var buffer = bufSource.getBuffer(RenderType.translucent()); + var pose = ps.last(); + + var idx = Math.abs(GaslightingTracker.getGaslightingAmount() % BlockQuenchedAllay.VARIANTS); + var model = + RegisterClientStuff.QUENCHED_ALLAY_VARIANTS + .get(BuiltInRegistries.BLOCK.getKey(block)) + .get(idx); + + dispatcher + .getModelRenderer() + .renderModel(pose, buffer, null, model, 1f, 1f, 1f, packedLight, packedOverlay); + } + + @Override + public void render( + BlockEntityQuenchedAllay blockEntity, + float partialTick, + PoseStack poseStack, + MultiBufferSource bufferSource, + int packedLight, + int packedOverlay) { + // https://github.com/MinecraftForge/MinecraftForge/blob/79dfdb0ace9694f9dd0f1d9e8c5c24a0ae2d77f8/patches/minecraft/net/minecraft/client/renderer/LevelRenderer.java.patch#L68 + // Forge fixes BEs rendering offscreen; Fabric doesn't! + // So we do a special check on Fabric only + var pos = blockEntity.getBlockPos(); + var aabb = new AABB(pos.offset(-1, 0, -1), pos.offset(1, 1, 1)); + if (IClientXplatAbstractions.INSTANCE.fabricAdditionalQuenchFrustumCheck(aabb)) { + doRender( + (BlockQuenchedAllay) blockEntity.getBlockState().getBlock(), + this.ctx.getBlockRenderDispatcher(), + poseStack, + bufferSource, + packedLight, + packedOverlay); + } + } + + @Override + public boolean shouldRenderOffScreen(BlockEntityQuenchedAllay blockEntity) { + return false; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/be/BlockEntitySlateRenderer.java b/Common/src/main/java/at/petrak/hexcasting/client/render/be/BlockEntitySlateRenderer.java index 7fbf43ffc6..32c7cb1504 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/be/BlockEntitySlateRenderer.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/be/BlockEntitySlateRenderer.java @@ -8,18 +8,22 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; public class BlockEntitySlateRenderer implements BlockEntityRenderer<BlockEntitySlate> { - public BlockEntitySlateRenderer(BlockEntityRendererProvider.Context ctx) { - // NO-OP - } + public BlockEntitySlateRenderer(BlockEntityRendererProvider.Context ctx) { + // NO-OP + } - @Override - public void render(BlockEntitySlate tile, float pPartialTick, PoseStack ps, - MultiBufferSource buffer, int light, int overlay) { - if (tile.pattern == null) - return; + @Override + public void render( + BlockEntitySlate tile, + float pPartialTick, + PoseStack ps, + MultiBufferSource buffer, + int light, + int overlay) { + if (tile.pattern == null) return; - var bs = tile.getBlockState(); + var bs = tile.getBlockState(); - WorldlyPatternRenderHelpers.renderPatternForSlate(tile, tile.pattern, ps, buffer, light, bs); - } -} \ No newline at end of file + WorldlyPatternRenderHelpers.renderPatternForSlate(tile, tile.pattern, ps, buffer, light, bs); + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/shader/FakeBufferSource.java b/Common/src/main/java/at/petrak/hexcasting/client/render/shader/FakeBufferSource.java index 78d7d16027..27b0c58db3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/shader/FakeBufferSource.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/shader/FakeBufferSource.java @@ -4,30 +4,31 @@ import at.petrak.hexcasting.mixin.accessor.client.AccessorEmptyTextureStateShard; import at.petrak.hexcasting.mixin.accessor.client.AccessorRenderStateShard; import com.mojang.blaze3d.vertex.VertexConsumer; +import java.util.Optional; +import java.util.function.Function; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.NotNull; -import java.util.Optional; -import java.util.function.Function; - -public record FakeBufferSource(MultiBufferSource parent, - Function<ResourceLocation, RenderType> mapper) implements MultiBufferSource { +public record FakeBufferSource( + MultiBufferSource parent, Function<ResourceLocation, RenderType> mapper) + implements MultiBufferSource { - @Override - @SuppressWarnings("ConstantConditions") - public @NotNull VertexConsumer getBuffer(@NotNull RenderType renderType) { - if (((AccessorRenderStateShard) renderType).hex$name().equals("entity_cutout_no_cull") - && renderType instanceof RenderType.CompositeRenderType) { - RenderType.CompositeState state = ((AccessorCompositeRenderType) renderType).hex$state(); - RenderStateShard.EmptyTextureStateShard shard = state.textureState; - Optional<ResourceLocation> texture = ((AccessorEmptyTextureStateShard) shard).hex$cutoutTexture(); - if (texture.isPresent()) { - return parent.getBuffer(mapper.apply(texture.get())); - } - } - return parent.getBuffer(renderType); - } + @Override + @SuppressWarnings("ConstantConditions") + public @NotNull VertexConsumer getBuffer(@NotNull RenderType renderType) { + if (((AccessorRenderStateShard) renderType).hex$name().equals("entity_cutout_no_cull") + && renderType instanceof RenderType.CompositeRenderType) { + RenderType.CompositeState state = ((AccessorCompositeRenderType) renderType).hex$state(); + RenderStateShard.EmptyTextureStateShard shard = state.textureState; + Optional<ResourceLocation> texture = + ((AccessorEmptyTextureStateShard) shard).hex$cutoutTexture(); + if (texture.isPresent()) { + return parent.getBuffer(mapper.apply(texture.get())); + } + } + return parent.getBuffer(renderType); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/shader/HexRenderTypes.java b/Common/src/main/java/at/petrak/hexcasting/client/render/shader/HexRenderTypes.java index ff9e549a6e..84c9ee3417 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/shader/HexRenderTypes.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/shader/HexRenderTypes.java @@ -4,42 +4,63 @@ import at.petrak.hexcasting.mixin.accessor.client.AccessorRenderType; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.VertexFormat; +import java.util.function.Function; import net.minecraft.Util; import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; -import java.util.function.Function; - // https://github.com/VazkiiMods/Botania/blob/3a43accc2fbc439c9f2f00a698f8f8ad017503db/Common/src/main/java/vazkii/botania/client/core/helper/RenderHelper.java public final class HexRenderTypes extends RenderType { - private HexRenderTypes(String string, VertexFormat vertexFormat, VertexFormat.Mode mode, int i, boolean bl, - boolean bl2, Runnable runnable, Runnable runnable2) { - super(string, vertexFormat, mode, i, bl, bl2, runnable, runnable2); - throw new UnsupportedOperationException("Should not be instantiated"); - } - - private static RenderType makeLayer(String name, VertexFormat format, VertexFormat.Mode mode, - int bufSize, boolean hasCrumbling, boolean sortOnUpload, RenderType.CompositeState glState) { - return AccessorRenderType.hex$create(name, format, mode, bufSize, hasCrumbling, sortOnUpload, glState); - } + private HexRenderTypes( + String string, + VertexFormat vertexFormat, + VertexFormat.Mode mode, + int i, + boolean bl, + boolean bl2, + Runnable runnable, + Runnable runnable2) { + super(string, vertexFormat, mode, i, bl, bl2, runnable, runnable2); + throw new UnsupportedOperationException("Should not be instantiated"); + } - private static final Function<ResourceLocation, RenderType> GRAYSCALE_PROVIDER = Util.memoize(texture -> { - CompositeState glState = RenderType.CompositeState.builder() - .setShaderState(new ShaderStateShard(HexShaders::grayscale)) - .setTextureState(new TextureStateShard(texture, false, false)) - .setTransparencyState(NO_TRANSPARENCY) - .setCullState(NO_CULL) - .setLightmapState(LIGHTMAP) - .setOverlayState(OVERLAY) - .createCompositeState(true); + private static RenderType makeLayer( + String name, + VertexFormat format, + VertexFormat.Mode mode, + int bufSize, + boolean hasCrumbling, + boolean sortOnUpload, + RenderType.CompositeState glState) { + return AccessorRenderType.hex$create( + name, format, mode, bufSize, hasCrumbling, sortOnUpload, glState); + } - return makeLayer(HexAPI.MOD_ID + ":grayscale", DefaultVertexFormat.NEW_ENTITY, VertexFormat.Mode.QUADS, 256, - true, false, glState); - }); + private static final Function<ResourceLocation, RenderType> GRAYSCALE_PROVIDER = + Util.memoize( + texture -> { + CompositeState glState = + RenderType.CompositeState.builder() + .setShaderState(new ShaderStateShard(HexShaders::grayscale)) + .setTextureState(new TextureStateShard(texture, false, false)) + .setTransparencyState(NO_TRANSPARENCY) + .setCullState(NO_CULL) + .setLightmapState(LIGHTMAP) + .setOverlayState(OVERLAY) + .createCompositeState(true); - public static RenderType getGrayscaleLayer(ResourceLocation texture) { - return GRAYSCALE_PROVIDER.apply(texture); - } + return makeLayer( + HexAPI.MOD_ID + ":grayscale", + DefaultVertexFormat.NEW_ENTITY, + VertexFormat.Mode.QUADS, + 256, + true, + false, + glState); + }); + public static RenderType getGrayscaleLayer(ResourceLocation texture) { + return GRAYSCALE_PROVIDER.apply(texture); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/render/shader/HexShaders.java b/Common/src/main/java/at/petrak/hexcasting/client/render/shader/HexShaders.java index b1a02bbf6f..1f034b802a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/render/shader/HexShaders.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/render/shader/HexShaders.java @@ -2,26 +2,27 @@ import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.datafixers.util.Pair; -import net.minecraft.client.renderer.ShaderInstance; -import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.server.packs.resources.ResourceProvider; - import java.io.IOException; import java.util.function.Consumer; +import net.minecraft.client.renderer.ShaderInstance; +import net.minecraft.server.packs.resources.ResourceProvider; // https://github.com/VazkiiMods/Botania/blob/3a43accc2fbc439c9f2f00a698f8f8ad017503db/Common/src/main/java/vazkii/botania/client/core/helper/CoreShaders.java public class HexShaders { - private static ShaderInstance grayscale; + private static ShaderInstance grayscale; - public static void init(ResourceProvider resourceProvider, - Consumer<Pair<ShaderInstance, Consumer<ShaderInstance>>> registrations) throws IOException { - registrations.accept(Pair.of( - new ShaderInstance(resourceProvider, "hexcasting__grayscale", DefaultVertexFormat.NEW_ENTITY), - inst -> grayscale = inst) - ); - } + public static void init( + ResourceProvider resourceProvider, + Consumer<Pair<ShaderInstance, Consumer<ShaderInstance>>> registrations) + throws IOException { + registrations.accept( + Pair.of( + new ShaderInstance( + resourceProvider, "hexcasting__grayscale", DefaultVertexFormat.NEW_ENTITY), + inst -> grayscale = inst)); + } - public static ShaderInstance grayscale() { - return grayscale; - } + public static ShaderInstance grayscale() { + return grayscale; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/client/sound/GridSoundInstance.kt b/Common/src/main/java/at/petrak/hexcasting/client/sound/GridSoundInstance.kt index 027fa63cb3..77b10eab04 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/sound/GridSoundInstance.kt +++ b/Common/src/main/java/at/petrak/hexcasting/client/sound/GridSoundInstance.kt @@ -11,56 +11,56 @@ import net.minecraft.world.entity.player.Player import net.minecraft.world.phys.Vec3 class GridSoundInstance(val player: Player) : - AbstractTickableSoundInstance( - HexSounds.CASTING_AMBIANCE, - SoundSource.PLAYERS, - SoundInstance.createUnseededRandom() - ) { - var mousePosX: Double = 0.5 - var mousePosY: Double = 0.5 + AbstractTickableSoundInstance( + HexSounds.CASTING_AMBIANCE, + SoundSource.PLAYERS, + SoundInstance.createUnseededRandom() + ) { + var mousePosX: Double = 0.5 + var mousePosY: Double = 0.5 - init { - val lookVec = player.lookAngle - val playerPos = player.eyePosition - this.x = playerPos.x + lookVec.x - this.y = playerPos.y + lookVec.y - this.z = playerPos.z + lookVec.z - this.attenuation = SoundInstance.Attenuation.LINEAR - this.looping = true - this.delay = 0 - this.relative = false - } + init { + val lookVec = player.lookAngle + val playerPos = player.eyePosition + this.x = playerPos.x + lookVec.x + this.y = playerPos.y + lookVec.y + this.z = playerPos.z + lookVec.z + this.attenuation = SoundInstance.Attenuation.LINEAR + this.looping = true + this.delay = 0 + this.relative = false + } - override fun tick() { - val minecraft = Minecraft.getInstance() - val screen = minecraft.screen - if (screen !is GuiSpellcasting) - stop() - else { - val horizontalPlanarVector = calculateVectorFromPitchAndYaw(player.xRot + 90, player.yRot) - val verticalPlanarVector = calculateVectorFromPitchAndYaw(player.xRot, player.yRot + 90) - val normalVector = calculateVectorFromPitchAndYaw(player.xRot, player.yRot) - val newPos = player.eyePosition - .add(normalVector) - .add(horizontalPlanarVector.scale(PAN_SCALE * 2 * (mousePosX - 0.5))) - .add(verticalPlanarVector.scale(PAN_SCALE * 2 * (mousePosY - 0.5))) - this.x = newPos.x - this.y = newPos.y - this.z = newPos.z - } - } + override fun tick() { + val minecraft = Minecraft.getInstance() + val screen = minecraft.screen + if (screen !is GuiSpellcasting) stop() + else { + val horizontalPlanarVector = calculateVectorFromPitchAndYaw(player.xRot + 90, player.yRot) + val verticalPlanarVector = calculateVectorFromPitchAndYaw(player.xRot, player.yRot + 90) + val normalVector = calculateVectorFromPitchAndYaw(player.xRot, player.yRot) + val newPos = + player.eyePosition + .add(normalVector) + .add(horizontalPlanarVector.scale(PAN_SCALE * 2 * (mousePosX - 0.5))) + .add(verticalPlanarVector.scale(PAN_SCALE * 2 * (mousePosY - 0.5))) + this.x = newPos.x + this.y = newPos.y + this.z = newPos.z + } + } - private fun calculateVectorFromPitchAndYaw(pitch: Float, yaw: Float): Vec3 { - val radiansPitch = pitch * Mth.DEG_TO_RAD - val radiansYaw = -yaw * Mth.DEG_TO_RAD - val xComponent = Mth.cos(radiansYaw).toDouble() - val zComponent = Mth.sin(radiansYaw).toDouble() - val azimuthHorizontal = Mth.cos(radiansPitch).toDouble() - val azimuthVertical = Mth.sin(radiansPitch).toDouble() - return Vec3(zComponent * azimuthHorizontal, -azimuthVertical, xComponent * azimuthHorizontal) - } + private fun calculateVectorFromPitchAndYaw(pitch: Float, yaw: Float): Vec3 { + val radiansPitch = pitch * Mth.DEG_TO_RAD + val radiansYaw = -yaw * Mth.DEG_TO_RAD + val xComponent = Mth.cos(radiansYaw).toDouble() + val zComponent = Mth.sin(radiansYaw).toDouble() + val azimuthHorizontal = Mth.cos(radiansPitch).toDouble() + val azimuthVertical = Mth.sin(radiansPitch).toDouble() + return Vec3(zComponent * azimuthHorizontal, -azimuthVertical, xComponent * azimuthHorizontal) + } - companion object { - const val PAN_SCALE = 0.5 - } + companion object { + const val PAN_SCALE = 0.5 + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockConjured.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockConjured.java index 078b819a3c..e6048d1ef3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockConjured.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockConjured.java @@ -28,104 +28,116 @@ public class BlockConjured extends Block implements EntityBlock, IForgeLikeBlock { - public BlockConjured(Properties properties) { - super(properties); - } - - @Override - public void playerWillDestroy(Level pLevel, BlockPos pPos, BlockState pState, Player pPlayer) { - super.playerWillDestroy(pLevel, pPos, pState, pPlayer); - // For some reason the block doesn't play breaking noises. So we fix that! - pPlayer.playSound(SoundEvents.AMETHYST_BLOCK_BREAK, 1f, 1f); - } - - @Nullable - @Override - public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level pLevel, BlockState pState, - BlockEntityType<T> pBlockEntityType) { - if (pLevel.isClientSide()) { - return BlockConjured::tick; - } else { - return null; - } - } - - private static <T extends BlockEntity> void tick(Level level, BlockPos blockPos, BlockState blockState, T t) { - if (t instanceof BlockEntityConjured conjured) { - conjured.particleEffect(); - } - } - - @Override - public void stepOn(Level pLevel, @NotNull BlockPos pPos, @NotNull BlockState pState, @NotNull Entity pEntity) { - BlockEntity tile = pLevel.getBlockEntity(pPos); - if (tile instanceof BlockEntityConjured bec) { - bec.walkParticle(pEntity); - } - } - - @Nullable - @Override - public BlockEntity newBlockEntity(@NotNull BlockPos pPos, @NotNull BlockState pState) { - return new BlockEntityConjured(pPos, pState); - } - - public static void setColor(LevelAccessor pLevel, BlockPos pPos, FrozenPigment colorizer) { - BlockEntity blockentity = pLevel.getBlockEntity(pPos); - if (blockentity instanceof BlockEntityConjured tile) { - tile.setColorizer(colorizer); - } - } - - @Override - public void onPlace(@NotNull BlockState pState, Level pLevel, @NotNull BlockPos pPos, @NotNull BlockState pOldState, - boolean pIsMoving) { - pLevel.sendBlockUpdated(pPos, pState, pState, Block.UPDATE_CLIENTS); - super.onPlace(pState, pLevel, pPos, pOldState, pIsMoving); - } - - @Override - public boolean propagatesSkylightDown(@NotNull BlockState pState, @NotNull BlockGetter pLevel, - @NotNull BlockPos pPos) { - return true; - } - - @Override - public @NotNull VoxelShape getVisualShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, - CollisionContext pContext) { - return Shapes.empty(); - } - - @Override - public float getShadeBrightness(BlockState pState, BlockGetter pLevel, BlockPos pPos) { - return 1.0F; - } - - @Override - public @NotNull RenderShape getRenderShape(@NotNull BlockState state) { - return RenderShape.INVISIBLE; - } - - @Override - protected void spawnDestroyParticles(Level pLevel, Player pPlayer, BlockPos pPos, BlockState pState) { - // NO-OP - } - - - @SoftImplement("forge") - public boolean addLandingEffects(BlockState state1, ServerLevel worldserver, BlockPos pos, BlockState state2, - LivingEntity entity, int numberOfParticles) { - return addLandingEffects(state1, worldserver, pos, entity, numberOfParticles); - } - - @Override - public boolean addLandingEffects(BlockState state, ServerLevel worldserver, BlockPos pos, - LivingEntity entity, int numberOfParticles) { - BlockEntity tile = worldserver.getBlockEntity(pos); - if (tile instanceof BlockEntityConjured bec) { - bec.landParticle(entity, numberOfParticles); - } - return true; - } + public BlockConjured(Properties properties) { + super(properties); + } + + @Override + public void playerWillDestroy(Level pLevel, BlockPos pPos, BlockState pState, Player pPlayer) { + super.playerWillDestroy(pLevel, pPos, pState, pPlayer); + // For some reason the block doesn't play breaking noises. So we fix that! + pPlayer.playSound(SoundEvents.AMETHYST_BLOCK_BREAK, 1f, 1f); + } + + @Nullable @Override + public <T extends BlockEntity> BlockEntityTicker<T> getTicker( + Level pLevel, BlockState pState, BlockEntityType<T> pBlockEntityType) { + if (pLevel.isClientSide()) { + return BlockConjured::tick; + } else { + return null; + } + } + + private static <T extends BlockEntity> void tick( + Level level, BlockPos blockPos, BlockState blockState, T t) { + if (t instanceof BlockEntityConjured conjured) { + conjured.particleEffect(); + } + } + + @Override + public void stepOn( + Level pLevel, @NotNull BlockPos pPos, @NotNull BlockState pState, @NotNull Entity pEntity) { + BlockEntity tile = pLevel.getBlockEntity(pPos); + if (tile instanceof BlockEntityConjured bec) { + bec.walkParticle(pEntity); + } + } + + @Nullable @Override + public BlockEntity newBlockEntity(@NotNull BlockPos pPos, @NotNull BlockState pState) { + return new BlockEntityConjured(pPos, pState); + } + + public static void setColor(LevelAccessor pLevel, BlockPos pPos, FrozenPigment colorizer) { + BlockEntity blockentity = pLevel.getBlockEntity(pPos); + if (blockentity instanceof BlockEntityConjured tile) { + tile.setColorizer(colorizer); + } + } + + @Override + public void onPlace( + @NotNull BlockState pState, + Level pLevel, + @NotNull BlockPos pPos, + @NotNull BlockState pOldState, + boolean pIsMoving) { + pLevel.sendBlockUpdated(pPos, pState, pState, Block.UPDATE_CLIENTS); + super.onPlace(pState, pLevel, pPos, pOldState, pIsMoving); + } + + @Override + public boolean propagatesSkylightDown( + @NotNull BlockState pState, @NotNull BlockGetter pLevel, @NotNull BlockPos pPos) { + return true; + } + + @Override + public @NotNull VoxelShape getVisualShape( + BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + return Shapes.empty(); + } + + @Override + public float getShadeBrightness(BlockState pState, BlockGetter pLevel, BlockPos pPos) { + return 1.0F; + } + + @Override + public @NotNull RenderShape getRenderShape(@NotNull BlockState state) { + return RenderShape.INVISIBLE; + } + + @Override + protected void spawnDestroyParticles( + Level pLevel, Player pPlayer, BlockPos pPos, BlockState pState) { + // NO-OP + } + + @SoftImplement("forge") + public boolean addLandingEffects( + BlockState state1, + ServerLevel worldserver, + BlockPos pos, + BlockState state2, + LivingEntity entity, + int numberOfParticles) { + return addLandingEffects(state1, worldserver, pos, entity, numberOfParticles); + } + + @Override + public boolean addLandingEffects( + BlockState state, + ServerLevel worldserver, + BlockPos pos, + LivingEntity entity, + int numberOfParticles) { + BlockEntity tile = worldserver.getBlockEntity(pos); + if (tile instanceof BlockEntityConjured bec) { + bec.landParticle(entity, numberOfParticles); + } + return true; + } } - diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockConjuredLight.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockConjuredLight.java index cd59595474..88c60e20db 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockConjuredLight.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockConjuredLight.java @@ -1,5 +1,6 @@ package at.petrak.hexcasting.common.blocks; +import javax.annotation.Nonnull; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; @@ -19,72 +20,83 @@ import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.level.material.PushReaction; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.annotation.Nonnull; - public class BlockConjuredLight extends BlockConjured implements SimpleWaterloggedBlock { - public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; - private static final VoxelShape SHAPE = Block.box(5.0D, 5.0D, 5.0D, 11.0D, 11.0D, 11.0D); + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + private static final VoxelShape SHAPE = Block.box(5.0D, 5.0D, 5.0D, 11.0D, 11.0D, 11.0D); - public BlockConjuredLight(BlockBehaviour.Properties properties) { - super(properties); - this.registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false)); - } + public BlockConjuredLight(BlockBehaviour.Properties properties) { + super(properties); + this.registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false)); + } - @Override - protected void createBlockStateDefinition(@NotNull StateDefinition.Builder<Block, BlockState> builder) { - builder.add(WATERLOGGED); - } + @Override + protected void createBlockStateDefinition( + @NotNull StateDefinition.Builder<Block, BlockState> builder) { + builder.add(WATERLOGGED); + } - @Override - public boolean propagatesSkylightDown(BlockState state, @Nonnull BlockGetter reader, @Nonnull BlockPos pos) { - return !state.getValue(WATERLOGGED); - } + @Override + public boolean propagatesSkylightDown( + BlockState state, @Nonnull BlockGetter reader, @Nonnull BlockPos pos) { + return !state.getValue(WATERLOGGED); + } - @Nonnull - @Override - public FluidState getFluidState(BlockState state) { - return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); - } + @Nonnull + @Override + public FluidState getFluidState(BlockState state) { + return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } - @Nullable - @Override - public BlockState getStateForPlacement(BlockPlaceContext pContext) { - FluidState fluidState = pContext.getLevel().getFluidState(pContext.getClickedPos()); - return defaultBlockState().setValue(WATERLOGGED, fluidState.is(FluidTags.WATER) && fluidState.getAmount() == 8); - } + @Nullable @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + FluidState fluidState = pContext.getLevel().getFluidState(pContext.getClickedPos()); + return defaultBlockState() + .setValue(WATERLOGGED, fluidState.is(FluidTags.WATER) && fluidState.getAmount() == 8); + } - @Nonnull - @Override - public BlockState updateShape(BlockState state, @Nonnull Direction facing, @Nonnull BlockState facingState, - @Nonnull LevelAccessor level, @Nonnull BlockPos pos, @Nonnull BlockPos facingPos) { - if (state.getValue(WATERLOGGED)) { - level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); - } + @Nonnull + @Override + public BlockState updateShape( + BlockState state, + @Nonnull Direction facing, + @Nonnull BlockState facingState, + @Nonnull LevelAccessor level, + @Nonnull BlockPos pos, + @Nonnull BlockPos facingPos) { + if (state.getValue(WATERLOGGED)) { + level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } - return super.updateShape(state, facing, facingState, level, pos, facingPos); - } + return super.updateShape(state, facing, facingState, level, pos, facingPos); + } - @Override - public @NotNull VoxelShape getShape(@NotNull BlockState state, @NotNull BlockGetter level, @NotNull BlockPos pos, - @NotNull CollisionContext context) { - return SHAPE; - } + @Override + public @NotNull VoxelShape getShape( + @NotNull BlockState state, + @NotNull BlockGetter level, + @NotNull BlockPos pos, + @NotNull CollisionContext context) { + return SHAPE; + } - @Override - public void stepOn(Level pLevel, @NotNull BlockPos pPos, @NotNull BlockState pState, @NotNull Entity pEntity) { - // NO-OP - } + @Override + public void stepOn( + Level pLevel, @NotNull BlockPos pPos, @NotNull BlockState pState, @NotNull Entity pEntity) { + // NO-OP + } - @Override - public boolean addLandingEffects(BlockState state, ServerLevel worldserver, BlockPos pos, - LivingEntity entity, int numberOfParticles) { - return true; - } + @Override + public boolean addLandingEffects( + BlockState state, + ServerLevel worldserver, + BlockPos pos, + LivingEntity entity, + int numberOfParticles) { + return true; + } } - diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockFlammable.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockFlammable.java index 20c9573454..345002ea51 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockFlammable.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockFlammable.java @@ -7,30 +7,31 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; -/** - * Does absolutely nothing on Fabric; the flammable block registry is for that. - */ +/** Does absolutely nothing on Fabric; the flammable block registry is for that. */ public class BlockFlammable extends Block { - public final int burn, spread; + public final int burn, spread; - public BlockFlammable(Properties $$0, int burn, int spread) { - super($$0); - this.burn = burn; - this.spread = spread; - } + public BlockFlammable(Properties $$0, int burn, int spread) { + super($$0); + this.burn = burn; + this.spread = spread; + } - @SoftImplement("forge") - public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return true; - } + @SoftImplement("forge") + public boolean isFlammable( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return true; + } - @SoftImplement("forge") - public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return burn; - } + @SoftImplement("forge") + public int getFlammability( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return burn; + } - @SoftImplement("forge") - public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return spread; - } + @SoftImplement("forge") + public int getFireSpreadSpeed( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return spread; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockQuenchedAllay.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockQuenchedAllay.java index bdf889fb90..4941ce636f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockQuenchedAllay.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/BlockQuenchedAllay.java @@ -17,43 +17,42 @@ import org.jetbrains.annotations.Nullable; public class BlockQuenchedAllay extends Block implements EntityBlock { - public static final int VARIANTS = 4; + public static final int VARIANTS = 4; - public BlockQuenchedAllay(Properties properties) { - super(properties); - } + public BlockQuenchedAllay(Properties properties) { + super(properties); + } - @Nullable - @Override - public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { - return new BlockEntityQuenchedAllay(this, pos, state); - } + @Nullable @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new BlockEntityQuenchedAllay(this, pos, state); + } - @Override - public RenderShape getRenderShape(BlockState state) { - return RenderShape.INVISIBLE; - } + @Override + public RenderShape getRenderShape(BlockState state) { + return RenderShape.INVISIBLE; + } - @Override - public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource rand) { - ParticleOptions options = new ConjureParticleOptions(0x8932b8); - Vec3 center = Vec3.atCenterOf(pos); - for (Direction direction : Direction.values()) { - int dX = direction.getStepX(); - int dY = direction.getStepY(); - int dZ = direction.getStepZ(); + @Override + public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource rand) { + ParticleOptions options = new ConjureParticleOptions(0x8932b8); + Vec3 center = Vec3.atCenterOf(pos); + for (Direction direction : Direction.values()) { + int dX = direction.getStepX(); + int dY = direction.getStepY(); + int dZ = direction.getStepZ(); - int count = rand.nextInt(10) / 4; - for (int i = 0; i < count; i++) { - double pX = center.x + (dX == 0 ? Mth.nextDouble(rand, -0.5D, 0.5D) : (double) dX * 0.55D); - double pY = center.y + (dY == 0 ? Mth.nextDouble(rand, -0.5D, 0.5D) : (double) dY * 0.55D); - double pZ = center.z + (dZ == 0 ? Mth.nextDouble(rand, -0.5D, 0.5D) : (double) dZ * 0.55D); - double vPerp = Mth.nextDouble(rand, 0.0, 0.01); - double vX = vPerp * dX; - double vY = vPerp * dY; - double vZ = vPerp * dZ; - level.addParticle(options, pX, pY, pZ, vX, vY, vZ); - } - } - } + int count = rand.nextInt(10) / 4; + for (int i = 0; i < count; i++) { + double pX = center.x + (dX == 0 ? Mth.nextDouble(rand, -0.5D, 0.5D) : (double) dX * 0.55D); + double pY = center.y + (dY == 0 ? Mth.nextDouble(rand, -0.5D, 0.5D) : (double) dY * 0.55D); + double pZ = center.z + (dZ == 0 ? Mth.nextDouble(rand, -0.5D, 0.5D) : (double) dZ * 0.55D); + double vPerp = Mth.nextDouble(rand, 0.0, 0.01); + double vX = vPerp * dX; + double vY = vPerp * dY; + double vZ = vPerp * dZ; + level.addParticle(options, pX, pY, pZ, vX, vY, vZ); + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/AkashicFloodfiller.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/AkashicFloodfiller.java index ab810391af..10fb6f2d5e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/AkashicFloodfiller.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/AkashicFloodfiller.java @@ -1,71 +1,72 @@ package at.petrak.hexcasting.common.blocks.akashic; import at.petrak.hexcasting.api.misc.TriPredicate; +import java.util.ArrayDeque; +import java.util.HashSet; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.Nullable; -import java.util.ArrayDeque; -import java.util.HashSet; - public interface AkashicFloodfiller { - default boolean canBeFloodedThrough(BlockPos pos, BlockState state, Level world) { - return true; - } + default boolean canBeFloodedThrough(BlockPos pos, BlockState state, Level world) { + return true; + } - @Nullable - static BlockPos floodFillFor(BlockPos start, Level world, TriPredicate<BlockPos, BlockState, Level> isTarget) { - return floodFillFor(start, world, 0f, isTarget, 128); - } + @Nullable static BlockPos floodFillFor( + BlockPos start, Level world, TriPredicate<BlockPos, BlockState, Level> isTarget) { + return floodFillFor(start, world, 0f, isTarget, 128); + } - @Nullable - static BlockPos floodFillFor(BlockPos start, Level world, float skipChance, - TriPredicate<BlockPos, BlockState, Level> isTarget, int maxRange) { - var seenBlocks = new HashSet<BlockPos>(); - var todo = new ArrayDeque<BlockPos>(); - todo.add(start); - var skippedBlocks = new HashSet<BlockPos>(); + @Nullable static BlockPos floodFillFor( + BlockPos start, + Level world, + float skipChance, + TriPredicate<BlockPos, BlockState, Level> isTarget, + int maxRange) { + var seenBlocks = new HashSet<BlockPos>(); + var todo = new ArrayDeque<BlockPos>(); + todo.add(start); + var skippedBlocks = new HashSet<BlockPos>(); - while (!todo.isEmpty()) { - var here = todo.remove(); + while (!todo.isEmpty()) { + var here = todo.remove(); - for (var dir : Direction.values()) { - var neighbor = here.relative(dir); + for (var dir : Direction.values()) { + var neighbor = here.relative(dir); - if (neighbor.distSqr(start) > maxRange * maxRange) - continue; + if (neighbor.distSqr(start) > maxRange * maxRange) continue; - if (seenBlocks.add(neighbor)) { - var bs = world.getBlockState(neighbor); - if (isTarget.test(neighbor, bs, world)) { - if (world.random.nextFloat() > skipChance) { - return neighbor; - } else { - skippedBlocks.add(neighbor); - } - } - if (canItBeFloodedThrough(neighbor, bs, world)) { - todo.add(neighbor); - } - } - } - } + if (seenBlocks.add(neighbor)) { + var bs = world.getBlockState(neighbor); + if (isTarget.test(neighbor, bs, world)) { + if (world.random.nextFloat() > skipChance) { + return neighbor; + } else { + skippedBlocks.add(neighbor); + } + } + if (canItBeFloodedThrough(neighbor, bs, world)) { + todo.add(neighbor); + } + } + } + } - if (!skippedBlocks.isEmpty()) { - // We found something valid, we just skipped past it - return skippedBlocks.iterator().next(); - } + if (!skippedBlocks.isEmpty()) { + // We found something valid, we just skipped past it + return skippedBlocks.iterator().next(); + } - return null; - } + return null; + } - static boolean canItBeFloodedThrough(BlockPos pos, BlockState state, Level world) { - if (!(state.getBlock() instanceof AkashicFloodfiller flooder)) { - return false; - } + static boolean canItBeFloodedThrough(BlockPos pos, BlockState state, Level world) { + if (!(state.getBlock() instanceof AkashicFloodfiller flooder)) { + return false; + } - return flooder.canBeFloodedThrough(pos, state, world); - } + return flooder.canBeFloodedThrough(pos, state, world); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicBookshelf.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicBookshelf.java index 39545fd968..51612c1750 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicBookshelf.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicBookshelf.java @@ -27,83 +27,89 @@ import net.minecraft.world.phys.BlockHitResult; import org.jetbrains.annotations.Nullable; -public class BlockAkashicBookshelf extends Block implements AkashicFloodfiller, EntityBlock, IForgeLikeBlock { - public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; - public static final BooleanProperty HAS_BOOKS = BooleanProperty.create("has_books"); +public class BlockAkashicBookshelf extends Block + implements AkashicFloodfiller, EntityBlock, IForgeLikeBlock { + public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; + public static final BooleanProperty HAS_BOOKS = BooleanProperty.create("has_books"); - public BlockAkashicBookshelf(Properties p_49795_) { - super(p_49795_); - this.registerDefaultState(this.getStateDefinition().any() - .setValue(FACING, Direction.NORTH) - .setValue(HAS_BOOKS, false)); - } + public BlockAkashicBookshelf(Properties p_49795_) { + super(p_49795_); + this.registerDefaultState( + this.getStateDefinition() + .any() + .setValue(FACING, Direction.NORTH) + .setValue(HAS_BOOKS, false)); + } - @Override - public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, - BlockHitResult pHit) { - if (pLevel.getBlockEntity(pPos) instanceof BlockEntityAkashicBookshelf shelf) { - var stack = pPlayer.getItemInHand(pHand); - if (stack.getItem() instanceof ItemScroll scroll) { - if (!pLevel.isClientSide()) { - scroll.writeDatum(stack, new PatternIota(shelf.getPattern())); - } - pLevel.playSound(pPlayer, pPos, HexSounds.SCROLL_SCRIBBLE, SoundSource.BLOCKS, 1f, 1f); - return InteractionResult.sidedSuccess(pLevel.isClientSide); - } else if (pPlayer.isDiscrete() && pHand == InteractionHand.MAIN_HAND && stack.isEmpty()) { - if (!pLevel.isClientSide()) { - shelf.clearIota(); - } + @Override + public InteractionResult use( + BlockState pState, + Level pLevel, + BlockPos pPos, + Player pPlayer, + InteractionHand pHand, + BlockHitResult pHit) { + if (pLevel.getBlockEntity(pPos) instanceof BlockEntityAkashicBookshelf shelf) { + var stack = pPlayer.getItemInHand(pHand); + if (stack.getItem() instanceof ItemScroll scroll) { + if (!pLevel.isClientSide()) { + scroll.writeDatum(stack, new PatternIota(shelf.getPattern())); + } + pLevel.playSound(pPlayer, pPos, HexSounds.SCROLL_SCRIBBLE, SoundSource.BLOCKS, 1f, 1f); + return InteractionResult.sidedSuccess(pLevel.isClientSide); + } else if (pPlayer.isDiscrete() && pHand == InteractionHand.MAIN_HAND && stack.isEmpty()) { + if (!pLevel.isClientSide()) { + shelf.clearIota(); + } - pLevel.playSound(pPlayer, pPos, HexSounds.SCROLL_SCRIBBLE, SoundSource.BLOCKS, - 1f, 0.8f); - return InteractionResult.sidedSuccess(pLevel.isClientSide); - } - } + pLevel.playSound(pPlayer, pPos, HexSounds.SCROLL_SCRIBBLE, SoundSource.BLOCKS, 1f, 0.8f); + return InteractionResult.sidedSuccess(pLevel.isClientSide); + } + } - return InteractionResult.PASS; - } + return InteractionResult.PASS; + } - @Override - protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { - builder.add(FACING, HAS_BOOKS); - } + @Override + protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { + builder.add(FACING, HAS_BOOKS); + } - @Override - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - return this.defaultBlockState().setValue(FACING, ctx.getHorizontalDirection().getOpposite()); - } + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + return this.defaultBlockState().setValue(FACING, ctx.getHorizontalDirection().getOpposite()); + } - @SoftImplement("forge") - public float getEnchantPowerBonus(BlockState state, LevelReader level, BlockPos pos) { - return hasEnchantPowerBonus(state, level, pos) ? 1 : 0; - } + @SoftImplement("forge") + public float getEnchantPowerBonus(BlockState state, LevelReader level, BlockPos pos) { + return hasEnchantPowerBonus(state, level, pos) ? 1 : 0; + } - @Override - public boolean hasEnchantPowerBonus(BlockState state, LevelReader level, BlockPos pos) { - return true; - } + @Override + public boolean hasEnchantPowerBonus(BlockState state, LevelReader level, BlockPos pos) { + return true; + } - @Override - public boolean hasAnalogOutputSignal(BlockState pState) { - return true; - } + @Override + public boolean hasAnalogOutputSignal(BlockState pState) { + return true; + } - @Override - public int getAnalogOutputSignal(BlockState pState, Level pLevel, BlockPos pPos) { - return pState.getValue(HAS_BOOKS) ? 15 : 0; // TODO have an iota -> comparator value mapping? - } + @Override + public int getAnalogOutputSignal(BlockState pState, Level pLevel, BlockPos pPos) { + return pState.getValue(HAS_BOOKS) ? 15 : 0; // TODO have an iota -> comparator value mapping? + } - @Nullable - @Override - public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { - return new BlockEntityAkashicBookshelf(pPos, pState); - } + @Nullable @Override + public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { + return new BlockEntityAkashicBookshelf(pPos, pState); + } - public BlockState rotate(BlockState pState, Rotation pRot) { - return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING))); - } + public BlockState rotate(BlockState pState, Rotation pRot) { + return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING))); + } - public BlockState mirror(BlockState pState, Mirror pMirror) { - return pState.rotate(pMirror.getRotation(pState.getValue(FACING))); - } + public BlockState mirror(BlockState pState, Mirror pMirror) { + return pState.rotate(pMirror.getRotation(pState.getValue(FACING))); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicLigature.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicLigature.java index c86019bd10..efa49db9bc 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicLigature.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicLigature.java @@ -3,7 +3,7 @@ import net.minecraft.world.level.block.Block; public class BlockAkashicLigature extends Block implements AkashicFloodfiller { - public BlockAkashicLigature(Properties properties) { - super(properties); - } + public BlockAkashicLigature(Properties properties) { + super(properties); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicRecord.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicRecord.java index db3f96ac14..905e620952 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicRecord.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicRecord.java @@ -10,55 +10,64 @@ import org.jetbrains.annotations.Nullable; public class BlockAkashicRecord extends Block { - public BlockAkashicRecord(Properties p_49795_) { - super(p_49795_); - } + public BlockAkashicRecord(Properties p_49795_) { + super(p_49795_); + } + /** + * @return the block position of the place it gets stored, or null if there was no room. + * <p>Will never clobber anything. + */ + public @Nullable BlockPos addNewDatum(BlockPos herePos, Level level, HexPattern key, Iota datum) { + var clobbereePos = + AkashicFloodfiller.floodFillFor( + herePos, + level, + (pos, bs, world) -> + world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile + && tile.getPattern() != null + && tile.getPattern().sigsEqual(key)); - /** - * @return the block position of the place it gets stored, or null if there was no room. - * <p> - * Will never clobber anything. - */ - public @Nullable - BlockPos addNewDatum(BlockPos herePos, Level level, HexPattern key, Iota datum) { - var clobbereePos = AkashicFloodfiller.floodFillFor(herePos, level, - (pos, bs, world) -> - world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile - && tile.getPattern() != null && tile.getPattern().sigsEqual(key)); + if (clobbereePos != null) { + return null; + } - if (clobbereePos != null) { - return null; - } + var openPos = + AkashicFloodfiller.floodFillFor( + herePos, + level, + 0.9f, + (pos, bs, world) -> + world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile + && tile.getPattern() == null, + 128); + if (openPos != null) { + var tile = (BlockEntityAkashicBookshelf) level.getBlockEntity(openPos); + tile.setNewMapping(key, datum); - var openPos = AkashicFloodfiller.floodFillFor(herePos, level, 0.9f, - (pos, bs, world) -> - world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile - && tile.getPattern() == null, 128); - if (openPos != null) { - var tile = (BlockEntityAkashicBookshelf) level.getBlockEntity(openPos); - tile.setNewMapping(key, datum); + return openPos; + } else { + return null; + } + } - return openPos; - } else { - return null; - } - } + public @Nullable Iota lookupPattern(BlockPos herePos, HexPattern key, ServerLevel slevel) { + var foundPos = + AkashicFloodfiller.floodFillFor( + herePos, + slevel, + (pos, bs, world) -> + world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile + && tile.getPattern() != null + && tile.getPattern().sigsEqual(key)); + if (foundPos == null) { + return null; + } - public @Nullable - Iota lookupPattern(BlockPos herePos, HexPattern key, ServerLevel slevel) { - var foundPos = AkashicFloodfiller.floodFillFor(herePos, slevel, - (pos, bs, world) -> - world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile - && tile.getPattern() != null && tile.getPattern().sigsEqual(key)); - if (foundPos == null) { - return null; - } + var tile = (BlockEntityAkashicBookshelf) slevel.getBlockEntity(foundPos); + var tag = tile.getIotaTag(); + return tag == null ? null : IotaType.deserialize(tag, slevel); + } - var tile = (BlockEntityAkashicBookshelf) slevel.getBlockEntity(foundPos); - var tag = tile.getIotaTag(); - return tag == null ? null : IotaType.deserialize(tag, slevel); - } - - // TODO get comparators working again and also cache the number of iotas somehow? + // TODO get comparators working again and also cache the number of iotas somehow? } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockEntityAkashicBookshelf.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockEntityAkashicBookshelf.java index d6e4cd8041..0f9b9e96c2 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockEntityAkashicBookshelf.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockEntityAkashicBookshelf.java @@ -12,81 +12,80 @@ import org.jetbrains.annotations.Nullable; public class BlockEntityAkashicBookshelf extends HexBlockEntity { - public static final String TAG_PATTERN = "pattern"; - public static final String TAG_IOTA = "iota"; - public static final String TAG_DUMMY = "dummy"; + public static final String TAG_PATTERN = "pattern"; + public static final String TAG_IOTA = "iota"; + public static final String TAG_DUMMY = "dummy"; - // This is only not null if this stores any data. - private HexPattern pattern = null; - // When the world is first loading we can sometimes try to deser this from nbt without the world existing yet. - // We also need a way to display the iota to the client. - // For both these cases we save just the tag of the iota. - private CompoundTag iotaTag = null; + // This is only not null if this stores any data. + private HexPattern pattern = null; + // When the world is first loading we can sometimes try to deser this from nbt without the world + // existing yet. + // We also need a way to display the iota to the client. + // For both these cases we save just the tag of the iota. + private CompoundTag iotaTag = null; - public HexPatternPoints points; + public HexPatternPoints points; - public BlockEntityAkashicBookshelf(BlockPos pWorldPosition, BlockState pBlockState) { - super(HexBlockEntities.AKASHIC_BOOKSHELF_TILE, pWorldPosition, pBlockState); - } + public BlockEntityAkashicBookshelf(BlockPos pWorldPosition, BlockState pBlockState) { + super(HexBlockEntities.AKASHIC_BOOKSHELF_TILE, pWorldPosition, pBlockState); + } - @Nullable - public HexPattern getPattern() { - return pattern; - } + @Nullable public HexPattern getPattern() { + return pattern; + } - @Nullable - public CompoundTag getIotaTag() { - return iotaTag; - } + @Nullable public CompoundTag getIotaTag() { + return iotaTag; + } - public void setNewMapping(HexPattern pattern, Iota iota) { - var previouslyEmpty = this.pattern == null; - this.pattern = pattern; - this.iotaTag = IotaType.serialize(iota); + public void setNewMapping(HexPattern pattern, Iota iota) { + var previouslyEmpty = this.pattern == null; + this.pattern = pattern; + this.iotaTag = IotaType.serialize(iota); - if (previouslyEmpty) { - var oldBs = this.getBlockState(); - var newBs = oldBs.setValue(BlockAkashicBookshelf.HAS_BOOKS, true); - this.level.setBlock(this.getBlockPos(), newBs, 3); - this.level.sendBlockUpdated(this.getBlockPos(), oldBs, newBs, 3); - } else { - this.setChanged(); - } - } + if (previouslyEmpty) { + var oldBs = this.getBlockState(); + var newBs = oldBs.setValue(BlockAkashicBookshelf.HAS_BOOKS, true); + this.level.setBlock(this.getBlockPos(), newBs, 3); + this.level.sendBlockUpdated(this.getBlockPos(), oldBs, newBs, 3); + } else { + this.setChanged(); + } + } - public void clearIota() { - var previouslyEmpty = this.pattern == null; - this.pattern = null; - this.iotaTag = null; + public void clearIota() { + var previouslyEmpty = this.pattern == null; + this.pattern = null; + this.iotaTag = null; - if (!previouslyEmpty) { - var oldBs = this.getBlockState(); - var newBs = oldBs.setValue(BlockAkashicBookshelf.HAS_BOOKS, false); - this.level.setBlock(this.getBlockPos(), newBs, 3); - this.level.sendBlockUpdated(this.getBlockPos(), oldBs, newBs, 3); - } else { - this.setChanged(); - } - } + if (!previouslyEmpty) { + var oldBs = this.getBlockState(); + var newBs = oldBs.setValue(BlockAkashicBookshelf.HAS_BOOKS, false); + this.level.setBlock(this.getBlockPos(), newBs, 3); + this.level.sendBlockUpdated(this.getBlockPos(), oldBs, newBs, 3); + } else { + this.setChanged(); + } + } - @Override - protected void saveModData(CompoundTag compoundTag) { - if (this.pattern != null && this.iotaTag != null) { - compoundTag.put(TAG_PATTERN, this.pattern.serializeToNBT()); - compoundTag.put(TAG_IOTA, this.iotaTag); - } else { - compoundTag.putBoolean(TAG_DUMMY, false); - } - } + @Override + protected void saveModData(CompoundTag compoundTag) { + if (this.pattern != null && this.iotaTag != null) { + compoundTag.put(TAG_PATTERN, this.pattern.serializeToNBT()); + compoundTag.put(TAG_IOTA, this.iotaTag); + } else { + compoundTag.putBoolean(TAG_DUMMY, false); + } + } - @Override - protected void loadModData(CompoundTag tag) { - if (tag.contains(TAG_PATTERN) && tag.contains(TAG_IOTA)) { - this.pattern = HexPattern.fromNBT(tag.getCompound(TAG_PATTERN)); - this.iotaTag = tag.getCompound(TAG_IOTA); - } else if (tag.contains(TAG_DUMMY)) { - this.pattern = null; - this.iotaTag = null; - } - } + @Override + protected void loadModData(CompoundTag tag) { + if (tag.contains(TAG_PATTERN) && tag.contains(TAG_IOTA)) { + this.pattern = HexPattern.fromNBT(tag.getCompound(TAG_PATTERN)); + this.iotaTag = tag.getCompound(TAG_IOTA); + } else if (tag.contains(TAG_DUMMY)) { + this.pattern = null; + this.iotaTag = null; + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/behavior/HexComposting.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/behavior/HexComposting.java index f072ea51cb..2398d90fff 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/behavior/HexComposting.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/behavior/HexComposting.java @@ -8,17 +8,17 @@ public final class HexComposting { - public static void setup() { - compost(HexBlocks.AMETHYST_EDIFIED_LEAVES, 0.3F); - compost(HexBlocks.AVENTURINE_EDIFIED_LEAVES, 0.3F); - compost(HexBlocks.CITRINE_EDIFIED_LEAVES, 0.3F); - } + public static void setup() { + compost(HexBlocks.AMETHYST_EDIFIED_LEAVES, 0.3F); + compost(HexBlocks.AVENTURINE_EDIFIED_LEAVES, 0.3F); + compost(HexBlocks.CITRINE_EDIFIED_LEAVES, 0.3F); + } - private static void compost(ItemLike itemLike, float chance) { - Item item = itemLike.asItem(); + private static void compost(ItemLike itemLike, float chance) { + Item item = itemLike.asItem(); - if (item != Items.AIR) { - ComposterBlock.COMPOSTABLES.put(item, chance); - } - } + if (item != Items.AIR) { + ComposterBlock.COMPOSTABLES.put(item, chance); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/behavior/HexStrippables.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/behavior/HexStrippables.java index d36254090d..ff456697ab 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/behavior/HexStrippables.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/behavior/HexStrippables.java @@ -1,20 +1,19 @@ package at.petrak.hexcasting.common.blocks.behavior; import at.petrak.hexcasting.common.lib.HexBlocks; -import net.minecraft.world.level.block.Block; - import java.util.HashMap; import java.util.Map; +import net.minecraft.world.level.block.Block; public class HexStrippables { - public static final Map<Block, Block> STRIPPABLES = new HashMap<>(); + public static final Map<Block, Block> STRIPPABLES = new HashMap<>(); - public static void init() { - STRIPPABLES.put(HexBlocks.EDIFIED_LOG, HexBlocks.STRIPPED_EDIFIED_LOG); - STRIPPABLES.put(HexBlocks.EDIFIED_LOG_AMETHYST, HexBlocks.STRIPPED_EDIFIED_LOG); - STRIPPABLES.put(HexBlocks.EDIFIED_LOG_AVENTURINE, HexBlocks.STRIPPED_EDIFIED_LOG); - STRIPPABLES.put(HexBlocks.EDIFIED_LOG_CITRINE, HexBlocks.STRIPPED_EDIFIED_LOG); - STRIPPABLES.put(HexBlocks.EDIFIED_LOG_PURPLE, HexBlocks.STRIPPED_EDIFIED_LOG); - STRIPPABLES.put(HexBlocks.EDIFIED_WOOD, HexBlocks.STRIPPED_EDIFIED_WOOD); - } + public static void init() { + STRIPPABLES.put(HexBlocks.EDIFIED_LOG, HexBlocks.STRIPPED_EDIFIED_LOG); + STRIPPABLES.put(HexBlocks.EDIFIED_LOG_AMETHYST, HexBlocks.STRIPPED_EDIFIED_LOG); + STRIPPABLES.put(HexBlocks.EDIFIED_LOG_AVENTURINE, HexBlocks.STRIPPED_EDIFIED_LOG); + STRIPPABLES.put(HexBlocks.EDIFIED_LOG_CITRINE, HexBlocks.STRIPPED_EDIFIED_LOG); + STRIPPABLES.put(HexBlocks.EDIFIED_LOG_PURPLE, HexBlocks.STRIPPED_EDIFIED_LOG); + STRIPPABLES.put(HexBlocks.EDIFIED_WOOD, HexBlocks.STRIPPED_EDIFIED_WOOD); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEmptyImpetus.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEmptyImpetus.java index 2cac9c79f1..a63a62aeef 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEmptyImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEmptyImpetus.java @@ -3,6 +3,8 @@ import at.petrak.hexcasting.api.block.circle.BlockCircleComponent; import at.petrak.hexcasting.api.casting.eval.env.CircleCastEnv; import at.petrak.hexcasting.api.casting.eval.vm.CastingImage; +import java.util.EnumSet; +import java.util.List; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; @@ -15,65 +17,68 @@ 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.DirectionProperty; -import net.minecraft.world.level.material.PushReaction; - -import java.util.EnumSet; -import java.util.List; // As it turns out, not actually an impetus public class BlockEmptyImpetus extends BlockCircleComponent { - public static final DirectionProperty FACING = BlockStateProperties.FACING; + public static final DirectionProperty FACING = BlockStateProperties.FACING; - public BlockEmptyImpetus(Properties p_49795_) { - super(p_49795_); - this.registerDefaultState(this.stateDefinition.any() - .setValue(ENERGIZED, false).setValue(FACING, Direction.NORTH)); - } + public BlockEmptyImpetus(Properties p_49795_) { + super(p_49795_); + this.registerDefaultState( + this.stateDefinition.any().setValue(ENERGIZED, false).setValue(FACING, Direction.NORTH)); + } - @Override - public ControlFlow acceptControlFlow(CastingImage imageIn, CircleCastEnv env, Direction enterDir, BlockPos pos, - BlockState bs, ServerLevel world) { - return new ControlFlow.Continue(imageIn, List.of(this.exitPositionFromDirection(pos, bs.getValue(FACING)))); - } + @Override + public ControlFlow acceptControlFlow( + CastingImage imageIn, + CircleCastEnv env, + Direction enterDir, + BlockPos pos, + BlockState bs, + ServerLevel world) { + return new ControlFlow.Continue( + imageIn, List.of(this.exitPositionFromDirection(pos, bs.getValue(FACING)))); + } - @Override - public boolean canEnterFromDirection(Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world) { - return enterDir != bs.getValue(FACING).getOpposite(); - } + @Override + public boolean canEnterFromDirection( + Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world) { + return enterDir != bs.getValue(FACING).getOpposite(); + } - @Override - public EnumSet<Direction> possibleExitDirections(BlockPos pos, BlockState bs, Level world) { - return EnumSet.of(bs.getValue(FACING)); - } + @Override + public EnumSet<Direction> possibleExitDirections(BlockPos pos, BlockState bs, Level world) { + return EnumSet.of(bs.getValue(FACING)); + } - @Override - public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) { - return normalDirOfOther(pos.relative(bs.getValue(FACING)), world, recursionLeft); - } + @Override + public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) { + return normalDirOfOther(pos.relative(bs.getValue(FACING)), world, recursionLeft); + } - @Override - public float particleHeight(BlockPos pos, BlockState bs, Level world) { - return 0.5f; - } + @Override + public float particleHeight(BlockPos pos, BlockState bs, Level world) { + return 0.5f; + } - @Override - protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { - super.createBlockStateDefinition(builder); - builder.add(FACING); - } + @Override + protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { + super.createBlockStateDefinition(builder); + builder.add(FACING); + } - @Override - public BlockState getStateForPlacement(BlockPlaceContext pContext) { - return BlockCircleComponent.placeStateDirAndSneak(this.defaultBlockState(), pContext); - } + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + return BlockCircleComponent.placeStateDirAndSneak(this.defaultBlockState(), pContext); + } - @Override - public BlockState rotate(BlockState pState, Rotation pRot) { - return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING))); - } + @Override + public BlockState rotate(BlockState pState, Rotation pRot) { + return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING))); + } - @Override - public BlockState mirror(BlockState pState, Mirror pMirror) { - return pState.rotate(pMirror.getRotation(pState.getValue(FACING))); - } + @Override + public BlockState mirror(BlockState pState, Mirror pMirror) { + return pState.rotate(pMirror.getRotation(pState.getValue(FACING))); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEntitySlate.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEntitySlate.java index 9a0ec965bc..bcc94ba3a2 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEntitySlate.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEntitySlate.java @@ -10,36 +10,34 @@ import org.jetbrains.annotations.Nullable; public class BlockEntitySlate extends HexBlockEntity { - public static final String TAG_PATTERN = "pattern"; + public static final String TAG_PATTERN = "pattern"; - @Nullable - public HexPattern pattern; + @Nullable public HexPattern pattern; - public BlockEntitySlate(BlockPos pos, BlockState state) { - super(HexBlockEntities.SLATE_TILE, pos, state); - } + public BlockEntitySlate(BlockPos pos, BlockState state) { + super(HexBlockEntities.SLATE_TILE, pos, state); + } - @Override - protected void saveModData(CompoundTag tag) { - if (this.pattern != null) { - tag.put(TAG_PATTERN, this.pattern.serializeToNBT()); - } else { - tag.put(TAG_PATTERN, new CompoundTag()); - } - } - - @Override - protected void loadModData(CompoundTag tag) { - if (tag.contains(TAG_PATTERN, Tag.TAG_COMPOUND)) { - CompoundTag patternTag = tag.getCompound(TAG_PATTERN); - if (HexPattern.isPattern(patternTag)) { - this.pattern = HexPattern.fromNBT(patternTag); - } else { - this.pattern = null; - } - } else { - this.pattern = null; - } - } + @Override + protected void saveModData(CompoundTag tag) { + if (this.pattern != null) { + tag.put(TAG_PATTERN, this.pattern.serializeToNBT()); + } else { + tag.put(TAG_PATTERN, new CompoundTag()); + } + } + @Override + protected void loadModData(CompoundTag tag) { + if (tag.contains(TAG_PATTERN, Tag.TAG_COMPOUND)) { + CompoundTag patternTag = tag.getCompound(TAG_PATTERN); + if (HexPattern.isPattern(patternTag)) { + this.pattern = HexPattern.fromNBT(patternTag); + } else { + this.pattern = null; + } + } else { + this.pattern = null; + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockSlate.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockSlate.java index a982c4c1e8..fefe8e2ab9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockSlate.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockSlate.java @@ -8,6 +8,8 @@ import at.petrak.hexcasting.api.casting.iota.PatternIota; import at.petrak.hexcasting.api.casting.math.HexPattern; import at.petrak.hexcasting.common.lib.HexItems; +import java.util.EnumSet; +import javax.annotation.Nonnull; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; @@ -21,223 +23,238 @@ import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.SimpleWaterloggedBlock; import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.SimpleWaterloggedBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.*; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.level.material.PushReaction; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; import org.jetbrains.annotations.Nullable; -import javax.annotation.Nonnull; -import java.util.EnumSet; - // When on the floor or ceiling FACING is the direction the *bottom* of the pattern points // (or which way is "down"). // When on the wall FACING is the direction of the *front* of the block -public class BlockSlate extends BlockCircleComponent implements EntityBlock, SimpleWaterloggedBlock { - public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; - public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; - public static final EnumProperty<AttachFace> ATTACH_FACE = BlockStateProperties.ATTACH_FACE; - - public static final double THICKNESS = 1; - public static final VoxelShape AABB_FLOOR = Block.box(0, 0, 0, 16, THICKNESS, 16); - public static final VoxelShape AABB_CEILING = Block.box(0, 16 - THICKNESS, 0, 16, 16, 16); - public static final VoxelShape AABB_EAST_WALL = Block.box(0, 0, 0, THICKNESS, 16, 16); - public static final VoxelShape AABB_WEST_WALL = Block.box(16 - THICKNESS, 0, 0, 16, 16, 16); - public static final VoxelShape AABB_SOUTH_WALL = Block.box(0, 0, 0, 16, 16, THICKNESS); - public static final VoxelShape AABB_NORTH_WALL = Block.box(0, 0, 16 - THICKNESS, 16, 16, 16); - - public BlockSlate(Properties p_53182_) { - super(p_53182_); - this.registerDefaultState( - this.stateDefinition.any() - .setValue(ENERGIZED, false) - .setValue(FACING, Direction.NORTH) - .setValue(WATERLOGGED, false)); - } - - @Override - public boolean propagatesSkylightDown(BlockState state, @Nonnull BlockGetter reader, @Nonnull BlockPos pos) { - return !state.getValue(WATERLOGGED); - } - - @Nonnull - @Override - public FluidState getFluidState(BlockState state) { - return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); - } - - @Override - public ControlFlow acceptControlFlow(CastingImage imageIn, CircleCastEnv env, Direction enterDir, BlockPos pos, - BlockState bs, ServerLevel world) { - HexPattern pattern; - if (world.getBlockEntity(pos) instanceof BlockEntitySlate tile) { - pattern = tile.pattern; - } else { - return new ControlFlow.Stop(); - } - - var exitDirsSet = this.possibleExitDirections(pos, bs, world); - exitDirsSet.remove(enterDir.getOpposite()); - - var exitDirs = exitDirsSet.stream().map((dir) -> this.exitPositionFromDirection(pos, dir)); - - if (pattern == null) - return new ControlFlow.Continue(imageIn, exitDirs.toList()); - - var vm = new CastingVM(imageIn, env); - - var result = vm.queueExecuteAndWrapIota(new PatternIota(pattern), world); - if (result.getResolutionType().getSuccess()) { - return new ControlFlow.Continue(vm.getImage(), exitDirs.toList()); - } else { - return new ControlFlow.Stop(); - } - } - - @Override - public boolean canEnterFromDirection(Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world) { - var thisNormal = this.normalDir(pos, bs, world); - return enterDir != thisNormal.getOpposite(); // && enterDir != thisNormal; - } - - @Override - public EnumSet<Direction> possibleExitDirections(BlockPos pos, BlockState bs, Level world) { - var allDirs = EnumSet.allOf(Direction.class); - var normal = this.normalDir(pos, bs, world); - allDirs.remove(normal); -// allDirs.remove(normal.getOpposite()); - return allDirs; - } - - @SoftImplement("forge") - public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter level, BlockPos pos, - Player player) { - BlockEntity be = level.getBlockEntity(pos); - if (be instanceof BlockEntitySlate slate) { - ItemStack stack = new ItemStack(HexItems.SLATE); - if (slate.pattern != null) { - HexItems.SLATE.writeDatum(stack, new PatternIota(slate.pattern)); - } - return stack; - } - - return new ItemStack(this); - } - - @Override - public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) { - return switch (bs.getValue(ATTACH_FACE)) { - case FLOOR -> Direction.UP; - case CEILING -> Direction.DOWN; - case WALL -> bs.getValue(FACING); - }; - } - - @Override - public float particleHeight(BlockPos pos, BlockState bs, Level world) { - return 0.5f - 15f / 16f; - } - - @Nullable - @Override - public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { - return new BlockEntitySlate(pPos, pState); - } - - @Override - public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { - return switch (pState.getValue(ATTACH_FACE)) { - case FLOOR -> AABB_FLOOR; - case CEILING -> AABB_CEILING; - case WALL -> switch (pState.getValue(FACING)) { - case NORTH -> AABB_NORTH_WALL; - case EAST -> AABB_EAST_WALL; - case SOUTH -> AABB_SOUTH_WALL; - // NORTH; up and down don't happen (but we need branches for them) - default -> AABB_WEST_WALL; - }; - }; - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { - super.createBlockStateDefinition(builder); - builder.add(FACING, ATTACH_FACE, WATERLOGGED); - } - - @Override - @Nullable - public BlockState getStateForPlacement(BlockPlaceContext pContext) { - FluidState fluidState = pContext.getLevel().getFluidState(pContext.getClickedPos()); - - for (Direction direction : pContext.getNearestLookingDirections()) { - BlockState blockstate; - if (direction.getAxis() == Direction.Axis.Y) { - blockstate = this.defaultBlockState() - .setValue(ATTACH_FACE, direction == Direction.UP ? AttachFace.CEILING : AttachFace.FLOOR) - .setValue(FACING, pContext.getHorizontalDirection().getOpposite()); - } else { - blockstate = this.defaultBlockState() - .setValue(ATTACH_FACE, AttachFace.WALL) - .setValue(FACING, direction.getOpposite()); - } - blockstate = blockstate.setValue(WATERLOGGED, - fluidState.is(FluidTags.WATER) && fluidState.getAmount() == 8); - - if (blockstate.canSurvive(pContext.getLevel(), pContext.getClickedPos())) { - return blockstate; - } - } - - return null; - } - - // i do as the FaceAttachedHorizontalDirectionBlock.java guides - @Override - public boolean canSurvive(BlockState pState, LevelReader pLevel, BlockPos pPos) { - return canAttach(pLevel, pPos, getConnectedDirection(pState).getOpposite()); - } - - @Override - public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, - BlockPos pCurrentPos, BlockPos pFacingPos) { - if (pState.getValue(WATERLOGGED)) { - pLevel.scheduleTick(pCurrentPos, Fluids.WATER, Fluids.WATER.getTickDelay(pLevel)); - } - - return getConnectedDirection(pState).getOpposite() == pFacing - && !pState.canSurvive(pLevel, pCurrentPos) ? - pState.getFluidState().createLegacyBlock() - : super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos); - } - - public static boolean canAttach(LevelReader pReader, BlockPos pPos, Direction pDirection) { - BlockPos blockpos = pPos.relative(pDirection); - return pReader.getBlockState(blockpos).isFaceSturdy(pReader, blockpos, pDirection.getOpposite()); - } - - protected static Direction getConnectedDirection(BlockState pState) { - return switch (pState.getValue(ATTACH_FACE)) { - case CEILING -> Direction.DOWN; - case FLOOR -> Direction.UP; - default -> pState.getValue(FACING); - }; - } - - public BlockState rotate(BlockState state, Rotation rot) { - return (BlockState) state.setValue(FACING, rot.rotate((Direction) state.getValue(FACING))); - } - - public BlockState mirror(BlockState state, Mirror mirror) { - return state.rotate(mirror.getRotation((Direction) state.getValue(FACING))); - } +public class BlockSlate extends BlockCircleComponent + implements EntityBlock, SimpleWaterloggedBlock { + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; + public static final EnumProperty<AttachFace> ATTACH_FACE = BlockStateProperties.ATTACH_FACE; + + public static final double THICKNESS = 1; + public static final VoxelShape AABB_FLOOR = Block.box(0, 0, 0, 16, THICKNESS, 16); + public static final VoxelShape AABB_CEILING = Block.box(0, 16 - THICKNESS, 0, 16, 16, 16); + public static final VoxelShape AABB_EAST_WALL = Block.box(0, 0, 0, THICKNESS, 16, 16); + public static final VoxelShape AABB_WEST_WALL = Block.box(16 - THICKNESS, 0, 0, 16, 16, 16); + public static final VoxelShape AABB_SOUTH_WALL = Block.box(0, 0, 0, 16, 16, THICKNESS); + public static final VoxelShape AABB_NORTH_WALL = Block.box(0, 0, 16 - THICKNESS, 16, 16, 16); + + public BlockSlate(Properties p_53182_) { + super(p_53182_); + this.registerDefaultState( + this.stateDefinition + .any() + .setValue(ENERGIZED, false) + .setValue(FACING, Direction.NORTH) + .setValue(WATERLOGGED, false)); + } + + @Override + public boolean propagatesSkylightDown( + BlockState state, @Nonnull BlockGetter reader, @Nonnull BlockPos pos) { + return !state.getValue(WATERLOGGED); + } + + @Nonnull + @Override + public FluidState getFluidState(BlockState state) { + return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override + public ControlFlow acceptControlFlow( + CastingImage imageIn, + CircleCastEnv env, + Direction enterDir, + BlockPos pos, + BlockState bs, + ServerLevel world) { + HexPattern pattern; + if (world.getBlockEntity(pos) instanceof BlockEntitySlate tile) { + pattern = tile.pattern; + } else { + return new ControlFlow.Stop(); + } + + var exitDirsSet = this.possibleExitDirections(pos, bs, world); + exitDirsSet.remove(enterDir.getOpposite()); + + var exitDirs = exitDirsSet.stream().map((dir) -> this.exitPositionFromDirection(pos, dir)); + + if (pattern == null) return new ControlFlow.Continue(imageIn, exitDirs.toList()); + + var vm = new CastingVM(imageIn, env); + + var result = vm.queueExecuteAndWrapIota(new PatternIota(pattern), world); + if (result.getResolutionType().getSuccess()) { + return new ControlFlow.Continue(vm.getImage(), exitDirs.toList()); + } else { + return new ControlFlow.Stop(); + } + } + + @Override + public boolean canEnterFromDirection( + Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world) { + var thisNormal = this.normalDir(pos, bs, world); + return enterDir != thisNormal.getOpposite(); // && enterDir != thisNormal; + } + + @Override + public EnumSet<Direction> possibleExitDirections(BlockPos pos, BlockState bs, Level world) { + var allDirs = EnumSet.allOf(Direction.class); + var normal = this.normalDir(pos, bs, world); + allDirs.remove(normal); + // allDirs.remove(normal.getOpposite()); + return allDirs; + } + + @SoftImplement("forge") + public ItemStack getCloneItemStack( + BlockState state, HitResult target, BlockGetter level, BlockPos pos, Player player) { + BlockEntity be = level.getBlockEntity(pos); + if (be instanceof BlockEntitySlate slate) { + ItemStack stack = new ItemStack(HexItems.SLATE); + if (slate.pattern != null) { + HexItems.SLATE.writeDatum(stack, new PatternIota(slate.pattern)); + } + return stack; + } + + return new ItemStack(this); + } + + @Override + public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) { + return switch (bs.getValue(ATTACH_FACE)) { + case FLOOR -> Direction.UP; + case CEILING -> Direction.DOWN; + case WALL -> bs.getValue(FACING); + }; + } + + @Override + public float particleHeight(BlockPos pos, BlockState bs, Level world) { + return 0.5f - 15f / 16f; + } + + @Nullable @Override + public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { + return new BlockEntitySlate(pPos, pState); + } + + @Override + public VoxelShape getShape( + BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + return switch (pState.getValue(ATTACH_FACE)) { + case FLOOR -> AABB_FLOOR; + case CEILING -> AABB_CEILING; + case WALL -> + switch (pState.getValue(FACING)) { + case NORTH -> AABB_NORTH_WALL; + case EAST -> AABB_EAST_WALL; + case SOUTH -> AABB_SOUTH_WALL; + // NORTH; up and down don't happen (but we need branches for them) + default -> AABB_WEST_WALL; + }; + }; + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { + super.createBlockStateDefinition(builder); + builder.add(FACING, ATTACH_FACE, WATERLOGGED); + } + + @Override + @Nullable public BlockState getStateForPlacement(BlockPlaceContext pContext) { + FluidState fluidState = pContext.getLevel().getFluidState(pContext.getClickedPos()); + + for (Direction direction : pContext.getNearestLookingDirections()) { + BlockState blockstate; + if (direction.getAxis() == Direction.Axis.Y) { + blockstate = + this.defaultBlockState() + .setValue( + ATTACH_FACE, direction == Direction.UP ? AttachFace.CEILING : AttachFace.FLOOR) + .setValue(FACING, pContext.getHorizontalDirection().getOpposite()); + } else { + blockstate = + this.defaultBlockState() + .setValue(ATTACH_FACE, AttachFace.WALL) + .setValue(FACING, direction.getOpposite()); + } + blockstate = + blockstate.setValue( + WATERLOGGED, fluidState.is(FluidTags.WATER) && fluidState.getAmount() == 8); + + if (blockstate.canSurvive(pContext.getLevel(), pContext.getClickedPos())) { + return blockstate; + } + } + + return null; + } + + // i do as the FaceAttachedHorizontalDirectionBlock.java guides + @Override + public boolean canSurvive(BlockState pState, LevelReader pLevel, BlockPos pPos) { + return canAttach(pLevel, pPos, getConnectedDirection(pState).getOpposite()); + } + + @Override + public BlockState updateShape( + BlockState pState, + Direction pFacing, + BlockState pFacingState, + LevelAccessor pLevel, + BlockPos pCurrentPos, + BlockPos pFacingPos) { + if (pState.getValue(WATERLOGGED)) { + pLevel.scheduleTick(pCurrentPos, Fluids.WATER, Fluids.WATER.getTickDelay(pLevel)); + } + + return getConnectedDirection(pState).getOpposite() == pFacing + && !pState.canSurvive(pLevel, pCurrentPos) + ? pState.getFluidState().createLegacyBlock() + : super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos); + } + + public static boolean canAttach(LevelReader pReader, BlockPos pPos, Direction pDirection) { + BlockPos blockpos = pPos.relative(pDirection); + return pReader + .getBlockState(blockpos) + .isFaceSturdy(pReader, blockpos, pDirection.getOpposite()); + } + + protected static Direction getConnectedDirection(BlockState pState) { + return switch (pState.getValue(ATTACH_FACE)) { + case CEILING -> Direction.DOWN; + case FLOOR -> Direction.UP; + default -> pState.getValue(FACING); + }; + } + + public BlockState rotate(BlockState state, Rotation rot) { + return (BlockState) state.setValue(FACING, rot.rotate((Direction) state.getValue(FACING))); + } + + public BlockState mirror(BlockState state, Mirror mirror) { + return state.rotate(mirror.getRotation((Direction) state.getValue(FACING))); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockBooleanDirectrix.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockBooleanDirectrix.java index 81306f05de..47222eda90 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockBooleanDirectrix.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockBooleanDirectrix.java @@ -6,6 +6,10 @@ import at.petrak.hexcasting.api.casting.iota.BooleanIota; import at.petrak.hexcasting.api.casting.mishaps.circle.MishapBoolDirectrixEmptyStack; import at.petrak.hexcasting.api.casting.mishaps.circle.MishapBoolDirectrixNotBool; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Locale; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; @@ -20,116 +24,120 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.material.PushReaction; - -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; -import java.util.Locale; // When pops a true, outputs to FACING, when pops a false, outputs to the opposite public class BlockBooleanDirectrix extends BlockCircleComponent { - public static final DirectionProperty FACING = BlockStateProperties.FACING; - public static final EnumProperty<State> STATE = EnumProperty.create("state", State.class); - - public BlockBooleanDirectrix(Properties properties) { - super(properties); - this.registerDefaultState(this.stateDefinition.any() - .setValue(ENERGIZED, false) - .setValue(STATE, State.NEITHER) - .setValue(FACING, Direction.NORTH)); - } - - @Override - public ControlFlow acceptControlFlow(CastingImage imageIn, CircleCastEnv env, Direction enterDir, BlockPos pos, - BlockState bs, ServerLevel world) { - var stack = new ArrayList<>(imageIn.getStack()); - if (stack.isEmpty()) { - this.fakeThrowMishap(pos, bs, imageIn, env, - new MishapBoolDirectrixEmptyStack(pos)); - return new ControlFlow.Stop(); - } - var last = stack.remove(stack.size() - 1); - - if (!(last instanceof BooleanIota biota)) { - this.fakeThrowMishap(pos, bs, imageIn, env, - new MishapBoolDirectrixNotBool(last, pos)); - return new ControlFlow.Stop(); - } - - world.setBlockAndUpdate(pos, bs.setValue(STATE, biota.getBool() ? State.TRUE : State.FALSE)); - - var outputDir = biota.getBool() - ? bs.getValue(FACING).getOpposite() - : bs.getValue(FACING); - var imageOut = imageIn.copy(stack, imageIn.getParenCount(), imageIn.getParenthesized(), - imageIn.getEscapeNext(), imageIn.getOpsConsumed(), imageIn.getUserData()); - - return new ControlFlow.Continue(imageOut, List.of(this.exitPositionFromDirection(pos, outputDir))); - } - - @Override - public boolean canEnterFromDirection(Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world) { - // No entering from the front, no entering from the back. - return enterDir != bs.getValue(FACING).getOpposite() && enterDir != bs.getValue(FACING); - } - - @Override - public EnumSet<Direction> possibleExitDirections(BlockPos pos, BlockState bs, Level world) { - return EnumSet.of(bs.getValue(FACING), bs.getValue(FACING).getOpposite()); - } - - @Override - public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) { - return normalDirOfOther(pos.relative(bs.getValue(FACING)), world, recursionLeft); - } - - @Override - public float particleHeight(BlockPos pos, BlockState bs, Level world) { - return 0.5f; - } - - @Override - public BlockState endEnergized(BlockPos pos, BlockState bs, Level world) { - var newState = bs.setValue(ENERGIZED, false).setValue(STATE, State.NEITHER); - world.setBlockAndUpdate(pos, newState); - return newState; - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { - super.createBlockStateDefinition(builder); - builder.add(STATE, FACING); - } - - - @Override - public BlockState getStateForPlacement(BlockPlaceContext pContext) { - return BlockCircleComponent.placeStateDirAndSneak(this.defaultBlockState(), pContext); - } - - @Override - public BlockState rotate(BlockState pState, Rotation pRot) { - return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING))); - } - - @Override - public BlockState mirror(BlockState pState, Mirror pMirror) { - return pState.rotate(pMirror.getRotation(pState.getValue(FACING))); - } - - public enum State implements StringRepresentable { - // Freshly started - NEITHER, - // Popped a true - TRUE, - // Popped a false - FALSE, - ; - - @Override - public String getSerializedName() { - return this.name().toLowerCase(Locale.ROOT); - } - } + public static final DirectionProperty FACING = BlockStateProperties.FACING; + public static final EnumProperty<State> STATE = EnumProperty.create("state", State.class); + + public BlockBooleanDirectrix(Properties properties) { + super(properties); + this.registerDefaultState( + this.stateDefinition + .any() + .setValue(ENERGIZED, false) + .setValue(STATE, State.NEITHER) + .setValue(FACING, Direction.NORTH)); + } + + @Override + public ControlFlow acceptControlFlow( + CastingImage imageIn, + CircleCastEnv env, + Direction enterDir, + BlockPos pos, + BlockState bs, + ServerLevel world) { + var stack = new ArrayList<>(imageIn.getStack()); + if (stack.isEmpty()) { + this.fakeThrowMishap(pos, bs, imageIn, env, new MishapBoolDirectrixEmptyStack(pos)); + return new ControlFlow.Stop(); + } + var last = stack.remove(stack.size() - 1); + + if (!(last instanceof BooleanIota biota)) { + this.fakeThrowMishap(pos, bs, imageIn, env, new MishapBoolDirectrixNotBool(last, pos)); + return new ControlFlow.Stop(); + } + + world.setBlockAndUpdate(pos, bs.setValue(STATE, biota.getBool() ? State.TRUE : State.FALSE)); + + var outputDir = biota.getBool() ? bs.getValue(FACING).getOpposite() : bs.getValue(FACING); + var imageOut = + imageIn.copy( + stack, + imageIn.getParenCount(), + imageIn.getParenthesized(), + imageIn.getEscapeNext(), + imageIn.getOpsConsumed(), + imageIn.getUserData()); + + return new ControlFlow.Continue( + imageOut, List.of(this.exitPositionFromDirection(pos, outputDir))); + } + + @Override + public boolean canEnterFromDirection( + Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world) { + // No entering from the front, no entering from the back. + return enterDir != bs.getValue(FACING).getOpposite() && enterDir != bs.getValue(FACING); + } + + @Override + public EnumSet<Direction> possibleExitDirections(BlockPos pos, BlockState bs, Level world) { + return EnumSet.of(bs.getValue(FACING), bs.getValue(FACING).getOpposite()); + } + + @Override + public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) { + return normalDirOfOther(pos.relative(bs.getValue(FACING)), world, recursionLeft); + } + + @Override + public float particleHeight(BlockPos pos, BlockState bs, Level world) { + return 0.5f; + } + + @Override + public BlockState endEnergized(BlockPos pos, BlockState bs, Level world) { + var newState = bs.setValue(ENERGIZED, false).setValue(STATE, State.NEITHER); + world.setBlockAndUpdate(pos, newState); + return newState; + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { + super.createBlockStateDefinition(builder); + builder.add(STATE, FACING); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + return BlockCircleComponent.placeStateDirAndSneak(this.defaultBlockState(), pContext); + } + + @Override + public BlockState rotate(BlockState pState, Rotation pRot) { + return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING))); + } + + @Override + public BlockState mirror(BlockState pState, Mirror pMirror) { + return pState.rotate(pMirror.getRotation(pState.getValue(FACING))); + } + + public enum State implements StringRepresentable { + // Freshly started + NEITHER, + // Popped a true + TRUE, + // Popped a false + FALSE, + ; + + @Override + public String getSerializedName() { + return this.name().toLowerCase(Locale.ROOT); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockEmptyDirectrix.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockEmptyDirectrix.java index 3853f17805..b180e11121 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockEmptyDirectrix.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockEmptyDirectrix.java @@ -3,6 +3,8 @@ import at.petrak.hexcasting.api.block.circle.BlockCircleComponent; import at.petrak.hexcasting.api.casting.eval.env.CircleCastEnv; import at.petrak.hexcasting.api.casting.eval.vm.CastingImage; +import java.util.EnumSet; +import java.util.List; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; @@ -15,70 +17,69 @@ 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.DirectionProperty; -import net.minecraft.world.level.material.PushReaction; - -import java.util.EnumSet; -import java.util.List; public class BlockEmptyDirectrix extends BlockCircleComponent { - // Technically the impetus only needs an axis, but all the datagen assumes it has a facing - // so i might as well - public static final DirectionProperty FACING = BlockStateProperties.FACING; + // Technically the impetus only needs an axis, but all the datagen assumes it has a facing + // so i might as well + public static final DirectionProperty FACING = BlockStateProperties.FACING; - public BlockEmptyDirectrix(Properties p_49795_) { - super(p_49795_); - this.registerDefaultState(this.stateDefinition.any() - .setValue(ENERGIZED, false) - .setValue(FACING, Direction.NORTH)); - } + public BlockEmptyDirectrix(Properties p_49795_) { + super(p_49795_); + this.registerDefaultState( + this.stateDefinition.any().setValue(ENERGIZED, false).setValue(FACING, Direction.NORTH)); + } - @Override - public ControlFlow acceptControlFlow(CastingImage imageIn, CircleCastEnv env, Direction enterDir, BlockPos pos, - BlockState bs, ServerLevel world) { - var sign = world.random.nextBoolean() - ? bs.getValue(FACING) - : bs.getValue(FACING).getOpposite(); - return new ControlFlow.Continue(imageIn, List.of(this.exitPositionFromDirection(pos, sign))); - } + @Override + public ControlFlow acceptControlFlow( + CastingImage imageIn, + CircleCastEnv env, + Direction enterDir, + BlockPos pos, + BlockState bs, + ServerLevel world) { + var sign = world.random.nextBoolean() ? bs.getValue(FACING) : bs.getValue(FACING).getOpposite(); + return new ControlFlow.Continue(imageIn, List.of(this.exitPositionFromDirection(pos, sign))); + } - @Override - public boolean canEnterFromDirection(Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world) { - return true; - } + @Override + public boolean canEnterFromDirection( + Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world) { + return true; + } - @Override - public EnumSet<Direction> possibleExitDirections(BlockPos pos, BlockState bs, Level world) { - return EnumSet.of(bs.getValue(FACING), bs.getValue(FACING).getOpposite()); - } + @Override + public EnumSet<Direction> possibleExitDirections(BlockPos pos, BlockState bs, Level world) { + return EnumSet.of(bs.getValue(FACING), bs.getValue(FACING).getOpposite()); + } - @Override - public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) { - return Direction.UP; - } + @Override + public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) { + return Direction.UP; + } - @Override - public float particleHeight(BlockPos pos, BlockState bs, Level world) { - return 0.5f; - } + @Override + public float particleHeight(BlockPos pos, BlockState bs, Level world) { + return 0.5f; + } - @Override - protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { - super.createBlockStateDefinition(builder); - builder.add(FACING); - } + @Override + protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { + super.createBlockStateDefinition(builder); + builder.add(FACING); + } - @Override - public BlockState getStateForPlacement(BlockPlaceContext pContext) { - return BlockCircleComponent.placeStateDirAndSneak(this.defaultBlockState(), pContext); - } + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + return BlockCircleComponent.placeStateDirAndSneak(this.defaultBlockState(), pContext); + } - @Override - public BlockState rotate(BlockState pState, Rotation pRot) { - return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING))); - } + @Override + public BlockState rotate(BlockState pState, Rotation pRot) { + return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING))); + } - @Override - public BlockState mirror(BlockState pState, Mirror pMirror) { - return pState.rotate(pMirror.getRotation(pState.getValue(FACING))); - } + @Override + public BlockState mirror(BlockState pState, Mirror pMirror) { + return pState.rotate(pMirror.getRotation(pState.getValue(FACING))); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockRedstoneDirectrix.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockRedstoneDirectrix.java index 0143d8e3f7..7f884edf2c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockRedstoneDirectrix.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockRedstoneDirectrix.java @@ -3,6 +3,8 @@ import at.petrak.hexcasting.api.block.circle.BlockCircleComponent; import at.petrak.hexcasting.api.casting.eval.env.CircleCastEnv; import at.petrak.hexcasting.api.casting.eval.vm.CastingImage; +import java.util.EnumSet; +import java.util.List; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.DustParticleOptions; @@ -18,109 +20,117 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.DirectionProperty; -import net.minecraft.world.level.material.PushReaction; import net.minecraft.world.phys.Vec3; -import java.util.EnumSet; -import java.util.List; - // Outputs FACING when powered; outputs backwards otherwise // The FACING face is the happy one, bc i guess it's happy to get the redstone power public class BlockRedstoneDirectrix extends BlockCircleComponent { - public static final DirectionProperty FACING = BlockStateProperties.FACING; - public static final BooleanProperty REDSTONE_POWERED = BlockStateProperties.POWERED; - - public BlockRedstoneDirectrix(Properties p_49795_) { - super(p_49795_); - this.registerDefaultState(this.stateDefinition.any() - .setValue(REDSTONE_POWERED, false) - .setValue(ENERGIZED, false) - .setValue(FACING, Direction.NORTH)); - } - - @Override - public ControlFlow acceptControlFlow(CastingImage imageIn, CircleCastEnv env, Direction enterDir, BlockPos pos, - BlockState bs, ServerLevel world) { - return new ControlFlow.Continue(imageIn, List.of(this.exitPositionFromDirection(pos, getRealFacing(bs)))); - } - - @Override - public boolean canEnterFromDirection(Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world) { - return true; - } - - @Override - public EnumSet<Direction> possibleExitDirections(BlockPos pos, BlockState bs, Level world) { - return EnumSet.of(bs.getValue(FACING), bs.getValue(FACING).getOpposite()); - } - - @Override - public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) { - return normalDirOfOther(pos.relative(getRealFacing(bs)), world, recursionLeft); - } - - @Override - public float particleHeight(BlockPos pos, BlockState bs, Level world) { - return 0.5f; - } - - protected Direction getRealFacing(BlockState bs) { - var facing = bs.getValue(FACING); - if (bs.getValue(REDSTONE_POWERED)) { - return facing; - } else { - return facing.getOpposite(); - } - } - - @Override - public void neighborChanged(BlockState pState, Level pLevel, BlockPos pPos, Block pBlock, BlockPos pFromPos, - boolean pIsMoving) { - super.neighborChanged(pState, pLevel, pPos, pBlock, pFromPos, pIsMoving); - - if (!pLevel.isClientSide) { - boolean currentlyPowered = pState.getValue(REDSTONE_POWERED); - if (currentlyPowered != pLevel.hasNeighborSignal(pPos)) { - pLevel.setBlock(pPos, pState.setValue(REDSTONE_POWERED, !currentlyPowered), 2); - } - } - } - - - @Override - public void animateTick(BlockState bs, Level pLevel, BlockPos pos, RandomSource rand) { - if (bs.getValue(REDSTONE_POWERED)) { - for (int i = 0; i < 2; i++) { - var step = bs.getValue(FACING).step(); - var center = Vec3.atCenterOf(pos).add(step.x() * 0.5, step.y() * 0.5, step.z() * 0.5); - double x = center.x + (rand.nextDouble() - 0.5) * 0.5D; - double y = center.y + (rand.nextDouble() - 0.5) * 0.5D; - double z = center.z + (rand.nextDouble() - 0.5) * 0.5D; - pLevel.addParticle(DustParticleOptions.REDSTONE, x, y, z, - step.x() * 0.1, step.y() * 0.1, step.z() * 0.1); - } - } - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { - super.createBlockStateDefinition(builder); - builder.add(REDSTONE_POWERED, FACING); - } - - - @Override - public BlockState getStateForPlacement(BlockPlaceContext pContext) { - return BlockCircleComponent.placeStateDirAndSneak(this.defaultBlockState(), pContext); - } - - @Override - public BlockState rotate(BlockState pState, Rotation pRot) { - return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING))); - } - - @Override - public BlockState mirror(BlockState pState, Mirror pMirror) { - return pState.rotate(pMirror.getRotation(pState.getValue(FACING))); - } + public static final DirectionProperty FACING = BlockStateProperties.FACING; + public static final BooleanProperty REDSTONE_POWERED = BlockStateProperties.POWERED; + + public BlockRedstoneDirectrix(Properties p_49795_) { + super(p_49795_); + this.registerDefaultState( + this.stateDefinition + .any() + .setValue(REDSTONE_POWERED, false) + .setValue(ENERGIZED, false) + .setValue(FACING, Direction.NORTH)); + } + + @Override + public ControlFlow acceptControlFlow( + CastingImage imageIn, + CircleCastEnv env, + Direction enterDir, + BlockPos pos, + BlockState bs, + ServerLevel world) { + return new ControlFlow.Continue( + imageIn, List.of(this.exitPositionFromDirection(pos, getRealFacing(bs)))); + } + + @Override + public boolean canEnterFromDirection( + Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world) { + return true; + } + + @Override + public EnumSet<Direction> possibleExitDirections(BlockPos pos, BlockState bs, Level world) { + return EnumSet.of(bs.getValue(FACING), bs.getValue(FACING).getOpposite()); + } + + @Override + public Direction normalDir(BlockPos pos, BlockState bs, Level world, int recursionLeft) { + return normalDirOfOther(pos.relative(getRealFacing(bs)), world, recursionLeft); + } + + @Override + public float particleHeight(BlockPos pos, BlockState bs, Level world) { + return 0.5f; + } + + protected Direction getRealFacing(BlockState bs) { + var facing = bs.getValue(FACING); + if (bs.getValue(REDSTONE_POWERED)) { + return facing; + } else { + return facing.getOpposite(); + } + } + + @Override + public void neighborChanged( + BlockState pState, + Level pLevel, + BlockPos pPos, + Block pBlock, + BlockPos pFromPos, + boolean pIsMoving) { + super.neighborChanged(pState, pLevel, pPos, pBlock, pFromPos, pIsMoving); + + if (!pLevel.isClientSide) { + boolean currentlyPowered = pState.getValue(REDSTONE_POWERED); + if (currentlyPowered != pLevel.hasNeighborSignal(pPos)) { + pLevel.setBlock(pPos, pState.setValue(REDSTONE_POWERED, !currentlyPowered), 2); + } + } + } + + @Override + public void animateTick(BlockState bs, Level pLevel, BlockPos pos, RandomSource rand) { + if (bs.getValue(REDSTONE_POWERED)) { + for (int i = 0; i < 2; i++) { + var step = bs.getValue(FACING).step(); + var center = Vec3.atCenterOf(pos).add(step.x() * 0.5, step.y() * 0.5, step.z() * 0.5); + double x = center.x + (rand.nextDouble() - 0.5) * 0.5D; + double y = center.y + (rand.nextDouble() - 0.5) * 0.5D; + double z = center.z + (rand.nextDouble() - 0.5) * 0.5D; + pLevel.addParticle( + DustParticleOptions.REDSTONE, x, y, z, step.x() * 0.1, step.y() * 0.1, step.z() * 0.1); + } + } + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { + super.createBlockStateDefinition(builder); + builder.add(REDSTONE_POWERED, FACING); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + return BlockCircleComponent.placeStateDirAndSneak(this.defaultBlockState(), pContext); + } + + @Override + public BlockState rotate(BlockState pState, Rotation pRot) { + return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING))); + } + + @Override + public BlockState mirror(BlockState pState, Mirror pMirror) { + return pState.rotate(pMirror.getRotation(pState.getValue(FACING))); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityLookingImpetus.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityLookingImpetus.java index 963d62a649..6d95a8e5ee 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityLookingImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityLookingImpetus.java @@ -18,80 +18,81 @@ import net.minecraft.world.phys.HitResult; public class BlockEntityLookingImpetus extends BlockEntityAbstractImpetus { - public static final int MAX_LOOK_AMOUNT = 30; - public static final String TAG_LOOK_AMOUNT = "look_amount"; + public static final int MAX_LOOK_AMOUNT = 30; + public static final String TAG_LOOK_AMOUNT = "look_amount"; - private int lookAmount = 0; + private int lookAmount = 0; - public BlockEntityLookingImpetus(BlockPos pWorldPosition, BlockState pBlockState) { - super(HexBlockEntities.IMPETUS_LOOK_TILE, pWorldPosition, pBlockState); - } + public BlockEntityLookingImpetus(BlockPos pWorldPosition, BlockState pBlockState) { + super(HexBlockEntities.IMPETUS_LOOK_TILE, pWorldPosition, pBlockState); + } - // https://github.com/VazkiiMods/Botania/blob/2607bcd31c4eaeb617f7d1b3ec1c1db08f59add4/Common/src/main/java/vazkii/botania/common/block/tile/TileEnderEye.java#L27 - public static void serverTick(Level level, BlockPos pos, BlockState bs, BlockEntityLookingImpetus self) { - if (bs.getValue(BlockCircleComponent.ENERGIZED)) { - return; - } + // https://github.com/VazkiiMods/Botania/blob/2607bcd31c4eaeb617f7d1b3ec1c1db08f59add4/Common/src/main/java/vazkii/botania/common/block/tile/TileEnderEye.java#L27 + public static void serverTick( + Level level, BlockPos pos, BlockState bs, BlockEntityLookingImpetus self) { + if (bs.getValue(BlockCircleComponent.ENERGIZED)) { + return; + } - int prevLookAmt = self.lookAmount; - int range = 20; - var players = level.getEntitiesOfClass(ServerPlayer.class, - new AABB(pos.offset(-range, -range, -range), pos.offset(range, range, range))); + int prevLookAmt = self.lookAmount; + int range = 20; + var players = + level.getEntitiesOfClass( + ServerPlayer.class, + new AABB(pos.offset(-range, -range, -range), pos.offset(range, range, range))); - ServerPlayer looker = null; - for (var player : players) { - // might as well impl this heh - var hat = player.getItemBySlot(EquipmentSlot.HEAD); - // sadly `isEnderMask` requires the enderman - if (!hat.isEmpty() && hat.is(Blocks.CARVED_PUMPKIN.asItem())) { - continue; - } + ServerPlayer looker = null; + for (var player : players) { + // might as well impl this heh + var hat = player.getItemBySlot(EquipmentSlot.HEAD); + // sadly `isEnderMask` requires the enderman + if (!hat.isEmpty() && hat.is(Blocks.CARVED_PUMPKIN.asItem())) { + continue; + } - var lookEnd = player.getLookAngle().scale(range / 1.5f); // add some slop - var hit = level.clip(new ClipContext( - player.getEyePosition(), - player.getEyePosition().add(lookEnd), - ClipContext.Block.VISUAL, - ClipContext.Fluid.NONE, - player - )); - if (hit.getType() == HitResult.Type.BLOCK && hit.getBlockPos().equals(pos)) { - looker = player; - break; - } - } + var lookEnd = player.getLookAngle().scale(range / 1.5f); // add some slop + var hit = + level.clip( + new ClipContext( + player.getEyePosition(), + player.getEyePosition().add(lookEnd), + ClipContext.Block.VISUAL, + ClipContext.Fluid.NONE, + player)); + if (hit.getType() == HitResult.Type.BLOCK && hit.getBlockPos().equals(pos)) { + looker = player; + break; + } + } - var newLook = Mth.clamp( - prevLookAmt + (looker == null ? -1 : 1), - 0, - MAX_LOOK_AMOUNT - ); - if (newLook != prevLookAmt) { - if (newLook == MAX_LOOK_AMOUNT) { - self.lookAmount = 0; - self.startExecution(looker); - } else { - if (newLook % 5 == 1) { - var t = (float) newLook / MAX_LOOK_AMOUNT; - var pitch = Mth.lerp(t, 0.5f, 1.2f); - var volume = Mth.lerp(t, 0.2f, 1.2f); - level.playSound(null, pos, HexSounds.IMPETUS_LOOK_TICK, SoundSource.BLOCKS, volume, pitch); - } - self.lookAmount = newLook; - self.setChanged(); - } - } - } + var newLook = Mth.clamp(prevLookAmt + (looker == null ? -1 : 1), 0, MAX_LOOK_AMOUNT); + if (newLook != prevLookAmt) { + if (newLook == MAX_LOOK_AMOUNT) { + self.lookAmount = 0; + self.startExecution(looker); + } else { + if (newLook % 5 == 1) { + var t = (float) newLook / MAX_LOOK_AMOUNT; + var pitch = Mth.lerp(t, 0.5f, 1.2f); + var volume = Mth.lerp(t, 0.2f, 1.2f); + level.playSound( + null, pos, HexSounds.IMPETUS_LOOK_TICK, SoundSource.BLOCKS, volume, pitch); + } + self.lookAmount = newLook; + self.setChanged(); + } + } + } - @Override - protected void saveModData(CompoundTag tag) { - super.saveModData(tag); - tag.putInt(TAG_LOOK_AMOUNT, this.lookAmount); - } + @Override + protected void saveModData(CompoundTag tag) { + super.saveModData(tag); + tag.putInt(TAG_LOOK_AMOUNT, this.lookAmount); + } - @Override - protected void loadModData(CompoundTag tag) { - super.loadModData(tag); - this.lookAmount = tag.getInt(TAG_LOOK_AMOUNT); - } + @Override + protected void loadModData(CompoundTag tag) { + super.loadModData(tag); + this.lookAmount = tag.getInt(TAG_LOOK_AMOUNT); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java index b776d156ce..899d8ce3a0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java @@ -6,6 +6,8 @@ import at.petrak.hexcasting.common.lib.HexBlockEntities; import com.mojang.authlib.GameProfile; import com.mojang.datafixers.util.Pair; +import java.util.List; +import java.util.UUID; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -21,124 +23,130 @@ import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.Nullable; -import java.util.List; -import java.util.UUID; - public class BlockEntityRedstoneImpetus extends BlockEntityAbstractImpetus { - public static final String TAG_STORED_PLAYER = "stored_player"; - public static final String TAG_STORED_PLAYER_PROFILE = "stored_player_profile"; - - private GameProfile storedPlayerProfile = null; - private UUID storedPlayer = null; - - private GameProfile cachedDisplayProfile = null; - private ItemStack cachedDisplayStack = null; - - public BlockEntityRedstoneImpetus(BlockPos pWorldPosition, BlockState pBlockState) { - super(HexBlockEntities.IMPETUS_REDSTONE_TILE, pWorldPosition, pBlockState); - } - - protected @Nullable - GameProfile getPlayerName() { - if (this.level instanceof ServerLevel) { - Player player = getStoredPlayer(); - if (player != null) { - return player.getGameProfile(); - } - } - - return this.storedPlayerProfile; - } - - public void setPlayer(GameProfile profile, UUID player) { - this.storedPlayerProfile = profile; - this.storedPlayer = player; - this.setChanged(); - } - - public void clearPlayer() { - this.storedPlayerProfile = null; - this.storedPlayer = null; - } - - public void updatePlayerProfile() { - ServerPlayer player = getStoredPlayer(); - if (player != null) { - GameProfile newProfile = player.getGameProfile(); - if (!newProfile.equals(this.storedPlayerProfile)) { - this.storedPlayerProfile = newProfile; - this.setChanged(); - } - } else { - this.storedPlayerProfile = null; - } - } - - // just feels wrong to use the protected method - @Nullable - public ServerPlayer getStoredPlayer() { - if (this.storedPlayer == null) { - return null; - } - if (!(this.level instanceof ServerLevel slevel)) { - HexAPI.LOGGER.error("Called getStoredPlayer on the client"); - return null; - } - var e = slevel.getEntity(this.storedPlayer); - if (e instanceof ServerPlayer player) { - return player; - } else { - HexAPI.LOGGER.error("Entity {} stored in a cleric impetus wasn't a player somehow", e); - return null; - } - } - - public void applyScryingLensOverlay(List<Pair<ItemStack, Component>> lines, - BlockState state, BlockPos pos, Player observer, - Level world, - Direction hitFace) { - super.applyScryingLensOverlay(lines, state, pos, observer, world, hitFace); - - var name = this.getPlayerName(); - if (name != null) { - if (!name.equals(cachedDisplayProfile) || cachedDisplayStack == null) { - cachedDisplayProfile = name; - var head = new ItemStack(Items.PLAYER_HEAD); - NBTHelper.put(head, "SkullOwner", NbtUtils.writeGameProfile(new CompoundTag(), name)); - head.getItem().verifyTagAfterLoad(head.getOrCreateTag()); - cachedDisplayStack = head; - } - lines.add(new Pair<>(cachedDisplayStack, - Component.translatable("hexcasting.tooltip.lens.impetus.redstone.bound", name.getName()))); - } else { - lines.add(new Pair<>(new ItemStack(Items.BARRIER), - Component.translatable("hexcasting.tooltip.lens.impetus.redstone.bound.none"))); - } - } - - @Override - protected void saveModData(CompoundTag tag) { - super.saveModData(tag); - if (this.storedPlayer != null) { - tag.putUUID(TAG_STORED_PLAYER, this.storedPlayer); - } - if (this.storedPlayerProfile != null) { - tag.put(TAG_STORED_PLAYER_PROFILE, NbtUtils.writeGameProfile(new CompoundTag(), storedPlayerProfile)); - } - } - - @Override - protected void loadModData(CompoundTag tag) { - super.loadModData(tag); - if (tag.contains(TAG_STORED_PLAYER, Tag.TAG_INT_ARRAY)) { - this.storedPlayer = tag.getUUID(TAG_STORED_PLAYER); - } else { - this.storedPlayer = null; - } - if (tag.contains(TAG_STORED_PLAYER_PROFILE, Tag.TAG_COMPOUND)) { - this.storedPlayerProfile = NbtUtils.readGameProfile(tag.getCompound(TAG_STORED_PLAYER_PROFILE)); - } else { - this.storedPlayerProfile = null; - } - } + public static final String TAG_STORED_PLAYER = "stored_player"; + public static final String TAG_STORED_PLAYER_PROFILE = "stored_player_profile"; + + private GameProfile storedPlayerProfile = null; + private UUID storedPlayer = null; + + private GameProfile cachedDisplayProfile = null; + private ItemStack cachedDisplayStack = null; + + public BlockEntityRedstoneImpetus(BlockPos pWorldPosition, BlockState pBlockState) { + super(HexBlockEntities.IMPETUS_REDSTONE_TILE, pWorldPosition, pBlockState); + } + + protected @Nullable GameProfile getPlayerName() { + if (this.level instanceof ServerLevel) { + Player player = getStoredPlayer(); + if (player != null) { + return player.getGameProfile(); + } + } + + return this.storedPlayerProfile; + } + + public void setPlayer(GameProfile profile, UUID player) { + this.storedPlayerProfile = profile; + this.storedPlayer = player; + this.setChanged(); + } + + public void clearPlayer() { + this.storedPlayerProfile = null; + this.storedPlayer = null; + } + + public void updatePlayerProfile() { + ServerPlayer player = getStoredPlayer(); + if (player != null) { + GameProfile newProfile = player.getGameProfile(); + if (!newProfile.equals(this.storedPlayerProfile)) { + this.storedPlayerProfile = newProfile; + this.setChanged(); + } + } else { + this.storedPlayerProfile = null; + } + } + + // just feels wrong to use the protected method + @Nullable public ServerPlayer getStoredPlayer() { + if (this.storedPlayer == null) { + return null; + } + if (!(this.level instanceof ServerLevel slevel)) { + HexAPI.LOGGER.error("Called getStoredPlayer on the client"); + return null; + } + var e = slevel.getEntity(this.storedPlayer); + if (e instanceof ServerPlayer player) { + return player; + } else { + HexAPI.LOGGER.error("Entity {} stored in a cleric impetus wasn't a player somehow", e); + return null; + } + } + + public void applyScryingLensOverlay( + List<Pair<ItemStack, Component>> lines, + BlockState state, + BlockPos pos, + Player observer, + Level world, + Direction hitFace) { + super.applyScryingLensOverlay(lines, state, pos, observer, world, hitFace); + + var name = this.getPlayerName(); + if (name != null) { + if (!name.equals(cachedDisplayProfile) || cachedDisplayStack == null) { + cachedDisplayProfile = name; + var head = new ItemStack(Items.PLAYER_HEAD); + NBTHelper.put(head, "SkullOwner", NbtUtils.writeGameProfile(new CompoundTag(), name)); + head.getItem().verifyTagAfterLoad(head.getOrCreateTag()); + cachedDisplayStack = head; + } + lines.add( + new Pair<>( + cachedDisplayStack, + Component.translatable( + "hexcasting.tooltip.lens.impetus.redstone.bound", name.getName()))); + } else { + lines.add( + new Pair<>( + new ItemStack(Items.BARRIER), + Component.translatable("hexcasting.tooltip.lens.impetus.redstone.bound.none"))); + } + } + + @Override + protected void saveModData(CompoundTag tag) { + super.saveModData(tag); + if (this.storedPlayer != null) { + tag.putUUID(TAG_STORED_PLAYER, this.storedPlayer); + } + if (this.storedPlayerProfile != null) { + tag.put( + TAG_STORED_PLAYER_PROFILE, + NbtUtils.writeGameProfile(new CompoundTag(), storedPlayerProfile)); + } + } + + @Override + protected void loadModData(CompoundTag tag) { + super.loadModData(tag); + if (tag.contains(TAG_STORED_PLAYER, Tag.TAG_INT_ARRAY)) { + this.storedPlayer = tag.getUUID(TAG_STORED_PLAYER); + } else { + this.storedPlayer = null; + } + if (tag.contains(TAG_STORED_PLAYER_PROFILE, Tag.TAG_COMPOUND)) { + this.storedPlayerProfile = + NbtUtils.readGameProfile(tag.getCompound(TAG_STORED_PLAYER_PROFILE)); + } else { + this.storedPlayerProfile = null; + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRightClickImpetus.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRightClickImpetus.java index 8e7498d3fe..896a0235b6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRightClickImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRightClickImpetus.java @@ -6,7 +6,7 @@ import net.minecraft.world.level.block.state.BlockState; public class BlockEntityRightClickImpetus extends BlockEntityAbstractImpetus { - public BlockEntityRightClickImpetus(BlockPos pWorldPosition, BlockState pBlockState) { - super(HexBlockEntities.IMPETUS_RIGHTCLICK_TILE, pWorldPosition, pBlockState); - } + public BlockEntityRightClickImpetus(BlockPos pWorldPosition, BlockState pBlockState) { + super(HexBlockEntities.IMPETUS_RIGHTCLICK_TILE, pWorldPosition, pBlockState); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockLookingImpetus.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockLookingImpetus.java index 6cb5a1c245..250840f0ef 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockLookingImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockLookingImpetus.java @@ -12,33 +12,33 @@ public class BlockLookingImpetus extends BlockAbstractImpetus { - public BlockLookingImpetus(Properties p_49795_) { - super(p_49795_); - } + public BlockLookingImpetus(Properties p_49795_) { + super(p_49795_); + } - @Nullable - @Override - public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { - return new BlockEntityLookingImpetus(pPos, pState); - } + @Nullable @Override + public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { + return new BlockEntityLookingImpetus(pPos, pState); + } - @Nullable - @Override - public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level pLevel, BlockState pState, - BlockEntityType<T> type) { - if (!pLevel.isClientSide) { - return createTickerHelper(type, HexBlockEntities.IMPETUS_LOOK_TILE, - BlockEntityLookingImpetus::serverTick); - } else { - return null; - } - } + @Nullable @Override + public <T extends BlockEntity> BlockEntityTicker<T> getTicker( + Level pLevel, BlockState pState, BlockEntityType<T> type) { + if (!pLevel.isClientSide) { + return createTickerHelper( + type, HexBlockEntities.IMPETUS_LOOK_TILE, BlockEntityLookingImpetus::serverTick); + } else { + return null; + } + } - // uegh - @Nullable - @SuppressWarnings("unchecked") - protected static <E extends BlockEntity, A extends BlockEntity> BlockEntityTicker<A> createTickerHelper( - BlockEntityType<A> type, BlockEntityType<E> targetType, BlockEntityTicker<? super E> ticker) { - return targetType == type ? (BlockEntityTicker<A>) ticker : null; - } + // uegh + @Nullable @SuppressWarnings("unchecked") + protected static <E extends BlockEntity, A extends BlockEntity> + BlockEntityTicker<A> createTickerHelper( + BlockEntityType<A> type, + BlockEntityType<E> targetType, + BlockEntityTicker<? super E> ticker) { + return targetType == type ? (BlockEntityTicker<A>) ticker : null; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockRedstoneImpetus.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockRedstoneImpetus.java index 58b3ac7c18..6e0afafaea 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockRedstoneImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockRedstoneImpetus.java @@ -22,80 +22,89 @@ import org.jetbrains.annotations.Nullable; public class BlockRedstoneImpetus extends BlockAbstractImpetus { - public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; - public BlockRedstoneImpetus(Properties p_49795_) { - super(p_49795_); - } + public BlockRedstoneImpetus(Properties p_49795_) { + super(p_49795_); + } - @Nullable - @Override - public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { - return new BlockEntityRedstoneImpetus(pPos, pState); - } + @Nullable @Override + public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { + return new BlockEntityRedstoneImpetus(pPos, pState); + } - @Override - protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { - super.createBlockStateDefinition(builder); - builder.add(POWERED); - } + @Override + protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { + super.createBlockStateDefinition(builder); + builder.add(POWERED); + } - @Override - public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, - BlockHitResult pHit) { - if (pLevel instanceof ServerLevel level - && level.getBlockEntity(pPos) instanceof BlockEntityRedstoneImpetus tile) { - var usedStack = pPlayer.getItemInHand(pHand); - if (usedStack.isEmpty() && pPlayer.isDiscrete()) { - tile.clearPlayer(); - tile.sync(); - } else { - var datumContainer = IXplatAbstractions.INSTANCE.findDataHolder(usedStack); - if (datumContainer != null) { - var stored = datumContainer.readIota(level); - if (stored instanceof EntityIota eieio) { - var entity = eieio.getEntity(); - if (entity instanceof Player player) { - // phew, we got something - tile.setPlayer(player.getGameProfile(), entity.getUUID()); - tile.sync(); + @Override + public InteractionResult use( + BlockState pState, + Level pLevel, + BlockPos pPos, + Player pPlayer, + InteractionHand pHand, + BlockHitResult pHit) { + if (pLevel instanceof ServerLevel level + && level.getBlockEntity(pPos) instanceof BlockEntityRedstoneImpetus tile) { + var usedStack = pPlayer.getItemInHand(pHand); + if (usedStack.isEmpty() && pPlayer.isDiscrete()) { + tile.clearPlayer(); + tile.sync(); + } else { + var datumContainer = IXplatAbstractions.INSTANCE.findDataHolder(usedStack); + if (datumContainer != null) { + var stored = datumContainer.readIota(level); + if (stored instanceof EntityIota eieio) { + var entity = eieio.getEntity(); + if (entity instanceof Player player) { + // phew, we got something + tile.setPlayer(player.getGameProfile(), entity.getUUID()); + tile.sync(); - pLevel.playSound(pPlayer, pPos, HexSounds.IMPETUS_REDSTONE_DING, - SoundSource.BLOCKS, 1f, 1f); - } - } - } - } - } + pLevel.playSound( + pPlayer, pPos, HexSounds.IMPETUS_REDSTONE_DING, SoundSource.BLOCKS, 1f, 1f); + } + } + } + } + } - return InteractionResult.PASS; - } + return InteractionResult.PASS; + } - @Override - public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRandom) { - super.tick(pState, pLevel, pPos, pRandom); - if (pLevel.getBlockEntity(pPos) instanceof BlockEntityRedstoneImpetus tile) { - tile.updatePlayerProfile(); - } - } + @Override + public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRandom) { + super.tick(pState, pLevel, pPos, pRandom); + if (pLevel.getBlockEntity(pPos) instanceof BlockEntityRedstoneImpetus tile) { + tile.updatePlayerProfile(); + } + } - @Override - public void neighborChanged(BlockState pState, Level pLevel, BlockPos pPos, Block pBlock, BlockPos pFromPos, - boolean pIsMoving) { - super.neighborChanged(pState, pLevel, pPos, pBlock, pFromPos, pIsMoving); + @Override + public void neighborChanged( + BlockState pState, + Level pLevel, + BlockPos pPos, + Block pBlock, + BlockPos pFromPos, + boolean pIsMoving) { + super.neighborChanged(pState, pLevel, pPos, pBlock, pFromPos, pIsMoving); - if (pLevel instanceof ServerLevel slevel) { - boolean prevPowered = pState.getValue(POWERED); - boolean isPowered = pLevel.hasNeighborSignal(pPos); + if (pLevel instanceof ServerLevel slevel) { + boolean prevPowered = pState.getValue(POWERED); + boolean isPowered = pLevel.hasNeighborSignal(pPos); - if (prevPowered != isPowered) { - pLevel.setBlockAndUpdate(pPos, pState.setValue(POWERED, isPowered)); + if (prevPowered != isPowered) { + pLevel.setBlockAndUpdate(pPos, pState.setValue(POWERED, isPowered)); - if (isPowered && pLevel.getBlockEntity(pPos) instanceof BlockEntityRedstoneImpetus tile) { - var player = tile.getStoredPlayer(); - tile.startExecution(player); - } - } - } - } + if (isPowered && pLevel.getBlockEntity(pPos) instanceof BlockEntityRedstoneImpetus tile) { + var player = tile.getStoredPlayer(); + tile.startExecution(player); + } + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockRightClickImpetus.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockRightClickImpetus.java index cb6c3fb19c..2f1f5f3097 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockRightClickImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockRightClickImpetus.java @@ -13,29 +13,33 @@ import org.jetbrains.annotations.Nullable; public class BlockRightClickImpetus extends BlockAbstractImpetus { - public BlockRightClickImpetus(Properties p_49795_) { - super(p_49795_); - } + public BlockRightClickImpetus(Properties p_49795_) { + super(p_49795_); + } - @Nullable - @Override - public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { - return new BlockEntityRightClickImpetus(pPos, pState); - } + @Nullable @Override + public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { + return new BlockEntityRightClickImpetus(pPos, pState); + } - @Override - public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, - BlockHitResult pHit) { - if (!pPlayer.isShiftKeyDown()) { - var tile = pLevel.getBlockEntity(pPos); - if (tile instanceof BlockEntityRightClickImpetus impetus) { - if (pPlayer instanceof ServerPlayer serverPlayer) { -// impetus.activateSpellCircle(serverPlayer); - impetus.startExecution(serverPlayer); - } - return InteractionResult.SUCCESS; - } - } - return InteractionResult.PASS; - } + @Override + public InteractionResult use( + BlockState pState, + Level pLevel, + BlockPos pPos, + Player pPlayer, + InteractionHand pHand, + BlockHitResult pHit) { + if (!pPlayer.isShiftKeyDown()) { + var tile = pLevel.getBlockEntity(pPos); + if (tile instanceof BlockEntityRightClickImpetus impetus) { + if (pPlayer instanceof ServerPlayer serverPlayer) { + // impetus.activateSpellCircle(serverPlayer); + impetus.startExecution(serverPlayer); + } + return InteractionResult.SUCCESS; + } + } + return InteractionResult.PASS; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAkashicLeaves.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAkashicLeaves.java index 0603e1d393..0f42248a85 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAkashicLeaves.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAkashicLeaves.java @@ -8,22 +8,25 @@ import net.minecraft.world.level.block.state.BlockState; public class BlockAkashicLeaves extends LeavesBlock { - public BlockAkashicLeaves(Properties props) { - super(props); - } + public BlockAkashicLeaves(Properties props) { + super(props); + } - @SoftImplement("forge") - public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return true; - } + @SoftImplement("forge") + public boolean isFlammable( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return true; + } - @SoftImplement("forge") - public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 60; - } + @SoftImplement("forge") + public int getFlammability( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 60; + } - @SoftImplement("forge") - public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 30; - } + @SoftImplement("forge") + public int getFireSpreadSpeed( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 30; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAkashicLog.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAkashicLog.java index 6bf4d3343d..b0fc2a7c85 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAkashicLog.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAkashicLog.java @@ -7,23 +7,25 @@ import net.minecraft.world.level.block.state.BlockState; public class BlockAkashicLog extends BlockAxis { - public BlockAkashicLog(Properties props) { - super(props); - } + public BlockAkashicLog(Properties props) { + super(props); + } + @SoftImplement("forge") + public boolean isFlammable( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return true; + } - @SoftImplement("forge") - public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return true; - } + @SoftImplement("forge") + public int getFlammability( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 5; + } - @SoftImplement("forge") - public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 5; - } - - @SoftImplement("forge") - public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 5; - } + @SoftImplement("forge") + public int getFireSpreadSpeed( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 5; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAmethystDirectional.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAmethystDirectional.java index 8206a583a7..569a0f12fa 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAmethystDirectional.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAmethystDirectional.java @@ -13,24 +13,36 @@ import net.minecraft.world.phys.BlockHitResult; public class BlockAmethystDirectional extends DirectionalBlock { - public BlockAmethystDirectional(Properties properties) { - super(properties); - } + public BlockAmethystDirectional(Properties properties) { + super(properties); + } - public void onProjectileHit(Level level, BlockState state, BlockHitResult result, Projectile projectile) { - if (!level.isClientSide) { - BlockPos pos = result.getBlockPos(); - level.playSound(null, pos, SoundEvents.AMETHYST_BLOCK_HIT, SoundSource.BLOCKS, 1.0F, 0.5F + level.random.nextFloat() * 1.2F); - level.playSound(null, pos, SoundEvents.AMETHYST_BLOCK_CHIME, SoundSource.BLOCKS, 1.0F, 0.5F + level.random.nextFloat() * 1.2F); - } + public void onProjectileHit( + Level level, BlockState state, BlockHitResult result, Projectile projectile) { + if (!level.isClientSide) { + BlockPos pos = result.getBlockPos(); + level.playSound( + null, + pos, + SoundEvents.AMETHYST_BLOCK_HIT, + SoundSource.BLOCKS, + 1.0F, + 0.5F + level.random.nextFloat() * 1.2F); + level.playSound( + null, + pos, + SoundEvents.AMETHYST_BLOCK_CHIME, + SoundSource.BLOCKS, + 1.0F, + 0.5F + level.random.nextFloat() * 1.2F); + } + } - } + protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> $$0) { + $$0.add(FACING); + } - protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> $$0) { - $$0.add(FACING); - } - - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - return this.defaultBlockState().setValue(FACING, ctx.getClickedFace()); - } -} \ No newline at end of file + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + return this.defaultBlockState().setValue(FACING, ctx.getClickedFace()); + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAxis.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAxis.java index 4e99d60438..f0dd1348e5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAxis.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockAxis.java @@ -3,7 +3,7 @@ import net.minecraft.world.level.block.RotatedPillarBlock; public class BlockAxis extends RotatedPillarBlock { - public BlockAxis(Properties p_55926_) { - super(p_55926_); - } + public BlockAxis(Properties p_55926_) { + super(p_55926_); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexDoor.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexDoor.java index 6bc4459c00..9a40e2ae22 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexDoor.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexDoor.java @@ -9,24 +9,25 @@ import net.minecraft.world.level.block.state.BlockState; public class BlockHexDoor extends DoorBlock { - public BlockHexDoor(Properties $$0) { - super($$0, HexBlockSetTypes.EDIFIED_WOOD); - } + public BlockHexDoor(Properties $$0) { + super($$0, HexBlockSetTypes.EDIFIED_WOOD); + } + @SoftImplement("forge") + public boolean isFlammable( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return true; + } - @SoftImplement("forge") - public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return true; - } + @SoftImplement("forge") + public int getFlammability( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 20; + } - @SoftImplement("forge") - public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 20; - } - - @SoftImplement("forge") - public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 5; - } + @SoftImplement("forge") + public int getFireSpreadSpeed( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 5; + } } - diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexFence.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexFence.java index ec7ac95181..1421a3752c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexFence.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexFence.java @@ -9,22 +9,25 @@ public class BlockHexFence extends FenceBlock { - public BlockHexFence(Properties $$0) { - super($$0); - } + public BlockHexFence(Properties $$0) { + super($$0); + } - @SoftImplement("forge") - public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return true; - } + @SoftImplement("forge") + public boolean isFlammable( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return true; + } - @SoftImplement("forge") - public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 20; - } + @SoftImplement("forge") + public int getFlammability( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 20; + } - @SoftImplement("forge") - public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 5; - } + @SoftImplement("forge") + public int getFireSpreadSpeed( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 5; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexFenceGate.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexFenceGate.java index 10fc89230e..09d5e13f8b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexFenceGate.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexFenceGate.java @@ -1,7 +1,6 @@ package at.petrak.hexcasting.common.blocks.decoration; import at.petrak.hexcasting.annotations.SoftImplement; -import at.petrak.hexcasting.common.lib.HexBlockSetTypes; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.BlockGetter; @@ -11,22 +10,25 @@ public class BlockHexFenceGate extends FenceGateBlock { - public BlockHexFenceGate(Properties $$0) { - super($$0, WoodType.DARK_OAK); - } + public BlockHexFenceGate(Properties $$0) { + super($$0, WoodType.DARK_OAK); + } - @SoftImplement("forge") - public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return true; - } + @SoftImplement("forge") + public boolean isFlammable( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return true; + } - @SoftImplement("forge") - public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 20; - } + @SoftImplement("forge") + public int getFlammability( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 20; + } - @SoftImplement("forge") - public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 5; - } + @SoftImplement("forge") + public int getFireSpreadSpeed( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 5; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexPressurePlate.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexPressurePlate.java index 5e6a517b1d..09efb2e19d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexPressurePlate.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexPressurePlate.java @@ -9,23 +9,25 @@ import net.minecraft.world.level.block.state.BlockState; public class BlockHexPressurePlate extends PressurePlateBlock { - public BlockHexPressurePlate(Sensitivity $$0, Properties $$1) { - super($$0, $$1, HexBlockSetTypes.EDIFIED_WOOD); - } + public BlockHexPressurePlate(Sensitivity $$0, Properties $$1) { + super($$0, $$1, HexBlockSetTypes.EDIFIED_WOOD); + } + @SoftImplement("forge") + public boolean isFlammable( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return true; + } - @SoftImplement("forge") - public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return true; - } + @SoftImplement("forge") + public int getFlammability( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 20; + } - @SoftImplement("forge") - public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 20; - } - - @SoftImplement("forge") - public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 5; - } + @SoftImplement("forge") + public int getFireSpreadSpeed( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 5; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexSlab.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexSlab.java index 4f2f21c426..306a35eb81 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexSlab.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexSlab.java @@ -8,23 +8,25 @@ import net.minecraft.world.level.block.state.BlockState; public class BlockHexSlab extends SlabBlock { - public BlockHexSlab(Properties properties) { - super(properties); - } + public BlockHexSlab(Properties properties) { + super(properties); + } + @SoftImplement("forge") + public boolean isFlammable( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return true; + } - @SoftImplement("forge") - public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return true; - } + @SoftImplement("forge") + public int getFlammability( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 20; + } - @SoftImplement("forge") - public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 20; - } - - @SoftImplement("forge") - public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 5; - } + @SoftImplement("forge") + public int getFireSpreadSpeed( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 5; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexStairs.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexStairs.java index f2c0a06b81..fb361c3478 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexStairs.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexStairs.java @@ -8,22 +8,25 @@ import net.minecraft.world.level.block.state.BlockState; public class BlockHexStairs extends StairBlock { - public BlockHexStairs(BlockState $$0, Properties $$1) { - super($$0, $$1); - } + public BlockHexStairs(BlockState $$0, Properties $$1) { + super($$0, $$1); + } - @SoftImplement("forge") - public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return true; - } + @SoftImplement("forge") + public boolean isFlammable( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return true; + } - @SoftImplement("forge") - public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 20; - } + @SoftImplement("forge") + public int getFlammability( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 20; + } - @SoftImplement("forge") - public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 5; - } + @SoftImplement("forge") + public int getFireSpreadSpeed( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 5; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexTrapdoor.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexTrapdoor.java index 3e2620c59b..2c3a2a91c3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexTrapdoor.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexTrapdoor.java @@ -9,22 +9,25 @@ import net.minecraft.world.level.block.state.BlockState; public class BlockHexTrapdoor extends TrapDoorBlock { - public BlockHexTrapdoor(Properties $$0) { - super($$0, HexBlockSetTypes.EDIFIED_WOOD); - } + public BlockHexTrapdoor(Properties $$0) { + super($$0, HexBlockSetTypes.EDIFIED_WOOD); + } - @SoftImplement("forge") - public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return true; - } + @SoftImplement("forge") + public boolean isFlammable( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return true; + } - @SoftImplement("forge") - public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 20; - } + @SoftImplement("forge") + public int getFlammability( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 20; + } - @SoftImplement("forge") - public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 5; - } + @SoftImplement("forge") + public int getFireSpreadSpeed( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 5; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexWoodButton.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexWoodButton.java index 355f9edb9a..64e7c63bc6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexWoodButton.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockHexWoodButton.java @@ -9,23 +9,25 @@ import net.minecraft.world.level.block.state.properties.BlockSetType; public class BlockHexWoodButton extends ButtonBlock { - public BlockHexWoodButton(Properties $$0) { - super($$0, BlockSetType.DARK_OAK, 30, true); - } + public BlockHexWoodButton(Properties $$0) { + super($$0, BlockSetType.DARK_OAK, 30, true); + } + @SoftImplement("forge") + public boolean isFlammable( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return true; + } - @SoftImplement("forge") - public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return true; - } + @SoftImplement("forge") + public int getFlammability( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 20; + } - @SoftImplement("forge") - public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 20; - } - - @SoftImplement("forge") - public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { - return 5; - } + @SoftImplement("forge") + public int getFireSpreadSpeed( + BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 5; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockSconce.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockSconce.java index 8a6ff2b986..d1da7a91ba 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockSconce.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/decoration/BlockSconce.java @@ -3,11 +3,11 @@ import at.petrak.hexcasting.common.particles.ConjureParticleOptions; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.tags.FluidTags; -import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; +import net.minecraft.tags.FluidTags; import net.minecraft.util.RandomSource; +import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; @@ -16,107 +16,123 @@ import net.minecraft.world.level.block.SimpleWaterloggedBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.*; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.DirectionProperty; -import net.minecraft.world.level.block.state.properties.*; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.Fluids; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; public class BlockSconce extends AmethystBlock implements SimpleWaterloggedBlock { - public static final DirectionProperty FACING = BlockStateProperties.FACING; - public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; - protected static VoxelShape AABB_UP = Block.box(4, 0, 4, 12, 1, 12); - protected static VoxelShape AABB_DOWN = Block.box(4, 15, 4, 12, 16, 12); - protected static VoxelShape AABB_NORTH = Block.box(4, 4, 15, 12, 12, 16); - protected static VoxelShape AABB_SOUTH = Block.box(4, 4, 0, 12, 12, 1); - protected static VoxelShape AABB_WEST = Block.box(15, 4, 4, 16, 12, 12); - protected static VoxelShape AABB_EAST = Block.box(0, 4, 4, 1, 12, 12); + public static final DirectionProperty FACING = BlockStateProperties.FACING; + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + protected static VoxelShape AABB_UP = Block.box(4, 0, 4, 12, 1, 12); + protected static VoxelShape AABB_DOWN = Block.box(4, 15, 4, 12, 16, 12); + protected static VoxelShape AABB_NORTH = Block.box(4, 4, 15, 12, 12, 16); + protected static VoxelShape AABB_SOUTH = Block.box(4, 4, 0, 12, 12, 1); + protected static VoxelShape AABB_WEST = Block.box(15, 4, 4, 16, 12, 12); + protected static VoxelShape AABB_EAST = Block.box(0, 4, 4, 1, 12, 12); + + public BlockSconce(Properties p_49795_) { + super(p_49795_); + this.registerDefaultState( + this.stateDefinition.any().setValue(WATERLOGGED, false).setValue(FACING, Direction.UP)); + } + + @Override + public FluidState getFluidState(BlockState state) { + return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } - public BlockSconce(Properties p_49795_) { - super(p_49795_); - this.registerDefaultState(this.stateDefinition.any() - .setValue(WATERLOGGED, false).setValue(FACING, Direction.UP)); - } + @Override + public VoxelShape getShape( + BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + return switch (pState.getValue(FACING)) { + case UP -> AABB_UP; + case DOWN -> AABB_DOWN; + case NORTH -> AABB_NORTH; + case EAST -> AABB_EAST; + case SOUTH -> AABB_SOUTH; + case WEST -> AABB_WEST; + }; + } - @Override - public FluidState getFluidState(BlockState state) { - return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); - } + @Override + protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { + super.createBlockStateDefinition(builder); + builder.add(FACING, WATERLOGGED); + } - @Override - public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { - return switch (pState.getValue(FACING)) { - case UP -> AABB_UP; - case DOWN -> AABB_DOWN; - case NORTH -> AABB_NORTH; - case EAST -> AABB_EAST; - case SOUTH -> AABB_SOUTH; - case WEST -> AABB_WEST; - }; - } + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + FluidState fluidState = pContext.getLevel().getFluidState(pContext.getClickedPos()); + BlockState blockstate; + blockstate = this.defaultBlockState().setValue(FACING, pContext.getClickedFace()); + blockstate = + blockstate.setValue( + WATERLOGGED, fluidState.is(FluidTags.WATER) && fluidState.getAmount() == 8); + return blockstate; + } - @Override - protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { - super.createBlockStateDefinition(builder); - builder.add(FACING, WATERLOGGED); - } + @Override + public BlockState updateShape( + BlockState pState, + Direction pFacing, + BlockState pFacingState, + LevelAccessor pLevel, + BlockPos pCurrentPos, + BlockPos pFacingPos) { + if (pState.getValue(WATERLOGGED)) { + pLevel.scheduleTick(pCurrentPos, Fluids.WATER, Fluids.WATER.getTickDelay(pLevel)); + } - @Override - public BlockState getStateForPlacement(BlockPlaceContext pContext) { - FluidState fluidState = pContext.getLevel().getFluidState(pContext.getClickedPos()); - BlockState blockstate; - blockstate = this.defaultBlockState().setValue(FACING, pContext.getClickedFace()); - blockstate = blockstate.setValue(WATERLOGGED, - fluidState.is(FluidTags.WATER) && fluidState.getAmount() == 8); - return blockstate; - } - - @Override - public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, - BlockPos pCurrentPos, BlockPos pFacingPos) { - if (pState.getValue(WATERLOGGED)) { - pLevel.scheduleTick(pCurrentPos, Fluids.WATER, Fluids.WATER.getTickDelay(pLevel)); - } + return super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos); + } - return super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos); - } + @Override + public void animateTick(BlockState pState, Level pLevel, BlockPos pPos, RandomSource rand) { + if (rand.nextFloat() < 0.8f) { + var cx = pPos.getX() + 0.5; + var cy = pPos.getY() + 0.5; + var cz = pPos.getZ() + 0.5; + // values for particle direction randomization + // x + var dX = + switch (pState.getValue(FACING)) { + case EAST -> rand.triangle(0.01f, 0.05f); + case WEST -> rand.triangle(-0.01f, -0.05f); + default -> rand.triangle(-0.01f, 0.01f); + }; + // y + var dY = + switch (pState.getValue(FACING)) { + case UP -> rand.triangle(0.01f, 0.05f); + case DOWN -> rand.triangle(-0.01f, -0.05f); + default -> rand.triangle(-0.01f, 0.01f); + }; + // z + var dZ = + switch (pState.getValue(FACING)) { + case SOUTH -> rand.triangle(0.01f, 0.05f); + case NORTH -> rand.triangle(-0.01f, -0.05f); + default -> rand.triangle(-0.01f, 0.01f); + }; + int[] colors = {0xff_6f4fab, 0xff_b38ef3, 0xff_cfa0f3, 0xff_cfa0f3, 0xff_fffdd5}; + pLevel.addParticle( + new ConjureParticleOptions(colors[rand.nextInt(colors.length)]), cx, cy, cz, dX, dY, dZ); - @Override - public void animateTick(BlockState pState, Level pLevel, BlockPos pPos, RandomSource rand) { - if (rand.nextFloat() < 0.8f) { - var cx = pPos.getX() + 0.5; - var cy = pPos.getY() + 0.5; - var cz = pPos.getZ() + 0.5; - //values for particle direction randomization - //x - var dX = switch(pState.getValue(FACING)){ - case EAST -> rand.triangle(0.01f, 0.05f); - case WEST -> rand.triangle(-0.01f, -0.05f); - default -> rand.triangle(-0.01f, 0.01f); - }; - //y - var dY = switch(pState.getValue(FACING)){ - case UP -> rand.triangle(0.01f, 0.05f); - case DOWN -> rand.triangle(-0.01f, -0.05f); - default -> rand.triangle(-0.01f, 0.01f); - }; - //z - var dZ = switch(pState.getValue(FACING)){ - case SOUTH -> rand.triangle(0.01f, 0.05f); - case NORTH -> rand.triangle(-0.01f, -0.05f); - default -> rand.triangle(-0.01f, 0.01f); - }; - int[] colors = {0xff_6f4fab, 0xff_b38ef3, 0xff_cfa0f3, 0xff_cfa0f3, 0xff_fffdd5}; - pLevel.addParticle(new ConjureParticleOptions(colors[rand.nextInt(colors.length)]), cx, cy, cz, - dX, dY, dZ); - - if (rand.nextFloat() < 0.08f) { - pLevel.playLocalSound(cx, cy, cz, - SoundEvents.AMETHYST_BLOCK_CHIME, SoundSource.BLOCKS, 1.0F, - 0.5F + rand.nextFloat() * 1.2F, false); - } - } - } + if (rand.nextFloat() < 0.08f) { + pLevel.playLocalSound( + cx, + cy, + cz, + SoundEvents.AMETHYST_BLOCK_CHIME, + SoundSource.BLOCKS, + 1.0F, + 0.5F + rand.nextFloat() * 1.2F, + false); + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/entity/BlockEntityConjured.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/entity/BlockEntityConjured.java index 5ac5004b91..cd6e32befb 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/entity/BlockEntityConjured.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/entity/BlockEntityConjured.java @@ -6,104 +6,124 @@ import at.petrak.hexcasting.common.blocks.BlockConjuredLight; import at.petrak.hexcasting.common.lib.HexBlockEntities; import at.petrak.hexcasting.common.particles.ConjureParticleOptions; +import java.util.Random; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; -import java.util.Random; - public class BlockEntityConjured extends HexBlockEntity { - private static final Random RANDOM = new Random(); - private FrozenPigment colorizer = FrozenPigment.DEFAULT.get(); + private static final Random RANDOM = new Random(); + private FrozenPigment colorizer = FrozenPigment.DEFAULT.get(); - public static final String TAG_COLORIZER = "tag_colorizer"; + public static final String TAG_COLORIZER = "tag_colorizer"; - public BlockEntityConjured(BlockPos pos, BlockState state) { - super(HexBlockEntities.CONJURED_TILE, pos, state); - } + public BlockEntityConjured(BlockPos pos, BlockState state) { + super(HexBlockEntities.CONJURED_TILE, pos, state); + } - public void walkParticle(Entity pEntity) { - if (getBlockState().getBlock() instanceof BlockConjured conjured && !(conjured instanceof BlockConjuredLight)) { - var colProvider = this.colorizer.getColorProvider(); - for (int i = 0; i < 3; ++i) { - int color = colProvider.getColor(pEntity.tickCount, pEntity.position() - .add(new Vec3(RANDOM.nextFloat(), RANDOM.nextFloat(), RANDOM.nextFloat()).scale( - RANDOM.nextFloat() * 3))); - assert level != null; - level.addParticle(new ConjureParticleOptions(color), - pEntity.getX() + (RANDOM.nextFloat() * 0.6D) - 0.3D, - getBlockPos().getY() + (RANDOM.nextFloat() * 0.05D) + 0.95D, - pEntity.getZ() + (RANDOM.nextFloat() * 0.6D) - 0.3D, - RANDOM.nextFloat(-0.02f, 0.02f), - RANDOM.nextFloat(0.02f), - RANDOM.nextFloat(-0.02f, 0.02f)); - } - } - } + public void walkParticle(Entity pEntity) { + if (getBlockState().getBlock() instanceof BlockConjured conjured + && !(conjured instanceof BlockConjuredLight)) { + var colProvider = this.colorizer.getColorProvider(); + for (int i = 0; i < 3; ++i) { + int color = + colProvider.getColor( + pEntity.tickCount, + pEntity + .position() + .add( + new Vec3(RANDOM.nextFloat(), RANDOM.nextFloat(), RANDOM.nextFloat()) + .scale(RANDOM.nextFloat() * 3))); + assert level != null; + level.addParticle( + new ConjureParticleOptions(color), + pEntity.getX() + (RANDOM.nextFloat() * 0.6D) - 0.3D, + getBlockPos().getY() + (RANDOM.nextFloat() * 0.05D) + 0.95D, + pEntity.getZ() + (RANDOM.nextFloat() * 0.6D) - 0.3D, + RANDOM.nextFloat(-0.02f, 0.02f), + RANDOM.nextFloat(0.02f), + RANDOM.nextFloat(-0.02f, 0.02f)); + } + } + } - public void particleEffect() { - if (getBlockState().getBlock() instanceof BlockConjured) { - int color = this.colorizer.getColorProvider().getColor(RANDOM.nextFloat() * 16384, - new Vec3(RANDOM.nextFloat(), RANDOM.nextFloat(), RANDOM.nextFloat()).scale( - RANDOM.nextFloat() * 3)); - assert level != null; - if (getBlockState().getBlock() instanceof BlockConjuredLight) { - if (RANDOM.nextFloat() < 0.5) { - level.addParticle(new ConjureParticleOptions(color), - (double) getBlockPos().getX() + 0.45D + (RANDOM.nextFloat() * 0.1D), - (double) getBlockPos().getY() + 0.45D + (RANDOM.nextFloat() * 0.1D), - (double) getBlockPos().getZ() + 0.45D + (RANDOM.nextFloat() * 0.1D), - RANDOM.nextFloat(-0.005f, 0.005f), - RANDOM.nextFloat(-0.002f, 0.02f), - RANDOM.nextFloat(-0.005f, 0.005f)); - } - } else { - if (RANDOM.nextFloat() < 0.2) { - level.addParticle(new ConjureParticleOptions(color), - (double) getBlockPos().getX() + RANDOM.nextFloat(), - (double) getBlockPos().getY() + RANDOM.nextFloat(), - (double) getBlockPos().getZ() + RANDOM.nextFloat(), - RANDOM.nextFloat(-0.02f, 0.02f), - RANDOM.nextFloat(-0.02f, 0.02f), - RANDOM.nextFloat(-0.02f, 0.02f)); - } - } - } - } + public void particleEffect() { + if (getBlockState().getBlock() instanceof BlockConjured) { + int color = + this.colorizer + .getColorProvider() + .getColor( + RANDOM.nextFloat() * 16384, + new Vec3(RANDOM.nextFloat(), RANDOM.nextFloat(), RANDOM.nextFloat()) + .scale(RANDOM.nextFloat() * 3)); + assert level != null; + if (getBlockState().getBlock() instanceof BlockConjuredLight) { + if (RANDOM.nextFloat() < 0.5) { + level.addParticle( + new ConjureParticleOptions(color), + (double) getBlockPos().getX() + 0.45D + (RANDOM.nextFloat() * 0.1D), + (double) getBlockPos().getY() + 0.45D + (RANDOM.nextFloat() * 0.1D), + (double) getBlockPos().getZ() + 0.45D + (RANDOM.nextFloat() * 0.1D), + RANDOM.nextFloat(-0.005f, 0.005f), + RANDOM.nextFloat(-0.002f, 0.02f), + RANDOM.nextFloat(-0.005f, 0.005f)); + } + } else { + if (RANDOM.nextFloat() < 0.2) { + level.addParticle( + new ConjureParticleOptions(color), + (double) getBlockPos().getX() + RANDOM.nextFloat(), + (double) getBlockPos().getY() + RANDOM.nextFloat(), + (double) getBlockPos().getZ() + RANDOM.nextFloat(), + RANDOM.nextFloat(-0.02f, 0.02f), + RANDOM.nextFloat(-0.02f, 0.02f), + RANDOM.nextFloat(-0.02f, 0.02f)); + } + } + } + } - public void landParticle(Entity entity, int number) { - var colProvider = this.colorizer.getColorProvider(); - for (int i = 0; i < number * 2; i++) { - int color = colProvider.getColor(entity.tickCount, entity.position() - .add(new Vec3(RANDOM.nextFloat(), RANDOM.nextFloat(), RANDOM.nextFloat()).scale( - RANDOM.nextFloat() * 3))); - assert level != null; - level.addParticle(new ConjureParticleOptions(color), - entity.getX() + (RANDOM.nextFloat() * 0.8D) - 0.2D, - getBlockPos().getY() + (RANDOM.nextFloat() * 0.05D) + 0.95D, - entity.getZ() + (RANDOM.nextFloat() * 0.8D) - 0.2D, - 0.0, 0.0, 0.0); - } - } + public void landParticle(Entity entity, int number) { + var colProvider = this.colorizer.getColorProvider(); + for (int i = 0; i < number * 2; i++) { + int color = + colProvider.getColor( + entity.tickCount, + entity + .position() + .add( + new Vec3(RANDOM.nextFloat(), RANDOM.nextFloat(), RANDOM.nextFloat()) + .scale(RANDOM.nextFloat() * 3))); + assert level != null; + level.addParticle( + new ConjureParticleOptions(color), + entity.getX() + (RANDOM.nextFloat() * 0.8D) - 0.2D, + getBlockPos().getY() + (RANDOM.nextFloat() * 0.05D) + 0.95D, + entity.getZ() + (RANDOM.nextFloat() * 0.8D) - 0.2D, + 0.0, + 0.0, + 0.0); + } + } - @Override - protected void saveModData(CompoundTag tag) { - tag.put(TAG_COLORIZER, this.colorizer.serializeToNBT()); - } + @Override + protected void saveModData(CompoundTag tag) { + tag.put(TAG_COLORIZER, this.colorizer.serializeToNBT()); + } - @Override - protected void loadModData(CompoundTag tag) { - this.colorizer = FrozenPigment.fromNBT(tag.getCompound(TAG_COLORIZER)); - } + @Override + protected void loadModData(CompoundTag tag) { + this.colorizer = FrozenPigment.fromNBT(tag.getCompound(TAG_COLORIZER)); + } - public FrozenPigment getColorizer() { - return this.colorizer; - } + public FrozenPigment getColorizer() { + return this.colorizer; + } - public void setColorizer(FrozenPigment colorizer) { - this.colorizer = colorizer; - this.sync(); - } + public void setColorizer(FrozenPigment colorizer) { + this.colorizer = colorizer; + this.sync(); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/entity/BlockEntityQuenchedAllay.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/entity/BlockEntityQuenchedAllay.java index dac5512a58..6e7cae9de8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/entity/BlockEntityQuenchedAllay.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/entity/BlockEntityQuenchedAllay.java @@ -3,31 +3,25 @@ import at.petrak.hexcasting.api.block.HexBlockEntity; import at.petrak.hexcasting.common.blocks.BlockQuenchedAllay; import at.petrak.hexcasting.common.lib.HexBlockEntities; +import java.util.function.BiFunction; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.block.state.BlockState; -import java.util.function.BiFunction; - -/** - * No-op BE just to have a BER - */ +/** No-op BE just to have a BER */ public class BlockEntityQuenchedAllay extends HexBlockEntity { - public BlockEntityQuenchedAllay(BlockQuenchedAllay block, BlockPos pos, BlockState blockState) { - super(HexBlockEntities.typeForQuenchedAllay(block), pos, blockState); - } - - public static BiFunction<BlockPos, BlockState, BlockEntityQuenchedAllay> fromKnownBlock(BlockQuenchedAllay block) { - return (pos, state) -> new BlockEntityQuenchedAllay(block, pos, state); - } - - @Override - protected void saveModData(CompoundTag tag) { + public BlockEntityQuenchedAllay(BlockQuenchedAllay block, BlockPos pos, BlockState blockState) { + super(HexBlockEntities.typeForQuenchedAllay(block), pos, blockState); + } - } + public static BiFunction<BlockPos, BlockState, BlockEntityQuenchedAllay> fromKnownBlock( + BlockQuenchedAllay block) { + return (pos, state) -> new BlockEntityQuenchedAllay(block, pos, state); + } - @Override - protected void loadModData(CompoundTag tag) { + @Override + protected void saveModData(CompoundTag tag) {} - } + @Override + protected void loadModData(CompoundTag tag) {} } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/PatternRegistryManifest.java b/Common/src/main/java/at/petrak/hexcasting/common/casting/PatternRegistryManifest.java index 66199bfba1..0cf134455d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/PatternRegistryManifest.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/PatternRegistryManifest.java @@ -12,122 +12,126 @@ import at.petrak.hexcasting.server.ScrungledPatternsSave; import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.mojang.datafixers.util.Pair; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; import org.apache.commons.lang3.NotImplementedException; import org.jetbrains.annotations.Nullable; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - // Now an internal-only class used to do final processing on the registered stuff public class PatternRegistryManifest { - private static final ConcurrentMap<List<HexAngle>, ResourceKey<ActionRegistryEntry>> NORMAL_ACTION_LOOKUP = - new ConcurrentHashMap<>(); - - /** - * Process the registry! - * <p> - * This no longer checks any kind of per-world-pattern-ness because both this and ScrungledPatternsSave depends on - * the other to be done first. lol lmao. It just caches signature->action for the non-per-world-pats - * so it's an O(1) lookup. - */ - // TODO i just realized that logically, this should not be run every time the client/server connects - // just run it on startup, the info gathered here i think is static per world ... except for the per-worldies - // that need to be recalced... - // - // Client is passed in currently for no reason, again will be required for shape-matching - public static void processRegistry(@Nullable ServerLevel overworld) { - int perWorldActionCount = 0; - - var registry = IXplatAbstractions.INSTANCE.getActionRegistry(); - for (var key : registry.registryKeySet()) { - var entry = registry.get(key); - if (entry == null) - continue; - - if (!HexUtils.isOfTag(registry, key, HexTags.Actions.PER_WORLD_PATTERN)) { - var old = NORMAL_ACTION_LOOKUP.put(entry.prototype().getAngles(), key); - if (old != null) { - HexAPI.LOGGER.warn("Inserted %s which has same signature as %s, overriding it.".formatted(key, old)); - } - } else { - perWorldActionCount++; - } - } - - HexAPI.LOGGER.info(("We're on the %s! " + - "Loaded %d regular actions, %d per-world actions, and %d special handlers").formatted( - (overworld == null) ? "client" : "server", NORMAL_ACTION_LOOKUP.size(), perWorldActionCount, - IXplatAbstractions.INSTANCE.getSpecialHandlerRegistry().size() - )); - } - - /** - * Try to match this pattern to a special handler. If one is found, return both the handler and its key. - */ - @Nullable - public static Pair<SpecialHandler, ResourceKey<SpecialHandler.Factory<?>>> matchPatternToSpecialHandler(HexPattern pat, CastingEnvironment environment) { - var registry = IXplatAbstractions.INSTANCE.getSpecialHandlerRegistry(); - for (var key : registry.registryKeySet()) { - var factory = registry.get(key); - if (factory == null) - continue; - var handler = factory.tryMatch(pat,environment); - if (handler != null) { - return Pair.of(handler, key); - } - } - return null; - } - - /** - * Try to match this pattern to an action, whether via a normal pattern, a per-world pattern, or the machinations - * of a special handler. - * - * @param checkForAlternateStrokeOrders if this is true, will check if the pattern given is an erroneous stroke - * order - * for a per-world pattern. - */ - public static PatternShapeMatch matchPattern(HexPattern pat, CastingEnvironment environment, - boolean checkForAlternateStrokeOrders) { - // I am PURPOSELY checking normal actions before special handlers - // This way we don't get a repeat of the phial number literal incident - var sig = pat.getAngles(); - if (NORMAL_ACTION_LOOKUP.containsKey(sig)) { - var key = NORMAL_ACTION_LOOKUP.get(sig); - return new PatternShapeMatch.Normal(key); - } - - // Look it up in the world? - var perWorldPatterns = ScrungledPatternsSave.open(environment.getWorld().getServer().overworld()); - var entry = perWorldPatterns.lookup(pat.anglesSignature()); - if (entry != null) { - return new PatternShapeMatch.PerWorld(entry.key(), true); - } - - if (checkForAlternateStrokeOrders) { - throw new NotImplementedException("checking for alternate stroke orders is NYI sorry"); - } - - var shMatch = matchPatternToSpecialHandler(pat, environment); - if (shMatch != null) { - return new PatternShapeMatch.Special(shMatch.getSecond(), shMatch.getFirst()); - } - - return new PatternShapeMatch.Nothing(); - } - - @Nullable - public static HexPattern getCanonicalStrokesPerWorld(ResourceKey<ActionRegistryEntry> key, ServerLevel overworld) { - var perWorldPatterns = ScrungledPatternsSave.open(overworld); - - var pair = perWorldPatterns.lookupReverse(key); - if (pair == null) return null; - - var sig = pair.getFirst(); - var entry = pair.getSecond(); - return HexPattern.fromAngles(sig, entry.canonicalStartDir()); - } + private static final ConcurrentMap<List<HexAngle>, ResourceKey<ActionRegistryEntry>> + NORMAL_ACTION_LOOKUP = new ConcurrentHashMap<>(); + + /** + * Process the registry! + * + * <p>This no longer checks any kind of per-world-pattern-ness because both this and + * ScrungledPatternsSave depends on the other to be done first. lol lmao. It just caches + * signature->action for the non-per-world-pats so it's an O(1) lookup. + */ + // TODO i just realized that logically, this should not be run every time the client/server + // connects + // just run it on startup, the info gathered here i think is static per world ... except for the + // per-worldies + // that need to be recalced... + // + // Client is passed in currently for no reason, again will be required for shape-matching + public static void processRegistry(@Nullable ServerLevel overworld) { + int perWorldActionCount = 0; + + var registry = IXplatAbstractions.INSTANCE.getActionRegistry(); + for (var key : registry.registryKeySet()) { + var entry = registry.get(key); + if (entry == null) continue; + + if (!HexUtils.isOfTag(registry, key, HexTags.Actions.PER_WORLD_PATTERN)) { + var old = NORMAL_ACTION_LOOKUP.put(entry.prototype().getAngles(), key); + if (old != null) { + HexAPI.LOGGER.warn( + "Inserted %s which has same signature as %s, overriding it.".formatted(key, old)); + } + } else { + perWorldActionCount++; + } + } + + HexAPI.LOGGER.info( + ("We're on the %s! " + + "Loaded %d regular actions, %d per-world actions, and %d special handlers") + .formatted( + (overworld == null) ? "client" : "server", + NORMAL_ACTION_LOOKUP.size(), + perWorldActionCount, + IXplatAbstractions.INSTANCE.getSpecialHandlerRegistry().size())); + } + + /** + * Try to match this pattern to a special handler. If one is found, return both the handler and + * its key. + */ + @Nullable public static Pair<SpecialHandler, ResourceKey<SpecialHandler.Factory<?>>> + matchPatternToSpecialHandler(HexPattern pat, CastingEnvironment environment) { + var registry = IXplatAbstractions.INSTANCE.getSpecialHandlerRegistry(); + for (var key : registry.registryKeySet()) { + var factory = registry.get(key); + if (factory == null) continue; + var handler = factory.tryMatch(pat, environment); + if (handler != null) { + return Pair.of(handler, key); + } + } + return null; + } + + /** + * Try to match this pattern to an action, whether via a normal pattern, a per-world pattern, or + * the machinations of a special handler. + * + * @param checkForAlternateStrokeOrders if this is true, will check if the pattern given is an + * erroneous stroke order for a per-world pattern. + */ + public static PatternShapeMatch matchPattern( + HexPattern pat, CastingEnvironment environment, boolean checkForAlternateStrokeOrders) { + // I am PURPOSELY checking normal actions before special handlers + // This way we don't get a repeat of the phial number literal incident + var sig = pat.getAngles(); + if (NORMAL_ACTION_LOOKUP.containsKey(sig)) { + var key = NORMAL_ACTION_LOOKUP.get(sig); + return new PatternShapeMatch.Normal(key); + } + + // Look it up in the world? + var perWorldPatterns = + ScrungledPatternsSave.open(environment.getWorld().getServer().overworld()); + var entry = perWorldPatterns.lookup(pat.anglesSignature()); + if (entry != null) { + return new PatternShapeMatch.PerWorld(entry.key(), true); + } + + if (checkForAlternateStrokeOrders) { + throw new NotImplementedException("checking for alternate stroke orders is NYI sorry"); + } + + var shMatch = matchPatternToSpecialHandler(pat, environment); + if (shMatch != null) { + return new PatternShapeMatch.Special(shMatch.getSecond(), shMatch.getFirst()); + } + + return new PatternShapeMatch.Nothing(); + } + + @Nullable public static HexPattern getCanonicalStrokesPerWorld( + ResourceKey<ActionRegistryEntry> key, ServerLevel overworld) { + var perWorldPatterns = ScrungledPatternsSave.open(overworld); + + var pair = perWorldPatterns.lookupReverse(key); + if (pair == null) return null; + + var sig = pair.getFirst(); + var entry = pair.getSecond(); + return HexPattern.fromAngles(sig, entry.canonicalStartDir()); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityHeight.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityHeight.kt index eea382d0e4..17d710ae07 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityHeight.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityHeight.kt @@ -7,11 +7,11 @@ import at.petrak.hexcasting.api.casting.getEntity import at.petrak.hexcasting.api.casting.iota.Iota object OpEntityHeight : ConstMediaAction { - override val argc = 1 + override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val e = args.getEntity(0, argc) - env.assertEntityInRange(e) - return e.bbHeight.asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val e = args.getEntity(0, argc) + env.assertEntityInRange(e) + return e.bbHeight.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityLook.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityLook.kt index 14faec64eb..13ede10cc4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityLook.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityLook.kt @@ -7,11 +7,11 @@ import at.petrak.hexcasting.api.casting.getEntity import at.petrak.hexcasting.api.casting.iota.Iota object OpEntityLook : ConstMediaAction { - override val argc = 1 + override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val e = args.getEntity(0, argc) - env.assertEntityInRange(e) - return e.lookAngle.asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val e = args.getEntity(0, argc) + env.assertEntityInRange(e) + return e.lookAngle.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityPos.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityPos.kt index 80ab0e23f0..02d8dc8f06 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityPos.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityPos.kt @@ -7,11 +7,11 @@ import at.petrak.hexcasting.api.casting.getEntity import at.petrak.hexcasting.api.casting.iota.Iota class OpEntityPos(val feet: Boolean) : ConstMediaAction { - override val argc = 1 + override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val e = args.getEntity(0, argc) - env.assertEntityInRange(e) - return (if (this.feet) e.position() else e.eyePosition).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val e = args.getEntity(0, argc) + env.assertEntityInRange(e) + return (if (this.feet) e.position() else e.eyePosition).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityVelocity.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityVelocity.kt index b1b7330969..1bb30923da 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityVelocity.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityVelocity.kt @@ -8,13 +8,13 @@ import at.petrak.hexcasting.api.casting.getEntity import at.petrak.hexcasting.api.casting.iota.Iota object OpEntityVelocity : ConstMediaAction { - override val argc = 1 + override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val e = args.getEntity(0, argc) - env.assertEntityInRange(e) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val e = args.getEntity(0, argc) + env.assertEntityInRange(e) - val vel = HexAPI.instance().getEntityVelocitySpecial(e) - return vel.asActionResult - } + val vel = HexAPI.instance().getEntityVelocitySpecial(e) + return vel.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicRead.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicRead.kt index 34a28f0d26..aeea6eed0d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicRead.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicRead.kt @@ -11,19 +11,19 @@ import at.petrak.hexcasting.api.misc.MediaConstants import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicRecord object OpAkashicRead : ConstMediaAction { - override val argc = 2 - override val mediaCost: Long = MediaConstants.DUST_UNIT + override val argc = 2 + override val mediaCost: Long = MediaConstants.DUST_UNIT - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val pos = args.getBlockPos(0, argc) - val key = args.getPattern(1, argc) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val pos = args.getBlockPos(0, argc) + val key = args.getPattern(1, argc) - val record = env.world.getBlockState(pos).block - if (record !is BlockAkashicRecord) { - throw MishapNoAkashicRecord(pos) - } + val record = env.world.getBlockState(pos).block + if (record !is BlockAkashicRecord) { + throw MishapNoAkashicRecord(pos) + } - val datum = record.lookupPattern(pos, key, env.world) - return listOf(datum ?: NullIota()) - } + val datum = record.lookupPattern(pos, key, env.world) + return listOf(datum ?: NullIota()) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicWrite.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicWrite.kt index 2089965835..5f40fb225e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicWrite.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicWrite.kt @@ -17,55 +17,43 @@ import net.minecraft.server.level.ServerPlayer import net.minecraft.sounds.SoundSource object OpAkashicWrite : SpellAction { - override val argc = 3 - - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val pos = args.getBlockPos(0, argc) - val key = args.getPattern(1, argc) - val datum = args.get(2) - - env.assertPosInRange(pos) - - val record = env.world.getBlockState(pos).block - if (record !is BlockAkashicRecord) { - throw MishapNoAkashicRecord(pos) - } - - val trueName = MishapOthersName.getTrueNameFromDatum(datum, env.castingEntity as? ServerPlayer) - if (trueName != null) - throw MishapOthersName(trueName) - - return SpellAction.Result( - Spell(record, pos, key, datum), - MediaConstants.DUST_UNIT, - listOf() - ) - } - - private data class Spell( - val record: BlockAkashicRecord, - val recordPos: BlockPos, - val key: HexPattern, - val datum: Iota - ) : - RenderedSpell { - override fun cast(env: CastingEnvironment) { - record.addNewDatum(recordPos, env.world, key, datum) - - env.world.playSound( - null, recordPos, HexSounds.SCROLL_SCRIBBLE, SoundSource.BLOCKS, - 1f, 0.8f - ) - - // val colorizer = HexPlayerDataHelper.getColorizer(ctx.caster) - // val normal = record.blockState.getValue(BlockAkashicBookshelf.FACING).normal - // ParticleSpray( - // Vec3.atCenterOf(record.blockPos), Vec3.atBottomCenterOf(normal), - // 0.5, Math.PI / 4, 10 - // ).sprayParticles(ctx.world, colorizer) - } - } + override val argc = 3 + + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val pos = args.getBlockPos(0, argc) + val key = args.getPattern(1, argc) + val datum = args.get(2) + + env.assertPosInRange(pos) + + val record = env.world.getBlockState(pos).block + if (record !is BlockAkashicRecord) { + throw MishapNoAkashicRecord(pos) + } + + val trueName = MishapOthersName.getTrueNameFromDatum(datum, env.castingEntity as? ServerPlayer) + if (trueName != null) throw MishapOthersName(trueName) + + return SpellAction.Result(Spell(record, pos, key, datum), MediaConstants.DUST_UNIT, listOf()) + } + + private data class Spell( + val record: BlockAkashicRecord, + val recordPos: BlockPos, + val key: HexPattern, + val datum: Iota + ) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + record.addNewDatum(recordPos, env.world, key, datum) + + env.world.playSound(null, recordPos, HexSounds.SCROLL_SCRIBBLE, SoundSource.BLOCKS, 1f, 0.8f) + + // val colorizer = HexPlayerDataHelper.getColorizer(ctx.caster) + // val normal = record.blockState.getValue(BlockAkashicBookshelf.FACING).normal + // ParticleSpray( + // Vec3.atCenterOf(record.blockPos), Vec3.atBottomCenterOf(normal), + // 0.5, Math.PI / 4, 10 + // ).sprayParticles(ctx.world, colorizer) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/circles/OpCircleBounds.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/circles/OpCircleBounds.kt index 777ff834f0..74dee5137f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/circles/OpCircleBounds.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/circles/OpCircleBounds.kt @@ -9,18 +9,17 @@ import at.petrak.hexcasting.api.casting.mishaps.circle.MishapNoSpellCircle import net.minecraft.world.phys.Vec3 class OpCircleBounds(val max: Boolean) : ConstMediaAction { - override val argc = 0 + override val argc = 0 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - if (env !is CircleCastEnv) - throw MishapNoSpellCircle() - val circle = env.impetus ?: throw MishapNoSpellCircle() + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + if (env !is CircleCastEnv) throw MishapNoSpellCircle() + val circle = env.impetus ?: throw MishapNoSpellCircle() - val aabb = circle.executionState!!.bounds // the circle should have an execution state since it's executing this. + val aabb = + circle.executionState!! + .bounds // the circle should have an execution state since it's executing this. - return if (max) - Vec3(aabb.maxX - 0.5, aabb.maxY - 0.5, aabb.maxZ - 0.5).asActionResult - else - Vec3(aabb.minX + 0.5, aabb.minY + 0.5, aabb.minZ + 0.5).asActionResult - } + return if (max) Vec3(aabb.maxX - 0.5, aabb.maxY - 0.5, aabb.maxZ - 0.5).asActionResult + else Vec3(aabb.minX + 0.5, aabb.minY + 0.5, aabb.minZ + 0.5).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/circles/OpImpetusDir.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/circles/OpImpetusDir.kt index cb231bb416..ba2f6d9f73 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/circles/OpImpetusDir.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/circles/OpImpetusDir.kt @@ -7,17 +7,18 @@ import at.petrak.hexcasting.api.casting.eval.env.CircleCastEnv import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.mishaps.circle.MishapNoSpellCircle -// TODO: we now have the interesting potential to add *other* spell circle getters, like the current position +// TODO: we now have the interesting potential to add *other* spell circle getters, like the current +// position // of the eval. Hmm hm hm. -// Reminded of "targeted position" in Psi -- we could have a "cast location" refl that gets the player pos +// Reminded of "targeted position" in Psi -- we could have a "cast location" refl that gets the +// player pos // or the current eval pos on a circle object OpImpetusDir : ConstMediaAction { - override val argc = 0 + override val argc = 0 - override fun execute(args: List<Iota>, ctx: CastingEnvironment): List<Iota> { - if (ctx !is CircleCastEnv) - throw MishapNoSpellCircle() + override fun execute(args: List<Iota>, ctx: CastingEnvironment): List<Iota> { + if (ctx !is CircleCastEnv) throw MishapNoSpellCircle() - return ctx.circleState().impetusDir.step().asActionResult - } + return ctx.circleState().impetusDir.step().asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/circles/OpImpetusPos.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/circles/OpImpetusPos.kt index d1ca443041..b2e07ab9b0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/circles/OpImpetusPos.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/circles/OpImpetusPos.kt @@ -8,12 +8,11 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.mishaps.circle.MishapNoSpellCircle object OpImpetusPos : ConstMediaAction { - override val argc = 0 + override val argc = 0 - override fun execute(args: List<Iota>, ctx: CastingEnvironment): List<Iota> { - if (ctx !is CircleCastEnv) - throw MishapNoSpellCircle() + override fun execute(args: List<Iota>, ctx: CastingEnvironment): List<Iota> { + if (ctx !is CircleCastEnv) throw MishapNoSpellCircle() - return ctx.circleState().impetusPos.asActionResult - } + return ctx.circleState().impetusPos.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEval.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEval.kt index e9c9adf2a1..4b740ee6ae 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEval.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEval.kt @@ -14,26 +14,39 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpEval : Action { - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() - val iota = stack.removeLastOrNull() ?: throw MishapNotEnoughArgs(1, 0) - return exec(env, image, continuation, stack, iota) - } + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + val stack = image.stack.toMutableList() + val iota = stack.removeLastOrNull() ?: throw MishapNotEnoughArgs(1, 0) + return exec(env, image, continuation, stack, iota) + } - fun exec(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation, newStack: MutableList<Iota>, iota: Iota): OperationResult { - // also, never make a break boundary when evaluating just one pattern - val instrs = evaluatable(iota, 0) - val newCont = - if (instrs.left().isPresent || (continuation is SpellContinuation.NotDone && continuation.frame is FrameFinishEval)) { - continuation - } else { - continuation.pushFrame(FrameFinishEval) // install a break-boundary after eval - } + fun exec( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation, + newStack: MutableList<Iota>, + iota: Iota + ): OperationResult { + // also, never make a break boundary when evaluating just one pattern + val instrs = evaluatable(iota, 0) + val newCont = + if ( + instrs.left().isPresent || + (continuation is SpellContinuation.NotDone && continuation.frame is FrameFinishEval) + ) { + continuation + } else { + continuation.pushFrame(FrameFinishEval) // install a break-boundary after eval + } - val instrsList = instrs.map({ SpellList.LList(0, listOf(it)) }, { it }) - val frame = FrameEvaluate(instrsList, true) + val instrsList = instrs.map({ SpellList.LList(0, listOf(it)) }, { it }) + val frame = FrameEvaluate(instrsList, true) - val image2 = image.withUsedOp().copy(stack = newStack) - return OperationResult(image2, listOf(), newCont.pushFrame(frame), HexEvalSounds.HERMES) - } + val image2 = image.withUsedOp().copy(stack = newStack) + return OperationResult(image2, listOf(), newCont.pushFrame(frame), HexEvalSounds.HERMES) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEvalBreakable.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEvalBreakable.kt index f778d87356..195bf0fbd3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEvalBreakable.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEvalBreakable.kt @@ -9,12 +9,14 @@ import at.petrak.hexcasting.api.casting.iota.ContinuationIota import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs object OpEvalBreakable : Action { - override fun operate(env: CastingEnvironment, - image: CastingImage, - continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() - val iota = stack.removeLastOrNull() ?: throw MishapNotEnoughArgs(1, 0) - stack.add(ContinuationIota(continuation)) - return OpEval.exec(env, image, continuation, stack, iota) - } + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + val stack = image.stack.toMutableList() + val iota = stack.removeLastOrNull() ?: throw MishapNotEnoughArgs(1, 0) + stack.add(ContinuationIota(continuation)) + return OpEval.exec(env, image, continuation, stack, iota) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpForEach.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpForEach.kt index bdd4f76f7a..e3e36a6f72 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpForEach.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpForEach.kt @@ -11,20 +11,23 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpForEach : Action { - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + val stack = image.stack.toMutableList() - if (stack.size < 2) - throw MishapNotEnoughArgs(2, stack.size) + if (stack.size < 2) throw MishapNotEnoughArgs(2, stack.size) - val instrs = stack.getList(stack.lastIndex - 1, stack.size) - val datums = stack.getList(stack.lastIndex, stack.size) - stack.removeLastOrNull() - stack.removeLastOrNull() + val instrs = stack.getList(stack.lastIndex - 1, stack.size) + val datums = stack.getList(stack.lastIndex, stack.size) + stack.removeLastOrNull() + stack.removeLastOrNull() - val frame = FrameForEach(datums, instrs, null, mutableListOf()) - val image2 = image.withUsedOp().copy(stack = stack) + val frame = FrameForEach(datums, instrs, null, mutableListOf()) + val image2 = image.withUsedOp().copy(stack = stack) - return OperationResult(image2, listOf(), continuation.pushFrame(frame), HexEvalSounds.THOTH) - } + return OperationResult(image2, listOf(), continuation.pushFrame(frame), HexEvalSounds.THOTH) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpHalt.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpHalt.kt index 7436c26a0c..c1977eead8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpHalt.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpHalt.kt @@ -8,25 +8,30 @@ import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpHalt : Action { - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - var newStack = image.stack.toList() + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + var newStack = image.stack.toList() - var done = false - var newCont = continuation - while (!done && newCont is SpellContinuation.NotDone) { - // Kotlin Y U NO destructuring assignment - val newInfo = newCont.frame.breakDownwards(newStack) - done = newInfo.first - newStack = newInfo.second - newCont = newCont.next - } - // if we hit no continuation boundaries (i.e. thoth/hermes exits), we've TOTALLY cleared the itinerary... - if (!done) { - // bomb the stack so we exit - newStack = listOf() - } + var done = false + var newCont = continuation + while (!done && newCont is SpellContinuation.NotDone) { + // Kotlin Y U NO destructuring assignment + val newInfo = newCont.frame.breakDownwards(newStack) + done = newInfo.first + newStack = newInfo.second + newCont = newCont.next + } + // if we hit no continuation boundaries (i.e. thoth/hermes exits), we've TOTALLY cleared the + // itinerary... + if (!done) { + // bomb the stack so we exit + newStack = listOf() + } - val image2 = image.withUsedOp().copy(stack = newStack) - return OperationResult(image2, listOf(), newCont, HexEvalSounds.SPELL) - } + val image2 = image.withUsedOp().copy(stack = newStack) + return OperationResult(image2, listOf(), newCont, HexEvalSounds.SPELL) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpThanos.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpThanos.kt index 075fa90a2b..cbfce77794 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpThanos.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpThanos.kt @@ -6,16 +6,19 @@ import at.petrak.hexcasting.api.casting.eval.OperationResult import at.petrak.hexcasting.api.casting.eval.vm.CastingImage import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation import at.petrak.hexcasting.api.casting.iota.DoubleIota -import at.petrak.hexcasting.api.mod.HexConfig import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpThanos : Action { - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val opsLeft = env.maxOpCount() - image.opsConsumed - val stack = image.stack.toMutableList() - stack.add(DoubleIota(opsLeft.toDouble())) + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + val opsLeft = env.maxOpCount() - image.opsConsumed + val stack = image.stack.toMutableList() + stack.add(DoubleIota(opsLeft.toDouble())) - val image2 = image.withUsedOp().copy(stack = stack) - return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) - } -} \ No newline at end of file + val image2 = image.withUsedOp().copy(stack = stack) + return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpAppend.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpAppend.kt index 1834166ee2..e5252e78cd 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpAppend.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpAppend.kt @@ -7,11 +7,12 @@ import at.petrak.hexcasting.api.casting.getList import at.petrak.hexcasting.api.casting.iota.Iota object OpAppend : ConstMediaAction { - override val argc = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val list = args.getList(0, argc).toMutableList() - val datum = args[1] - list.add(datum) - return list.asActionResult - } + override val argc = 2 + + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val list = args.getList(0, argc).toMutableList() + val datum = args[1] + list.add(datum) + return list.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpConcat.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpConcat.kt index 2e77b35673..990b1f0f80 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpConcat.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpConcat.kt @@ -7,11 +7,12 @@ import at.petrak.hexcasting.api.casting.getList import at.petrak.hexcasting.api.casting.iota.Iota object OpConcat : ConstMediaAction { - override val argc = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val lhs = args.getList(0, argc).toMutableList() - val rhs = args.getList(1, argc) - lhs.addAll(rhs) - return lhs.asActionResult - } + override val argc = 2 + + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val lhs = args.getList(0, argc).toMutableList() + val rhs = args.getList(1, argc) + lhs.addAll(rhs) + return lhs.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpCons.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpCons.kt index b0ec3173fc..440d9fd1e2 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpCons.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpCons.kt @@ -8,10 +8,11 @@ import at.petrak.hexcasting.api.casting.getList import at.petrak.hexcasting.api.casting.iota.Iota object OpCons : ConstMediaAction { - override val argc = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val bottom = args.getList(0, argc) - val top = args[1] - return SpellList.LPair(top, bottom).asActionResult - } + override val argc = 2 + + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val bottom = args.getList(0, argc) + val top = args[1] + return SpellList.LPair(top, bottom).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpEmptyList.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpEmptyList.kt index b3c6398128..842934071d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpEmptyList.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpEmptyList.kt @@ -6,8 +6,9 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota object OpEmptyList : ConstMediaAction { - override val argc = 0 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - return emptyList<Iota>().asActionResult // sorry for taking all the easy impls, hudeler - } + override val argc = 0 + + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + return emptyList<Iota>().asActionResult // sorry for taking all the easy impls, hudeler + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpIndex.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpIndex.kt index dacaa022a8..4cdf18e17e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpIndex.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpIndex.kt @@ -9,11 +9,12 @@ import at.petrak.hexcasting.api.casting.iota.NullIota import kotlin.math.roundToInt object OpIndex : ConstMediaAction { - override val argc = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val list = args.getList(0, argc).toMutableList() - val index = args.getDouble(1, argc) - val x = list.getOrElse(index.roundToInt()) { NullIota() } - return listOf(x) - } + override val argc = 2 + + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val list = args.getList(0, argc).toMutableList() + val index = args.getDouble(1, argc) + val x = list.getOrElse(index.roundToInt()) { NullIota() } + return listOf(x) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpIndexOf.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpIndexOf.kt index 98209c9b08..c9f13ac99a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpIndexOf.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpIndexOf.kt @@ -7,12 +7,12 @@ import at.petrak.hexcasting.api.casting.getList import at.petrak.hexcasting.api.casting.iota.Iota object OpIndexOf : ConstMediaAction { - override val argc: Int - get() = 2 + override val argc: Int + get() = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val list = args.getList(0, argc).toMutableList() - val value = args[1] - return list.indexOfFirst { Iota.tolerates(value, it) }.asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val list = args.getList(0, argc).toMutableList() + val value = args[1] + return list.indexOfFirst { Iota.tolerates(value, it) }.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpLastNToList.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpLastNToList.kt index ffd4e3c10a..7db415334a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpLastNToList.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpLastNToList.kt @@ -12,21 +12,24 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpLastNToList : Action { - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + val stack = image.stack.toMutableList() - if (stack.isEmpty()) - throw MishapNotEnoughArgs(1, 0) - val yoinkCount = stack.takeLast(1).getPositiveIntUnderInclusive(0, stack.size - 1) - stack.removeLast() - val output = mutableListOf<Iota>() - output.addAll(stack.takeLast(yoinkCount)) - for (i in 0 until yoinkCount) { - stack.removeLast() - } - stack.addAll(output.asActionResult) + if (stack.isEmpty()) throw MishapNotEnoughArgs(1, 0) + val yoinkCount = stack.takeLast(1).getPositiveIntUnderInclusive(0, stack.size - 1) + stack.removeLast() + val output = mutableListOf<Iota>() + output.addAll(stack.takeLast(yoinkCount)) + for (i in 0 until yoinkCount) { + stack.removeLast() + } + stack.addAll(output.asActionResult) - val image2 = image.withUsedOp().copy(stack = stack) - return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) - } + val image2 = image.withUsedOp().copy(stack = stack) + return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpListSize.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpListSize.kt index 0df98e1653..e1b38578a9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpListSize.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpListSize.kt @@ -8,8 +8,9 @@ import at.petrak.hexcasting.api.casting.iota.Iota // it's still called beancounter's distillation in my heart object OpListSize : ConstMediaAction { - override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - return args.getList(0, argc).toList().size.asActionResult // mmm one-liner - } + override val argc = 1 + + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + return args.getList(0, argc).toList().size.asActionResult // mmm one-liner + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpModifyInPlace.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpModifyInPlace.kt index f54ec91edb..a3888a1146 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpModifyInPlace.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpModifyInPlace.kt @@ -9,11 +9,12 @@ import at.petrak.hexcasting.api.casting.getPositiveIntUnder import at.petrak.hexcasting.api.casting.iota.Iota object OpModifyInPlace : ConstMediaAction { - override val argc = 3 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val list = args.getList(0, argc) - val index = args.getPositiveIntUnder(1, list.size(), argc) - val iota = args[2] - return list.modifyAt(index) { SpellList.LPair(iota, it.cdr) }.asActionResult - } + override val argc = 3 + + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val list = args.getList(0, argc) + val index = args.getPositiveIntUnder(1, list.size(), argc) + val iota = args[2] + return list.modifyAt(index) { SpellList.LPair(iota, it.cdr) }.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpRemove.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpRemove.kt index 586b679eb0..dc5bac2a9b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpRemove.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpRemove.kt @@ -8,15 +8,14 @@ import at.petrak.hexcasting.api.casting.getList import at.petrak.hexcasting.api.casting.iota.Iota object OpRemove : ConstMediaAction { - override val argc: Int - get() = 2 + override val argc: Int + get() = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val list = args.getList(0, argc).toMutableList() - val index = args.getInt(1, argc) - if (index < 0 || index >= list.size) - return list.asActionResult - list.removeAt(index) - return list.asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val list = args.getList(0, argc).toMutableList() + val index = args.getInt(1, argc) + if (index < 0 || index >= list.size) return list.asActionResult + list.removeAt(index) + return list.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpReverski.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpReverski.kt index ffee540359..9c582758dc 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpReverski.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpReverski.kt @@ -7,8 +7,13 @@ import at.petrak.hexcasting.api.casting.getList import at.petrak.hexcasting.api.casting.iota.Iota object OpReverski : ConstMediaAction { - override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - return args.getList(0, argc).toList().asReversed().asActionResult // okay kotlin kinda pogged for this - } + override val argc = 1 + + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + return args + .getList(0, argc) + .toList() + .asReversed() + .asActionResult // okay kotlin kinda pogged for this + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpSingleton.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpSingleton.kt index 41fab11ff4..f647fa7109 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpSingleton.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpSingleton.kt @@ -6,8 +6,9 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota object OpSingleton : ConstMediaAction { - override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - return listOf(args[0]).asActionResult // god i love one-liners - } + override val argc = 1 + + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + return listOf(args[0]).asActionResult // god i love one-liners + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpSlice.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpSlice.kt index f83daf7614..04e899e588 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpSlice.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpSlice.kt @@ -10,15 +10,15 @@ import kotlin.math.max import kotlin.math.min object OpSlice : ConstMediaAction { - override val argc = 3 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val list = args.getList(0, argc).toList() - val index1 = args.getPositiveIntUnderInclusive(1, list.size, argc) - val index2 = args.getPositiveIntUnderInclusive(2, list.size, argc) + override val argc = 3 - if (index1 == index2) - return emptyList<Iota>().asActionResult + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val list = args.getList(0, argc).toList() + val index1 = args.getPositiveIntUnderInclusive(1, list.size, argc) + val index2 = args.getPositiveIntUnderInclusive(2, list.size, argc) - return list.subList(min(index1, index2), max(index1, index2)).asActionResult - } + if (index1 == index2) return emptyList<Iota>().asActionResult + + return list.subList(min(index1, index2), max(index1, index2)).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpSplat.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpSplat.kt index f35f0d8ac3..529f38b18d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpSplat.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpSplat.kt @@ -6,9 +6,9 @@ import at.petrak.hexcasting.api.casting.getList import at.petrak.hexcasting.api.casting.iota.Iota object OpSplat : ConstMediaAction { - override val argc: Int - get() = 1 + override val argc: Int + get() = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> = - args.getList(0, argc).toList() + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> = + args.getList(0, argc).toList() } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpUnCons.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpUnCons.kt index 211e91283d..c34f04159c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpUnCons.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpUnCons.kt @@ -8,12 +8,13 @@ import at.petrak.hexcasting.api.casting.iota.ListIota import at.petrak.hexcasting.api.casting.iota.NullIota object OpUnCons : ConstMediaAction { - override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val list = args.getList(0, argc) - if (list.nonEmpty) { - return listOf(ListIota(list.cdr), list.car) - } - return listOf(args[0], NullIota()) - } + override val argc = 1 + + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val list = args.getList(0, argc) + if (list.nonEmpty) { + return listOf(ListIota(list.cdr), list.car) + } + return listOf(args[0], NullIota()) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPeekLocal.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPeekLocal.kt index 375b5bbcc0..f3df3b0e7a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPeekLocal.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPeekLocal.kt @@ -11,18 +11,23 @@ import at.petrak.hexcasting.api.casting.iota.NullIota import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpPeekLocal : Action { - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + val stack = image.stack.toMutableList() - val rm = if (image.userData.contains(HexAPI.RAVENMIND_USERDATA)) { - IotaType.deserialize(image.userData.getCompound(HexAPI.RAVENMIND_USERDATA), env.world) - } else { - NullIota() - } - stack.add(rm) + val rm = + if (image.userData.contains(HexAPI.RAVENMIND_USERDATA)) { + IotaType.deserialize(image.userData.getCompound(HexAPI.RAVENMIND_USERDATA), env.world) + } else { + NullIota() + } + stack.add(rm) - // does not mutate userdata - val image2 = image.withUsedOp().copy(stack = stack) - return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) - } + // does not mutate userdata + val image2 = image.withUsedOp().copy(stack = stack) + return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPushLocal.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPushLocal.kt index 59c8a7e078..d8b5571a64 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPushLocal.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPushLocal.kt @@ -12,19 +12,20 @@ import at.petrak.hexcasting.common.lib.hex.HexEvalSounds import at.petrak.hexcasting.common.lib.hex.HexIotaTypes object OpPushLocal : Action { - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + val stack = image.stack.toMutableList() - if (stack.isEmpty()) - throw MishapNotEnoughArgs(1, 0) + if (stack.isEmpty()) throw MishapNotEnoughArgs(1, 0) - val newLocal = stack.removeLast() - if (newLocal.type == HexIotaTypes.NULL) - image.userData.remove(HexAPI.RAVENMIND_USERDATA) - else - image.userData.put(HexAPI.RAVENMIND_USERDATA, IotaType.serialize(newLocal)) + val newLocal = stack.removeLast() + if (newLocal.type == HexIotaTypes.NULL) image.userData.remove(HexAPI.RAVENMIND_USERDATA) + else image.userData.put(HexAPI.RAVENMIND_USERDATA, IotaType.serialize(newLocal)) - val image2 = image.withUsedOp().copy(stack = stack) - return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) - } + val image2 = image.withUsedOp().copy(stack = stack) + return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpAbsLen.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpAbsLen.kt index b78bb09a9b..467b4ba768 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpAbsLen.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpAbsLen.kt @@ -8,12 +8,12 @@ import at.petrak.hexcasting.api.casting.iota.Iota import kotlin.math.absoluteValue object OpAbsLen : ConstMediaAction { - override val argc: Int - get() = 1 + override val argc: Int + get() = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val x = args.getNumOrVec(0, argc) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val x = args.getNumOrVec(0, argc) - return x.map({ num -> num.absoluteValue }, { vec -> vec.length() }).asActionResult - } + return x.map({ num -> num.absoluteValue }, { vec -> vec.length() }).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpAdd.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpAdd.kt index cdb1cea4d9..ce43a9340c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpAdd.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpAdd.kt @@ -7,24 +7,26 @@ import at.petrak.hexcasting.api.casting.getNumOrVec import at.petrak.hexcasting.api.casting.iota.Iota object OpAdd : ConstMediaAction { - override val argc: Int - get() = 2 + override val argc: Int + get() = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val lhs = args.getNumOrVec(0, argc) - val rhs = args.getNumOrVec(1, argc) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val lhs = args.getNumOrVec(0, argc) + val rhs = args.getNumOrVec(1, argc) - return lhs.map( - { lnum -> - rhs.map( - { rnum -> (lnum + rnum).asActionResult }, { rvec -> rvec.add(lnum, lnum, lnum).asActionResult } - ) - }, - { lvec -> - rhs.map( - { rnum -> lvec.add(rnum, rnum, rnum).asActionResult }, { rvec -> lvec.add(rvec).asActionResult } - ) - } - ) - } + return lhs.map( + { lnum -> + rhs.map( + { rnum -> (lnum + rnum).asActionResult }, + { rvec -> rvec.add(lnum, lnum, lnum).asActionResult } + ) + }, + { lvec -> + rhs.map( + { rnum -> lvec.add(rnum, rnum, rnum).asActionResult }, + { rvec -> lvec.add(rvec).asActionResult } + ) + } + ) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpCeil.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpCeil.kt index d9b7cbd6af..82f19cff3a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpCeil.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpCeil.kt @@ -8,12 +8,12 @@ import at.petrak.hexcasting.api.casting.iota.Iota import kotlin.math.ceil object OpCeil : ConstMediaAction { - override val argc: Int - get() = 1 + override val argc: Int + get() = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val value = args.getNumOrVec(0, argc) - // i hate this fucking syntax what the hell is ::ceil are you a goddamn homestuck ::c - return listOf(aplKinnie(value, ::ceil)) - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val value = args.getNumOrVec(0, argc) + // i hate this fucking syntax what the hell is ::ceil are you a goddamn homestuck ::c + return listOf(aplKinnie(value, ::ceil)) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpCoerceToAxial.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpCoerceToAxial.kt index 2338066fc7..6523501c7a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpCoerceToAxial.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpCoerceToAxial.kt @@ -5,23 +5,22 @@ import at.petrak.hexcasting.api.casting.castables.ConstMediaAction import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.getNumOrVec import at.petrak.hexcasting.api.casting.iota.Iota +import kotlin.math.sign import net.minecraft.core.Direction import net.minecraft.world.phys.Vec3 -import kotlin.math.sign object OpCoerceToAxial : ConstMediaAction { - override val argc: Int - get() = 1 + override val argc: Int + get() = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val value = args.getNumOrVec(0, argc) - return value.map({ num -> - num.sign.asActionResult - }, { vec -> - if (vec == Vec3.ZERO) - vec.asActionResult - else - Vec3.atLowerCornerOf(Direction.getNearest(vec.x, vec.y, vec.z).normal).asActionResult - }) - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val value = args.getNumOrVec(0, argc) + return value.map( + { num -> num.sign.asActionResult }, + { vec -> + if (vec == Vec3.ZERO) vec.asActionResult + else Vec3.atLowerCornerOf(Direction.getNearest(vec.x, vec.y, vec.z).normal).asActionResult + } + ) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpConstructVec.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpConstructVec.kt index 3a94ea1e54..fcff7129ad 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpConstructVec.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpConstructVec.kt @@ -8,11 +8,12 @@ import at.petrak.hexcasting.api.casting.iota.Iota import net.minecraft.world.phys.Vec3 object OpConstructVec : ConstMediaAction { - override val argc = 3 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val x = args.getDouble(0, argc) - val y = args.getDouble(1, argc) - val z = args.getDouble(2, argc) - return Vec3(x, y, z).asActionResult - } + override val argc = 3 + + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val x = args.getDouble(0, argc) + val y = args.getDouble(1, argc) + val z = args.getDouble(2, argc) + return Vec3(x, y, z).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpDeconstructVec.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpDeconstructVec.kt index 68a979d206..9fe5595304 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpDeconstructVec.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpDeconstructVec.kt @@ -7,9 +7,10 @@ import at.petrak.hexcasting.api.casting.iota.DoubleIota import at.petrak.hexcasting.api.casting.iota.Iota object OpDeconstructVec : ConstMediaAction { - override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val v = args.getVec3(0, argc) - return listOf(DoubleIota(v.x), DoubleIota(v.y), DoubleIota(v.z)) - } + override val argc = 1 + + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val v = args.getVec3(0, argc) + return listOf(DoubleIota(v.x), DoubleIota(v.y), DoubleIota(v.z)) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpDivCross.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpDivCross.kt index f83c97b43f..bd2ff517ad 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpDivCross.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpDivCross.kt @@ -9,34 +9,36 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapDivideByZero import net.minecraft.world.phys.Vec3 object OpDivCross : ConstMediaAction { - override val argc: Int - get() = 2 + override val argc: Int + get() = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val lhs = args.getNumOrVec(0, argc) - val rhs = args.getNumOrVec(1, argc) - val theMishap = MishapDivideByZero.of(args[0], args[1]) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val lhs = args.getNumOrVec(0, argc) + val rhs = args.getNumOrVec(1, argc) + val theMishap = MishapDivideByZero.of(args[0], args[1]) - return lhs.map( - { lnum -> - rhs.map( - { rnum -> - if (rnum == 0.0) throw theMishap // throw theMishap throw theMishap badumbadum - (lnum / rnum).asActionResult - }, - { rvec -> - if (rvec.x == 0.0 || rvec.y == 0.0 || rvec.z == 0.0) throw theMishap - Vec3(lnum / rvec.x, lnum / rvec.y, lnum / rvec.z).asActionResult - } - ) - }, { lvec -> - rhs.map( - { rnum -> - if (lvec == Vec3.ZERO) throw theMishap - lvec.scale(1.0 / rnum).asActionResult - }, - { rvec -> lvec.cross(rvec).asActionResult } - ) - }) - } + return lhs.map( + { lnum -> + rhs.map( + { rnum -> + if (rnum == 0.0) throw theMishap // throw theMishap throw theMishap badumbadum + (lnum / rnum).asActionResult + }, + { rvec -> + if (rvec.x == 0.0 || rvec.y == 0.0 || rvec.z == 0.0) throw theMishap + Vec3(lnum / rvec.x, lnum / rvec.y, lnum / rvec.z).asActionResult + } + ) + }, + { lvec -> + rhs.map( + { rnum -> + if (lvec == Vec3.ZERO) throw theMishap + lvec.scale(1.0 / rnum).asActionResult + }, + { rvec -> lvec.cross(rvec).asActionResult } + ) + } + ) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpFloor.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpFloor.kt index 761888de93..ae1986c889 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpFloor.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpFloor.kt @@ -8,11 +8,11 @@ import at.petrak.hexcasting.api.casting.iota.Iota import kotlin.math.floor object OpFloor : ConstMediaAction { - override val argc: Int - get() = 1 + override val argc: Int + get() = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val value = args.getNumOrVec(0, argc) - return listOf(aplKinnie(value, ::floor)) - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val value = args.getNumOrVec(0, argc) + return listOf(aplKinnie(value, ::floor)) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpLog.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpLog.kt index 054debb4a4..441b0d92af 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpLog.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpLog.kt @@ -9,14 +9,14 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapDivideByZero import kotlin.math.log object OpLog : ConstMediaAction { - override val argc: Int - get() = 2 + override val argc: Int + get() = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val value = args.getDouble(0, argc) - val base = args.getDouble(1, argc) - if (value <= 0.0 || base <= 0.0 || base == 1.0) - throw MishapDivideByZero.of(args[0], args[1], "logarithm") - return log(value, base).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val value = args.getDouble(0, argc) + val base = args.getDouble(1, argc) + if (value <= 0.0 || base <= 0.0 || base == 1.0) + throw MishapDivideByZero.of(args[0], args[1], "logarithm") + return log(value, base).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpModulo.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpModulo.kt index 57753f8fb4..3e413a8d24 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpModulo.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpModulo.kt @@ -8,15 +8,14 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.mishaps.MishapDivideByZero object OpModulo : ConstMediaAction { - override val argc: Int - get() = 2 + override val argc: Int + get() = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - // TODO: some wAckY vector operation to go in the vector x vector overload - val l = args.getDouble(0, argc) - val r = args.getDouble(1, argc) - if (r == 0.0) - throw MishapDivideByZero.of(args[0], args[1]) - return (l % r).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + // TODO: some wAckY vector operation to go in the vector x vector overload + val l = args.getDouble(0, argc) + val r = args.getDouble(1, argc) + if (r == 0.0) throw MishapDivideByZero.of(args[0], args[1]) + return (l % r).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpMulDot.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpMulDot.kt index fe5324ddd1..7eaf7f3933 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpMulDot.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpMulDot.kt @@ -7,23 +7,26 @@ import at.petrak.hexcasting.api.casting.getNumOrVec import at.petrak.hexcasting.api.casting.iota.Iota object OpMulDot : ConstMediaAction { - override val argc: Int - get() = 2 + override val argc: Int + get() = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val lhs = args.getNumOrVec(0, OpAdd.argc) - val rhs = args.getNumOrVec(1, OpAdd.argc) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val lhs = args.getNumOrVec(0, OpAdd.argc) + val rhs = args.getNumOrVec(1, OpAdd.argc) - return lhs.map( - { lnum -> - rhs.map( - { rnum -> (lnum * rnum).asActionResult }, { rvec -> rvec.scale(lnum).asActionResult } - ) - }, { lvec -> - rhs.map( - { rnum -> lvec.scale(rnum).asActionResult }, { rvec -> lvec.dot(rvec).asActionResult } - ) - }) - - } + return lhs.map( + { lnum -> + rhs.map( + { rnum -> (lnum * rnum).asActionResult }, + { rvec -> rvec.scale(lnum).asActionResult } + ) + }, + { lvec -> + rhs.map( + { rnum -> lvec.scale(rnum).asActionResult }, + { rvec -> lvec.dot(rvec).asActionResult } + ) + } + ) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpPowProj.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpPowProj.kt index 814fca39d7..5ed2fbf995 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpPowProj.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpPowProj.kt @@ -6,44 +6,43 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.getNumOrVec import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.mishaps.MishapDivideByZero -import net.minecraft.world.phys.Vec3 import kotlin.math.pow +import net.minecraft.world.phys.Vec3 object OpPowProj : ConstMediaAction { - override val argc: Int - get() = 2 + override val argc: Int + get() = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val lhs = args.getNumOrVec(0, OpAdd.argc) - val rhs = args.getNumOrVec(1, OpAdd.argc) - val theMishap = MishapDivideByZero.of(args[0], args[1], "exponent") + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val lhs = args.getNumOrVec(0, OpAdd.argc) + val rhs = args.getNumOrVec(1, OpAdd.argc) + val theMishap = MishapDivideByZero.of(args[0], args[1], "exponent") - return lhs.map( - { lnum -> - rhs.map( - { rnum -> - if (rnum == 0.0 && lnum == 0.0) - throw theMishap - lnum.pow(rnum).asActionResult - }, { rvec -> - if (lnum == 0.0 && (rvec.x == 0.0 || rvec.y == 0.0 || rvec.z == 0.0)) - throw theMishap - Vec3(lnum.pow(rvec.x), lnum.pow(rvec.y), lnum.pow(rvec.z)).asActionResult - } - ) - }, { lvec -> - rhs.map( - { rnum -> - if (rnum == 0.0 && (lvec.x == 0.0 || lvec.y == 0.0 || lvec.z == 0.0)) - throw theMishap - Vec3(lvec.x.pow(rnum), lvec.y.pow(rnum), lvec.z.pow(rnum)).asActionResult - }, - { rvec -> - if (lvec == Vec3.ZERO) - throw MishapDivideByZero.of(args[0], args[1], "project") - lvec.scale(rvec.dot(lvec) / lvec.dot(lvec)).asActionResult - } - ) - }) - } + return lhs.map( + { lnum -> + rhs.map( + { rnum -> + if (rnum == 0.0 && lnum == 0.0) throw theMishap + lnum.pow(rnum).asActionResult + }, + { rvec -> + if (lnum == 0.0 && (rvec.x == 0.0 || rvec.y == 0.0 || rvec.z == 0.0)) throw theMishap + Vec3(lnum.pow(rvec.x), lnum.pow(rvec.y), lnum.pow(rvec.z)).asActionResult + } + ) + }, + { lvec -> + rhs.map( + { rnum -> + if (rnum == 0.0 && (lvec.x == 0.0 || lvec.y == 0.0 || lvec.z == 0.0)) throw theMishap + Vec3(lvec.x.pow(rnum), lvec.y.pow(rnum), lvec.z.pow(rnum)).asActionResult + }, + { rvec -> + if (lvec == Vec3.ZERO) throw MishapDivideByZero.of(args[0], args[1], "project") + lvec.scale(rvec.dot(lvec) / lvec.dot(lvec)).asActionResult + } + ) + } + ) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpRandom.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpRandom.kt index 87853a1ecf..7179d145ee 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpRandom.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpRandom.kt @@ -6,10 +6,10 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota object OpRandom : ConstMediaAction { - override val argc: Int - get() = 0 + override val argc: Int + get() = 0 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - return env.world.random.nextDouble().asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + return env.world.random.nextDouble().asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpSub.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpSub.kt index e5aec943ca..a7a90b26cb 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpSub.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/OpSub.kt @@ -8,23 +8,26 @@ import at.petrak.hexcasting.api.casting.iota.Iota import net.minecraft.world.phys.Vec3 object OpSub : ConstMediaAction { - override val argc: Int - get() = 2 + override val argc: Int + get() = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val lhs = args.getNumOrVec(0, OpAdd.argc) - val rhs = args.getNumOrVec(1, OpAdd.argc) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val lhs = args.getNumOrVec(0, OpAdd.argc) + val rhs = args.getNumOrVec(1, OpAdd.argc) - return lhs.map({ lnum -> - rhs.map( - { rnum -> (lnum - rnum).asActionResult }, - { rvec -> Vec3(lnum - rvec.x, lnum - rvec.y, lnum - rvec.z).asActionResult } - ) - }, { lvec -> - rhs.map( - { rnum -> lvec.subtract(rnum, rnum, rnum).asActionResult }, - { rvec -> lvec.subtract(rvec).asActionResult } - ) - }) - } + return lhs.map( + { lnum -> + rhs.map( + { rnum -> (lnum - rnum).asActionResult }, + { rvec -> Vec3(lnum - rvec.x, lnum - rvec.y, lnum - rvec.z).asActionResult } + ) + }, + { lvec -> + rhs.map( + { rnum -> lvec.subtract(rnum, rnum, rnum).asActionResult }, + { rvec -> lvec.subtract(rvec).asActionResult } + ) + } + ) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/SpecialHandlerNumberLiteral.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/SpecialHandlerNumberLiteral.kt index 20d317ce84..7b9d3cd297 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/SpecialHandlerNumberLiteral.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/SpecialHandlerNumberLiteral.kt @@ -15,64 +15,64 @@ import at.petrak.hexcasting.xplat.IXplatAbstractions import net.minecraft.network.chat.Component class SpecialHandlerNumberLiteral(val x: Double) : SpecialHandler { - override fun act(): Action { - return InnerAction(this.x) - } + override fun act(): Action { + return InnerAction(this.x) + } - override fun getName(): Component { - val key = IXplatAbstractions.INSTANCE.specialHandlerRegistry.getResourceKey(HexSpecialHandlers.NUMBER).get() - return HexAPI.instance().getSpecialHandlerI18nKey(key) - .asTranslatedComponent(Action.DOUBLE_FORMATTER.format(x)).lightPurple - } + override fun getName(): Component { + val key = + IXplatAbstractions.INSTANCE.specialHandlerRegistry + .getResourceKey(HexSpecialHandlers.NUMBER) + .get() + return HexAPI.instance() + .getSpecialHandlerI18nKey(key) + .asTranslatedComponent(Action.DOUBLE_FORMATTER.format(x)) + .lightPurple + } - class InnerAction(val x: Double) : ConstMediaAction { - override val argc = 0 + class InnerAction(val x: Double) : ConstMediaAction { + override val argc = 0 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - return this.x.asActionResult - } - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + return this.x.asActionResult + } + } - class Factory : SpecialHandler.Factory<SpecialHandlerNumberLiteral> { - override fun tryMatch(pat: HexPattern, env: CastingEnvironment): SpecialHandlerNumberLiteral? { - val sig = pat.anglesSignature() - if (sig.startsWith("aqaa") || sig.startsWith("dedd")) { - val negate = sig.startsWith("dedd"); - var accumulator = 0.0; - for (ch in sig.substring(4)) { - when (ch) { - 'w' -> { - accumulator += 1; - } - - 'q' -> { - accumulator += 5; - } - - 'e' -> { - accumulator += 10; - } - - 'a' -> { - accumulator *= 2; - } - - 'd' -> { - accumulator /= 2; - } - // ok funny man - 's' -> {} - else -> throw IllegalStateException() - } - } - if (negate) { - accumulator = -accumulator; - } - return SpecialHandlerNumberLiteral(accumulator); - } else { - return null; - } - } - - } -} \ No newline at end of file + class Factory : SpecialHandler.Factory<SpecialHandlerNumberLiteral> { + override fun tryMatch(pat: HexPattern, env: CastingEnvironment): SpecialHandlerNumberLiteral? { + val sig = pat.anglesSignature() + if (sig.startsWith("aqaa") || sig.startsWith("dedd")) { + val negate = sig.startsWith("dedd") + var accumulator = 0.0 + for (ch in sig.substring(4)) { + when (ch) { + 'w' -> { + accumulator += 1 + } + 'q' -> { + accumulator += 5 + } + 'e' -> { + accumulator += 10 + } + 'a' -> { + accumulator *= 2 + } + 'd' -> { + accumulator /= 2 + } + // ok funny man + 's' -> {} + else -> throw IllegalStateException() + } + } + if (negate) { + accumulator = -accumulator + } + return SpecialHandlerNumberLiteral(accumulator) + } else { + return null + } + } + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpAnd.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpAnd.kt index 60ec2eecb8..93a68d1587 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpAnd.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpAnd.kt @@ -9,20 +9,20 @@ import at.petrak.hexcasting.api.casting.getLongOrList import at.petrak.hexcasting.api.casting.iota.Iota object OpAnd : ConstMediaAction { - override val argc = 2 + override val argc = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val firstParam = args.getLongOrList(0, argc) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val firstParam = args.getLongOrList(0, argc) - return firstParam.map( - { num1 -> - val num2 = args.getLong(1, argc) - (num1 and num2).asActionResult - }, - { list1 -> - val list2 = args.getList(1, argc) - list1.filter { x -> list2.any { Iota.tolerates(x, it) } }.asActionResult - } - ) - } + return firstParam.map( + { num1 -> + val num2 = args.getLong(1, argc) + (num1 and num2).asActionResult + }, + { list1 -> + val list2 = args.getList(1, argc) + list1.filter { x -> list2.any { Iota.tolerates(x, it) } }.asActionResult + } + ) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpNot.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpNot.kt index 435b1706f0..89616ce8f5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpNot.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpNot.kt @@ -7,10 +7,10 @@ import at.petrak.hexcasting.api.casting.getLong import at.petrak.hexcasting.api.casting.iota.Iota object OpNot : ConstMediaAction { - override val argc = 1 + override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val num = args.getLong(0, argc) - return num.inv().asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val num = args.getLong(0, argc) + return num.inv().asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpOr.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpOr.kt index 220ff72468..f9f3e38464 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpOr.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpOr.kt @@ -9,20 +9,20 @@ import at.petrak.hexcasting.api.casting.getLongOrList import at.petrak.hexcasting.api.casting.iota.Iota object OpOr : ConstMediaAction { - override val argc = 2 + override val argc = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val firstParam = args.getLongOrList(0, argc) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val firstParam = args.getLongOrList(0, argc) - return firstParam.map( - { num1 -> - val num2 = args.getLong(1, argc) - (num1 or num2).asActionResult - }, - { list1 -> - val list2 = args.getList(1, argc) - (list1 + list2.filter { x -> list1.none { Iota.tolerates(x, it) } }).asActionResult - } - ) - } + return firstParam.map( + { num1 -> + val num2 = args.getLong(1, argc) + (num1 or num2).asActionResult + }, + { list1 -> + val list2 = args.getList(1, argc) + (list1 + list2.filter { x -> list1.none { Iota.tolerates(x, it) } }).asActionResult + } + ) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpToSet.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpToSet.kt index 94ddcba5c1..08e0330187 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpToSet.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpToSet.kt @@ -7,18 +7,18 @@ import at.petrak.hexcasting.api.casting.getList import at.petrak.hexcasting.api.casting.iota.Iota object OpToSet : ConstMediaAction { - override val argc = 1 + override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val list = args.getList(0, argc) - val out = mutableListOf<Iota>() + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val list = args.getList(0, argc) + val out = mutableListOf<Iota>() - for (subiota in list) { - if (out.none { Iota.tolerates(it, subiota) }) { - out.add(subiota) - } - } + for (subiota in list) { + if (out.none { Iota.tolerates(it, subiota) }) { + out.add(subiota) + } + } - return out.asActionResult - } + return out.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpXor.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpXor.kt index d45323de52..c19caea3cb 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpXor.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/bit/OpXor.kt @@ -9,29 +9,23 @@ import at.petrak.hexcasting.api.casting.getLongOrList import at.petrak.hexcasting.api.casting.iota.Iota object OpXor : ConstMediaAction { - override val argc = 2 + override val argc = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val firstParam = args.getLongOrList(0, argc) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val firstParam = args.getLongOrList(0, argc) - return firstParam.map( - { num1 -> - val num2 = args.getLong(1, argc) - (num1 xor num2).asActionResult - }, - { list1 -> - val list2 = args.getList(1, argc) - val out = - list1.filter { x1 -> - list2.none { - Iota.tolerates( - x1, - it - ) - } - } + list2.filter { x2 -> list1.none { Iota.tolerates(x2, it) } } - out.asActionResult - } - ) - } + return firstParam.map( + { num1 -> + val num2 = args.getLong(1, argc) + (num1 xor num2).asActionResult + }, + { list1 -> + val list2 = args.getList(1, argc) + val out = + list1.filter { x1 -> list2.none { Iota.tolerates(x1, it) } } + + list2.filter { x2 -> list1.none { Iota.tolerates(x2, it) } } + out.asActionResult + } + ) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolAnd.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolAnd.kt index db3e8b0e7e..e41408abf0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolAnd.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolAnd.kt @@ -7,11 +7,11 @@ import at.petrak.hexcasting.api.casting.getBool import at.petrak.hexcasting.api.casting.iota.Iota object OpBoolAnd : ConstMediaAction { - override val argc = 2 + override val argc = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val lhs = args.getBool(0, argc) - val rhs = args.getBool(1, argc) - return (lhs && rhs).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val lhs = args.getBool(0, argc) + val rhs = args.getBool(1, argc) + return (lhs && rhs).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolIf.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolIf.kt index 140de0ea4f..480cdd71b2 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolIf.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolIf.kt @@ -6,12 +6,12 @@ import at.petrak.hexcasting.api.casting.getBool import at.petrak.hexcasting.api.casting.iota.Iota object OpBoolIf : ConstMediaAction { - override val argc = 3 + override val argc = 3 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val cond = args.getBool(0, argc) - val t = args[1] - val f = args[2] - return listOf(if (cond) t else f) - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val cond = args.getBool(0, argc) + val t = args[1] + val f = args[2] + return listOf(if (cond) t else f) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolNot.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolNot.kt index 834f498fc8..05e4565eec 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolNot.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolNot.kt @@ -7,10 +7,10 @@ import at.petrak.hexcasting.api.casting.getBool import at.petrak.hexcasting.api.casting.iota.Iota object OpBoolNot : ConstMediaAction { - override val argc = 1 + override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val b = args.getBool(0, argc) - return (!b).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val b = args.getBool(0, argc) + return (!b).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolOr.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolOr.kt index 7c2123b159..45afee1a26 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolOr.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolOr.kt @@ -7,11 +7,11 @@ import at.petrak.hexcasting.api.casting.getBool import at.petrak.hexcasting.api.casting.iota.Iota object OpBoolOr : ConstMediaAction { - override val argc = 2 + override val argc = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val lhs = args.getBool(0, argc) - val rhs = args.getBool(1, argc) - return (lhs || rhs).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val lhs = args.getBool(0, argc) + val rhs = args.getBool(1, argc) + return (lhs || rhs).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolToNumber.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolToNumber.kt index cc3902893c..e6fddcd089 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolToNumber.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolToNumber.kt @@ -7,10 +7,10 @@ import at.petrak.hexcasting.api.casting.getBool import at.petrak.hexcasting.api.casting.iota.Iota object OpBoolToNumber : ConstMediaAction { - override val argc = 1 + override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val arg = args.getBool(0, argc) - return (if (arg) 1.0 else 0.0).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val arg = args.getBool(0, argc) + return (if (arg) 1.0 else 0.0).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolXor.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolXor.kt index 5c1af93652..df76030519 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolXor.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpBoolXor.kt @@ -7,11 +7,11 @@ import at.petrak.hexcasting.api.casting.getBool import at.petrak.hexcasting.api.casting.iota.Iota object OpBoolXor : ConstMediaAction { - override val argc = 2 + override val argc = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val lhs = args.getBool(0, argc) - val rhs = args.getBool(1, argc) - return (lhs xor rhs).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val lhs = args.getBool(0, argc) + val rhs = args.getBool(1, argc) + return (lhs xor rhs).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpCoerceToBool.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpCoerceToBool.kt index d9996457be..36b5dbe048 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpCoerceToBool.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpCoerceToBool.kt @@ -6,9 +6,9 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota object OpCoerceToBool : ConstMediaAction { - override val argc = 1 + override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - return (args[0].isTruthy).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + return (args[0].isTruthy).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpCompare.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpCompare.kt index 98c479aa6e..ba830b8d49 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpCompare.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpCompare.kt @@ -8,15 +8,15 @@ import at.petrak.hexcasting.api.casting.iota.DoubleIota import at.petrak.hexcasting.api.casting.iota.Iota import java.util.function.BiPredicate -class OpCompare(val acceptsEqual: Boolean, val cmp: BiPredicate<Double, Double>) : ConstMediaAction { - override val argc = 2 +class OpCompare(val acceptsEqual: Boolean, val cmp: BiPredicate<Double, Double>) : + ConstMediaAction { + override val argc = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val lhs = args.getDouble(0, argc) - val rhs = args.getDouble(1, argc) - if (DoubleIota.tolerates(lhs, rhs)) - return acceptsEqual.asActionResult + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val lhs = args.getDouble(0, argc) + val rhs = args.getDouble(1, argc) + if (DoubleIota.tolerates(lhs, rhs)) return acceptsEqual.asActionResult - return cmp.test(lhs, rhs).asActionResult - } + return cmp.test(lhs, rhs).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpEquality.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpEquality.kt index 2dcc9f1961..efe66104b3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpEquality.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpEquality.kt @@ -6,12 +6,12 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota class OpEquality(val invert: Boolean) : ConstMediaAction { - override val argc = 2 + override val argc = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val lhs = args[0] - val rhs = args[1] + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val lhs = args[0] + val rhs = args[1] - return (Iota.tolerates(lhs, rhs) != invert).asActionResult - } + return (Iota.tolerates(lhs, rhs) != invert).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcCos.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcCos.kt index 49dce7e697..231465e2f1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcCos.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcCos.kt @@ -8,11 +8,11 @@ import at.petrak.hexcasting.api.casting.iota.Iota import kotlin.math.acos object OpArcCos : ConstMediaAction { - override val argc: Int - get() = 1 + override val argc: Int + get() = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val value = args.getDoubleBetween(0, -1.0, 1.0, argc) - return acos(value).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val value = args.getDoubleBetween(0, -1.0, 1.0, argc) + return acos(value).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcSin.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcSin.kt index 49e82a21df..e8c65c9b43 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcSin.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcSin.kt @@ -8,11 +8,11 @@ import at.petrak.hexcasting.api.casting.iota.Iota import kotlin.math.asin object OpArcSin : ConstMediaAction { - override val argc: Int - get() = 1 + override val argc: Int + get() = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val value = args.getDoubleBetween(0, -1.0, 1.0, OpArcCos.argc) - return asin(value).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val value = args.getDoubleBetween(0, -1.0, 1.0, OpArcCos.argc) + return asin(value).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcTan.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcTan.kt index 45b07c6ea5..9124f5b248 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcTan.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcTan.kt @@ -8,11 +8,11 @@ import at.petrak.hexcasting.api.casting.iota.Iota import kotlin.math.atan object OpArcTan : ConstMediaAction { - override val argc: Int - get() = 1 + override val argc: Int + get() = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val value = args.getDouble(0, argc) - return atan(value).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val value = args.getDouble(0, argc) + return atan(value).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcTan2.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcTan2.kt index 6418ccfa5e..eab496baea 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcTan2.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpArcTan2.kt @@ -8,12 +8,12 @@ import at.petrak.hexcasting.api.casting.iota.Iota import kotlin.math.atan2 object OpArcTan2 : ConstMediaAction { - override val argc: Int - get() = 2 + override val argc: Int + get() = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val y = args.getDouble(0, argc) - val x = args.getDouble(1, argc) - return atan2(y, x).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val y = args.getDouble(0, argc) + val x = args.getDouble(1, argc) + return atan2(y, x).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpCos.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpCos.kt index 7411c3b8ad..c75526ac11 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpCos.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpCos.kt @@ -8,11 +8,11 @@ import at.petrak.hexcasting.api.casting.iota.Iota import kotlin.math.cos object OpCos : ConstMediaAction { - override val argc: Int - get() = 1 + override val argc: Int + get() = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val angle = args.getDouble(0, argc) - return cos(angle).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val angle = args.getDouble(0, argc) + return cos(angle).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpSin.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpSin.kt index de67f35c65..6a93e97dc0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpSin.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpSin.kt @@ -8,11 +8,11 @@ import at.petrak.hexcasting.api.casting.iota.Iota import kotlin.math.sin object OpSin : ConstMediaAction { - override val argc: Int - get() = 1 + override val argc: Int + get() = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val angle = args.getDouble(0, argc) - return sin(angle).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val angle = args.getDouble(0, argc) + return sin(angle).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpTan.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpTan.kt index b6b7687276..0ce8363481 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpTan.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/trig/OpTan.kt @@ -11,13 +11,12 @@ import kotlin.math.cos import kotlin.math.tan object OpTan : ConstMediaAction { - override val argc: Int - get() = 1 + override val argc: Int + get() = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val angle = args.getDouble(0, argc) - if (cos(angle) == 0.0) - throw MishapDivideByZero.tan(args[0] as DoubleIota) - return tan(angle).asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val angle = args.getDouble(0, argc) + if (cos(angle) == 0.0) throw MishapDivideByZero.tan(args[0] as DoubleIota) + return tan(angle).asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockAxisRaycast.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockAxisRaycast.kt index 2aa68ecf28..e0671bee87 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockAxisRaycast.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockAxisRaycast.kt @@ -13,29 +13,33 @@ import net.minecraft.world.phys.HitResult import net.minecraft.world.phys.Vec3 object OpBlockAxisRaycast : ConstMediaAction { - override val argc = 2 - override val mediaCost: Long = MediaConstants.DUST_UNIT / 100 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val origin = args.getVec3(0, argc) - val look = args.getVec3(1, argc) + override val argc = 2 + override val mediaCost: Long = MediaConstants.DUST_UNIT / 100 - env.assertVecInRange(origin) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val origin = args.getVec3(0, argc) + val look = args.getVec3(1, argc) - val blockHitResult = env.world.clip( - ClipContext( - origin, - Action.raycastEnd(origin, look), - ClipContext.Block.COLLIDER, - ClipContext.Fluid.NONE, - @Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") - env.castingEntity - ) - ) + env.assertVecInRange(origin) - return if (blockHitResult.type == HitResult.Type.BLOCK && env.isVecInRange(Vec3.atCenterOf(blockHitResult.blockPos))) { - blockHitResult.direction.step().asActionResult - } else { - listOf(NullIota()) - } - } + val blockHitResult = + env.world.clip( + ClipContext( + origin, + Action.raycastEnd(origin, look), + ClipContext.Block.COLLIDER, + ClipContext.Fluid.NONE, + @Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") env.castingEntity + ) + ) + + return if ( + blockHitResult.type == HitResult.Type.BLOCK && + env.isVecInRange(Vec3.atCenterOf(blockHitResult.blockPos)) + ) { + blockHitResult.direction.step().asActionResult + } else { + listOf(NullIota()) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockRaycast.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockRaycast.kt index 33a2e990eb..f6a24e8968 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockRaycast.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockRaycast.kt @@ -13,33 +13,39 @@ import net.minecraft.world.phys.HitResult import net.minecraft.world.phys.Vec3 object OpBlockRaycast : ConstMediaAction { - override val argc = 2 - override val mediaCost: Long = MediaConstants.DUST_UNIT / 100 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val origin = args.getVec3(0, argc) - val look = args.getVec3(1, argc) + override val argc = 2 + override val mediaCost: Long = MediaConstants.DUST_UNIT / 100 - env.assertVecInRange(origin) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val origin = args.getVec3(0, argc) + val look = args.getVec3(1, argc) - val blockHitResult = env.world.clip( - ClipContext( - origin, - Action.raycastEnd(origin, look), - ClipContext.Block.COLLIDER, - ClipContext.Fluid.NONE, - @Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") - env.castingEntity - ) - ) + env.assertVecInRange(origin) - return if (blockHitResult.type == HitResult.Type.BLOCK && env.isVecInRange(Vec3.atCenterOf(blockHitResult.blockPos))) { - // the position on the bhr is the position of the specific *hit point*, which is actually on the outside of the block - // this is weird (for example, casting OpBreakBlock at this position will not break the block we're looking at) - // so we return the block pos instead - // TODO some action that has the "weird" version? - blockHitResult.blockPos.asActionResult - } else { - listOf(NullIota()) - } - } + val blockHitResult = + env.world.clip( + ClipContext( + origin, + Action.raycastEnd(origin, look), + ClipContext.Block.COLLIDER, + ClipContext.Fluid.NONE, + @Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") env.castingEntity + ) + ) + + return if ( + blockHitResult.type == HitResult.Type.BLOCK && + env.isVecInRange(Vec3.atCenterOf(blockHitResult.blockPos)) + ) { + // the position on the bhr is the position of the specific *hit point*, which is actually on + // the outside of the block + // this is weird (for example, casting OpBreakBlock at this position will not break the block + // we're looking at) + // so we return the block pos instead + // TODO some action that has the "weird" version? + blockHitResult.blockPos.asActionResult + } else { + listOf(NullIota()) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpEntityRaycast.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpEntityRaycast.kt index 64ea54525a..e612f9e934 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpEntityRaycast.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpEntityRaycast.kt @@ -8,77 +8,85 @@ import at.petrak.hexcasting.api.casting.getVec3 import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.NullIota import at.petrak.hexcasting.api.misc.MediaConstants +import java.util.function.Predicate import net.minecraft.world.entity.Entity import net.minecraft.world.level.Level import net.minecraft.world.phys.AABB import net.minecraft.world.phys.EntityHitResult import net.minecraft.world.phys.Vec3 -import java.util.function.Predicate object OpEntityRaycast : ConstMediaAction { - override val argc = 2 - override val mediaCost: Long = MediaConstants.DUST_UNIT / 100 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val origin = args.getVec3(0, argc) - val look = args.getVec3(1, argc) - val endp = Action.raycastEnd(origin, look) + override val argc = 2 + override val mediaCost: Long = MediaConstants.DUST_UNIT / 100 + + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val origin = args.getVec3(0, argc) + val look = args.getVec3(1, argc) + val endp = Action.raycastEnd(origin, look) - env.assertVecInRange(origin) + env.assertVecInRange(origin) - val entityHitResult = getEntityHitResult( - env.castingEntity, - env.world, - origin, - endp, - AABB(origin, endp), - { true }, - 1_000_000.0 - ) + val entityHitResult = + getEntityHitResult( + env.castingEntity, + env.world, + origin, + endp, + AABB(origin, endp), + { true }, + 1_000_000.0 + ) - return if (entityHitResult != null && env.isEntityInRange(entityHitResult.entity)) { - entityHitResult.entity.asActionResult - } else { - listOf(NullIota()) - } - } + return if (entityHitResult != null && env.isEntityInRange(entityHitResult.entity)) { + entityHitResult.entity.asActionResult + } else { + listOf(NullIota()) + } + } - fun getEntityHitResult( - entity: Entity?, level: Level, startPos: Vec3, endPos: Vec3, - aabb: AABB, isValid: Predicate<Entity>, maxSqrLength: Double): EntityHitResult? { - var sqrLength = maxSqrLength - var hitEntity: Entity? = null - var hitPos: Vec3? = null - val allValidInAABB: Iterator<*> = level.getEntities(entity, aabb, isValid).iterator() + fun getEntityHitResult( + entity: Entity?, + level: Level, + startPos: Vec3, + endPos: Vec3, + aabb: AABB, + isValid: Predicate<Entity>, + maxSqrLength: Double + ): EntityHitResult? { + var sqrLength = maxSqrLength + var hitEntity: Entity? = null + var hitPos: Vec3? = null + val allValidInAABB: Iterator<*> = level.getEntities(entity, aabb, isValid).iterator() - while (allValidInAABB.hasNext()) { - val nextEntity = allValidInAABB.next() as Entity - val hitBox = nextEntity.boundingBox.inflate(nextEntity.pickRadius.toDouble()) - val overlapBox = hitBox.clip(startPos, endPos) - if (hitBox.contains(startPos)) { - if (sqrLength >= 0.0) { - hitEntity = nextEntity - hitPos = overlapBox.orElse(startPos) - sqrLength = 0.0 - } - } else if (overlapBox.isPresent) { - val maybePos = overlapBox.get() - val sqrDist = startPos.distanceToSqr(maybePos) - if (sqrDist < sqrLength || sqrLength == 0.0) { - if (nextEntity.rootVehicle === entity?.rootVehicle) { - if (sqrLength == 0.0) { - hitEntity = nextEntity - hitPos = maybePos - } - } else { - hitEntity = nextEntity - hitPos = maybePos - sqrLength = sqrDist - } - } - } - } - return if (hitEntity == null) { - null - } else EntityHitResult(hitEntity, hitPos!!) // hitEntity != null <=> hitPos != null - } + while (allValidInAABB.hasNext()) { + val nextEntity = allValidInAABB.next() as Entity + val hitBox = nextEntity.boundingBox.inflate(nextEntity.pickRadius.toDouble()) + val overlapBox = hitBox.clip(startPos, endPos) + if (hitBox.contains(startPos)) { + if (sqrLength >= 0.0) { + hitEntity = nextEntity + hitPos = overlapBox.orElse(startPos) + sqrLength = 0.0 + } + } else if (overlapBox.isPresent) { + val maybePos = overlapBox.get() + val sqrDist = startPos.distanceToSqr(maybePos) + if (sqrDist < sqrLength || sqrLength == 0.0) { + if (nextEntity.rootVehicle === entity?.rootVehicle) { + if (sqrLength == 0.0) { + hitEntity = nextEntity + hitPos = maybePos + } + } else { + hitEntity = nextEntity + hitPos = maybePos + sqrLength = sqrDist + } + } + } + } + return if (hitEntity == null) { + null + } else EntityHitResult(hitEntity, hitPos!!) // hitEntity != null <=> hitPos != null + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpRead.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpRead.kt index 51791b6d26..885659e9c4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpRead.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpRead.kt @@ -7,27 +7,32 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapBadOffhandItem import at.petrak.hexcasting.xplat.IXplatAbstractions object OpRead : ConstMediaAction { - override val argc = 0 + override val argc = 0 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val (handStack) = env.getHeldItemToOperateOn { - val dataHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) - dataHolder != null && (dataHolder.readIota(env.world) != null || dataHolder.emptyIota() != null) - } - // If there are no data holders that are readable, find a data holder that isn't readable - // so that the error message is more helpful. - ?: env.getHeldItemToOperateOn { - val dataHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) - dataHolder != null - } ?: throw MishapBadOffhandItem.of(null, "iota.read") + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val (handStack) = + env.getHeldItemToOperateOn { + val dataHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) + dataHolder != null && + (dataHolder.readIota(env.world) != null || dataHolder.emptyIota() != null) + } + // If there are no data holders that are readable, find a data holder that isn't readable + // so that the error message is more helpful. + ?: env.getHeldItemToOperateOn { + val dataHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) + dataHolder != null + } + ?: throw MishapBadOffhandItem.of(null, "iota.read") - val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack) - ?: throw MishapBadOffhandItem.of(handStack, "iota.read") + val datumHolder = + IXplatAbstractions.INSTANCE.findDataHolder(handStack) + ?: throw MishapBadOffhandItem.of(handStack, "iota.read") - val datum = datumHolder.readIota(env.world) - ?: datumHolder.emptyIota() - ?: throw MishapBadOffhandItem.of(handStack, "iota.read") + val datum = + datumHolder.readIota(env.world) + ?: datumHolder.emptyIota() + ?: throw MishapBadOffhandItem.of(handStack, "iota.read") - return listOf(datum) - } + return listOf(datum) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpReadable.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpReadable.kt index d368b9d87b..83d12ec4f7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpReadable.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpReadable.kt @@ -7,20 +7,19 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.xplat.IXplatAbstractions object OpReadable : ConstMediaAction { - override val argc = 0 + override val argc = 0 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val (handStack) = env.getHeldItemToOperateOn { - IXplatAbstractions.INSTANCE.findDataHolder(it) != null - } ?: return false.asActionResult + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val (handStack) = + env.getHeldItemToOperateOn { IXplatAbstractions.INSTANCE.findDataHolder(it) != null } + ?: return false.asActionResult - val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack) - ?: return false.asActionResult + val datumHolder = + IXplatAbstractions.INSTANCE.findDataHolder(handStack) ?: return false.asActionResult - // If the datum contains no iota, return whether it has a default empty iota. - datumHolder.readIota(env.world) - ?: return (datumHolder.emptyIota() != null).asActionResult + // If the datum contains no iota, return whether it has a default empty iota. + datumHolder.readIota(env.world) ?: return (datumHolder.emptyIota() != null).asActionResult - return true.asActionResult - } + return true.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerRead.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerRead.kt index 4fd4a69f8b..f16323e909 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerRead.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerRead.kt @@ -8,22 +8,21 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapBadEntity import at.petrak.hexcasting.xplat.IXplatAbstractions object OpTheCoolerRead : ConstMediaAction { - override val argc = 1 + override val argc = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): List<Iota> { - val target = args.getEntity(0, argc) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val target = args.getEntity(0, argc) - env.assertEntityInRange(target) + env.assertEntityInRange(target) - val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(target) - ?: throw MishapBadEntity.of(target, "iota.read") + val datumHolder = + IXplatAbstractions.INSTANCE.findDataHolder(target) + ?: throw MishapBadEntity.of(target, "iota.read") - val datum = datumHolder.readIota(env.world) - ?: datumHolder.emptyIota() - ?: throw MishapBadEntity.of(target, "iota.read") - return listOf(datum) - } + val datum = + datumHolder.readIota(env.world) + ?: datumHolder.emptyIota() + ?: throw MishapBadEntity.of(target, "iota.read") + return listOf(datum) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerReadable.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerReadable.kt index aa118182af..d1619f6f8d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerReadable.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerReadable.kt @@ -8,22 +8,17 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.xplat.IXplatAbstractions object OpTheCoolerReadable : ConstMediaAction { - override val argc = 1 + override val argc = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): List<Iota> { - val target = args.getEntity(0, argc) - env.assertEntityInRange(target) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val target = args.getEntity(0, argc) + env.assertEntityInRange(target) - val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(target) - ?: return false.asActionResult + val datumHolder = + IXplatAbstractions.INSTANCE.findDataHolder(target) ?: return false.asActionResult - datumHolder.readIota(env.world) - ?: datumHolder.emptyIota() - ?: return false.asActionResult + datumHolder.readIota(env.world) ?: datumHolder.emptyIota() ?: return false.asActionResult - return true.asActionResult - } + return true.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWritable.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWritable.kt index 598ae8b145..3631c609ce 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWritable.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWritable.kt @@ -9,20 +9,17 @@ import at.petrak.hexcasting.api.casting.iota.NullIota import at.petrak.hexcasting.xplat.IXplatAbstractions object OpTheCoolerWritable : ConstMediaAction { - override val argc = 1 + override val argc = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): List<Iota> { - val target = args.getEntity(0, argc) - env.assertEntityInRange(target) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val target = args.getEntity(0, argc) + env.assertEntityInRange(target) - val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(target) - ?: return false.asActionResult + val datumHolder = + IXplatAbstractions.INSTANCE.findDataHolder(target) ?: return false.asActionResult - val success = datumHolder.writeIota(NullIota(), true) + val success = datumHolder.writeIota(NullIota(), true) - return success.asActionResult - } + return success.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWrite.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWrite.kt index 27e02a8f97..b61bbfd9a6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWrite.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWrite.kt @@ -14,44 +14,43 @@ import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.phys.Vec3 object OpTheCoolerWrite : SpellAction { - override val argc = 2 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val target = args.getEntity(0, argc) - val datum = args[1] - - env.assertEntityInRange(target) - - val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(target) - ?: throw MishapBadEntity.of(target, "iota.write") - - if (!datumHolder.writeIota(datum, true)) - throw MishapBadEntity.of(target, "iota.write") - - // We pass null here so that even the own caster won't be allowed into a focus. - // Otherwise, you could sentinel scout to people and remotely write their names into things using a cleric circle. - val trueName = MishapOthersName.getTrueNameFromDatum(datum, null) - if (trueName != null) - throw MishapOthersName(trueName) - - val burstPos = if (target is ItemEntity) { - // Special case these because the render is way above the entity - target.position().add(0.0, 3.0 / 8.0, 0.0) - } else { - target.position() - } - return SpellAction.Result( - Spell(datum, datumHolder), - 0, - listOf(ParticleSpray(burstPos, Vec3(1.0, 0.0, 0.0), 0.25, 3.14, 40)) - ) - } - - private data class Spell(val datum: Iota, val datumHolder: ADIotaHolder) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - datumHolder.writeIota(datum, false) - } - } + override val argc = 2 + + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val target = args.getEntity(0, argc) + val datum = args[1] + + env.assertEntityInRange(target) + + val datumHolder = + IXplatAbstractions.INSTANCE.findDataHolder(target) + ?: throw MishapBadEntity.of(target, "iota.write") + + if (!datumHolder.writeIota(datum, true)) throw MishapBadEntity.of(target, "iota.write") + + // We pass null here so that even the own caster won't be allowed into a focus. + // Otherwise, you could sentinel scout to people and remotely write their names into things + // using a cleric circle. + val trueName = MishapOthersName.getTrueNameFromDatum(datum, null) + if (trueName != null) throw MishapOthersName(trueName) + + val burstPos = + if (target is ItemEntity) { + // Special case these because the render is way above the entity + target.position().add(0.0, 3.0 / 8.0, 0.0) + } else { + target.position() + } + return SpellAction.Result( + Spell(datum, datumHolder), + 0, + listOf(ParticleSpray(burstPos, Vec3(1.0, 0.0, 0.0), 0.25, 3.14, 40)) + ) + } + + private data class Spell(val datum: Iota, val datumHolder: ADIotaHolder) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + datumHolder.writeIota(datum, false) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWritable.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWritable.kt index f0a3d0da10..c8716f6412 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWritable.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWritable.kt @@ -7,17 +7,19 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.xplat.IXplatAbstractions object OpWritable : ConstMediaAction { - override val argc = 0 + override val argc = 0 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val (handStack) = env.getHeldItemToOperateOn { - val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val (handStack) = + env.getHeldItemToOperateOn { + val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) - datumHolder != null - } ?: return false.asActionResult + datumHolder != null + } ?: return false.asActionResult - val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack) ?: return false.asActionResult - val success = datumHolder.writeable() - return success.asActionResult - } + val datumHolder = + IXplatAbstractions.INSTANCE.findDataHolder(handStack) ?: return false.asActionResult + val success = datumHolder.writeable() + return success.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt index 317dbc0453..b25c233e0d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt @@ -12,45 +12,41 @@ import net.minecraft.server.level.ServerPlayer // we make this a spell cause imo it's a little ... anticlimactic for it to just make no noise object OpWrite : SpellAction { - override val argc = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val datum = args[0] - - val (handStack) = env.getHeldItemToOperateOn { - val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) - - datumHolder != null && datumHolder.writeIota(datum, true) - } - // If there are no data holders that are writeable, find a data holder that isn't writeable - // so that the error message is more helpful. - ?: env.getHeldItemToOperateOn { - val dataHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) - dataHolder != null - } ?: throw MishapBadOffhandItem.of(null, "iota.write") - - val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack) - ?: throw MishapBadOffhandItem.of(handStack, "iota.write") - - if (!datumHolder.writeIota(datum, true)) - throw MishapBadOffhandItem.of(handStack, "iota.readonly", datum.display()) - - val trueName = MishapOthersName.getTrueNameFromDatum(datum, env.castingEntity as? ServerPlayer) - if (trueName != null) - throw MishapOthersName(trueName) - - return SpellAction.Result( - Spell(datum, datumHolder), - 0, - listOf() - ) - } - - private data class Spell(val datum: Iota, val datumHolder: ADIotaHolder) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - datumHolder.writeIota(datum, false) - } - } + override val argc = 1 + + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val datum = args[0] + + val (handStack) = + env.getHeldItemToOperateOn { + val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) + + datumHolder != null && datumHolder.writeIota(datum, true) + } + // If there are no data holders that are writeable, find a data holder that isn't writeable + // so that the error message is more helpful. + ?: env.getHeldItemToOperateOn { + val dataHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) + dataHolder != null + } + ?: throw MishapBadOffhandItem.of(null, "iota.write") + + val datumHolder = + IXplatAbstractions.INSTANCE.findDataHolder(handStack) + ?: throw MishapBadOffhandItem.of(handStack, "iota.write") + + if (!datumHolder.writeIota(datum, true)) + throw MishapBadOffhandItem.of(handStack, "iota.readonly", datum.display()) + + val trueName = MishapOthersName.getTrueNameFromDatum(datum, env.castingEntity as? ServerPlayer) + if (trueName != null) throw MishapOthersName(trueName) + + return SpellAction.Result(Spell(datum, datumHolder), 0, listOf()) + } + + private data class Spell(val datum: Iota, val datumHolder: ADIotaHolder) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + datumHolder.writeIota(datum, false) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/selectors/OpGetCaster.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/selectors/OpGetCaster.kt index d392927a2a..1bf9beb484 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/selectors/OpGetCaster.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/selectors/OpGetCaster.kt @@ -6,13 +6,12 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota object OpGetCaster : ConstMediaAction { - override val argc = 0 + override val argc = 0 - override fun execute(args: List<Iota>, ctx: CastingEnvironment): List<Iota> { - if (ctx.castingEntity == null) - return null.asActionResult + override fun execute(args: List<Iota>, ctx: CastingEnvironment): List<Iota> { + if (ctx.castingEntity == null) return null.asActionResult - ctx.assertEntityInRange(ctx.castingEntity) - return ctx.castingEntity.asActionResult - } + ctx.assertEntityInRange(ctx.castingEntity) + return ctx.castingEntity.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/selectors/OpGetEntitiesBy.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/selectors/OpGetEntitiesBy.kt index c3366c9aca..16e2775ada 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/selectors/OpGetEntitiesBy.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/selectors/OpGetEntitiesBy.kt @@ -7,6 +7,7 @@ import at.petrak.hexcasting.api.casting.getPositiveDouble import at.petrak.hexcasting.api.casting.getVec3 import at.petrak.hexcasting.api.casting.iota.EntityIota import at.petrak.hexcasting.api.casting.iota.Iota +import java.util.function.Predicate import net.minecraft.world.entity.Entity import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.animal.Animal @@ -17,41 +18,39 @@ import net.minecraft.world.entity.monster.Enemy import net.minecraft.world.entity.player.Player import net.minecraft.world.phys.AABB import net.minecraft.world.phys.Vec3 -import java.util.function.Predicate class OpGetEntitiesBy(val checker: Predicate<Entity>, val negate: Boolean) : ConstMediaAction { - override val argc = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val pos = args.getVec3(0, argc) - val radius = args.getPositiveDouble(1, argc) - env.assertVecInRange(pos) - - val aabb = AABB(pos.add(Vec3(-radius, -radius, -radius)), pos.add(Vec3(radius, radius, radius))) - val entitiesGot = env.world.getEntities(null, aabb) { - isReasonablySelectable(env, it) - && it.distanceToSqr(pos) <= radius * radius - && (checker.test(it) != negate) - }.sortedBy { it.distanceToSqr(pos) } - return entitiesGot.map(::EntityIota).asActionResult - } - - companion object { - fun isReasonablySelectable(ctx: CastingEnvironment, e: Entity) = - ctx.isEntityInRange(e) && e.isAlive && !e.isSpectator - - @JvmStatic - fun isAnimal(e: Entity): Boolean = e is Animal || e is WaterAnimal - - @JvmStatic - fun isMonster(e: Entity): Boolean = e is Enemy - - @JvmStatic - fun isItem(e: Entity): Boolean = e is ItemEntity - - @JvmStatic - fun isPlayer(e: Entity): Boolean = e is Player - - @JvmStatic - fun isLiving(e: Entity): Boolean = (e is LivingEntity) || (e is EnderDragonPart) - } + override val argc = 2 + + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val pos = args.getVec3(0, argc) + val radius = args.getPositiveDouble(1, argc) + env.assertVecInRange(pos) + + val aabb = AABB(pos.add(Vec3(-radius, -radius, -radius)), pos.add(Vec3(radius, radius, radius))) + val entitiesGot = + env.world + .getEntities(null, aabb) { + isReasonablySelectable(env, it) && + it.distanceToSqr(pos) <= radius * radius && + (checker.test(it) != negate) + } + .sortedBy { it.distanceToSqr(pos) } + return entitiesGot.map(::EntityIota).asActionResult + } + + companion object { + fun isReasonablySelectable(ctx: CastingEnvironment, e: Entity) = + ctx.isEntityInRange(e) && e.isAlive && !e.isSpectator + + @JvmStatic fun isAnimal(e: Entity): Boolean = e is Animal || e is WaterAnimal + + @JvmStatic fun isMonster(e: Entity): Boolean = e is Enemy + + @JvmStatic fun isItem(e: Entity): Boolean = e is ItemEntity + + @JvmStatic fun isPlayer(e: Entity): Boolean = e is Player + + @JvmStatic fun isLiving(e: Entity): Boolean = (e is LivingEntity) || (e is EnderDragonPart) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/selectors/OpGetEntityAt.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/selectors/OpGetEntityAt.kt index 55de453738..fe0ac78386 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/selectors/OpGetEntityAt.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/selectors/OpGetEntityAt.kt @@ -5,22 +5,26 @@ import at.petrak.hexcasting.api.casting.castables.ConstMediaAction import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.getVec3 import at.petrak.hexcasting.api.casting.iota.Iota +import java.util.function.Predicate import net.minecraft.world.entity.Entity import net.minecraft.world.phys.AABB import net.minecraft.world.phys.Vec3 -import java.util.function.Predicate class OpGetEntityAt(val checker: Predicate<Entity>) : ConstMediaAction { - override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val pos = args.getVec3(0, argc) - env.assertVecInRange(pos) - val aabb = AABB(pos.add(Vec3(-0.5, -0.5, -0.5)), pos.add(Vec3(0.5, 0.5, 0.5))) - val entitiesGot = env.world.getEntities(null, aabb) { - OpGetEntitiesBy.isReasonablySelectable(env, it) && checker.test(it) - }.sortedBy { it.distanceToSqr(pos) } + override val argc = 1 + + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val pos = args.getVec3(0, argc) + env.assertVecInRange(pos) + val aabb = AABB(pos.add(Vec3(-0.5, -0.5, -0.5)), pos.add(Vec3(0.5, 0.5, 0.5))) + val entitiesGot = + env.world + .getEntities(null, aabb) { + OpGetEntitiesBy.isReasonablySelectable(env, it) && checker.test(it) + } + .sortedBy { it.distanceToSqr(pos) } - val entity = entitiesGot.getOrNull(0) - return entity.asActionResult - } + val entity = entitiesGot.getOrNull(0) + return entity.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpAddMotion.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpAddMotion.kt index 7f45168f85..0685e12fcf 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpAddMotion.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpAddMotion.kt @@ -14,51 +14,49 @@ import net.minecraft.world.entity.Entity import net.minecraft.world.phys.Vec3 object OpAddMotion : SpellAction { - override val argc: Int - get() = 2 - - // for bug #387 - val MAX_MOTION: Double = 8192.0 - - override fun executeWithUserdata( - args: List<Iota>, - env: CastingEnvironment, - userData: CompoundTag - ): SpellAction.Result { - val target = args.getEntity(0, argc) - val motion = args.getVec3(1, argc) - env.assertEntityInRange(target) - - var motionForCost = motion.lengthSqr() - if (CastingImage.checkAndMarkGivenMotion(userData, target)) - motionForCost++ - - val shrunkMotion = if (motion.lengthSqr() > MAX_MOTION * MAX_MOTION) - motion.normalize().scale(MAX_MOTION) - else - motion - return SpellAction.Result( - Spell(target, shrunkMotion), - (motionForCost * MediaConstants.DUST_UNIT).toLong(), - listOf( - ParticleSpray( - target.position().add(0.0, target.eyeHeight / 2.0, 0.0), - motion.normalize(), - 0.0, - 0.1 - ) - ), - ) - } - - override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { - throw IllegalStateException() - } - - private data class Spell(val target: Entity, val motion: Vec3) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - target.push(motion.x, motion.y, motion.z) - target.hurtMarked = true // Whyyyyy - } - } + override val argc: Int + get() = 2 + + // for bug #387 + val MAX_MOTION: Double = 8192.0 + + override fun executeWithUserdata( + args: List<Iota>, + env: CastingEnvironment, + userData: CompoundTag + ): SpellAction.Result { + val target = args.getEntity(0, argc) + val motion = args.getVec3(1, argc) + env.assertEntityInRange(target) + + var motionForCost = motion.lengthSqr() + if (CastingImage.checkAndMarkGivenMotion(userData, target)) motionForCost++ + + val shrunkMotion = + if (motion.lengthSqr() > MAX_MOTION * MAX_MOTION) motion.normalize().scale(MAX_MOTION) + else motion + return SpellAction.Result( + Spell(target, shrunkMotion), + (motionForCost * MediaConstants.DUST_UNIT).toLong(), + listOf( + ParticleSpray( + target.position().add(0.0, target.eyeHeight / 2.0, 0.0), + motion.normalize(), + 0.0, + 0.1 + ) + ), + ) + } + + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + throw IllegalStateException() + } + + private data class Spell(val target: Entity, val motion: Vec3) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + target.push(motion.x, motion.y, motion.z) + target.hurtMarked = true // Whyyyyy + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBeep.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBeep.kt index 74807561f3..73a6793898 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBeep.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBeep.kt @@ -12,30 +12,34 @@ import net.minecraft.world.level.gameevent.GameEvent import net.minecraft.world.phys.Vec3 object OpBeep : SpellAction { - override val argc = 3 + override val argc = 3 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val target = args.getVec3(0, argc) - val instrument = args.getPositiveIntUnder(1, NoteBlockInstrument.values().size, argc) - val note = args.getPositiveIntUnderInclusive(2, 24, argc) // mojang don't have magic numbers challenge - env.assertVecInRange(target) + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val target = args.getVec3(0, argc) + val instrument = args.getPositiveIntUnder(1, NoteBlockInstrument.values().size, argc) + val note = + args.getPositiveIntUnderInclusive(2, 24, argc) // mojang don't have magic numbers challenge + env.assertVecInRange(target) - return SpellAction.Result( - Spell(target, note, NoteBlockInstrument.values()[instrument]), - MediaConstants.DUST_UNIT / 10, - listOf(ParticleSpray.cloud(target, 1.0)) - ) - } + return SpellAction.Result( + Spell(target, note, NoteBlockInstrument.values()[instrument]), + MediaConstants.DUST_UNIT / 10, + listOf(ParticleSpray.cloud(target, 1.0)) + ) + } - override fun hasCastingSound(ctx: CastingEnvironment) = false + override fun hasCastingSound(ctx: CastingEnvironment) = false - private data class Spell(val target: Vec3, val note: Int, val instrument: NoteBlockInstrument) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - IXplatAbstractions.INSTANCE.sendPacketNear(target, 128.0, env.world, MsgBeepS2C(target, note, instrument)) - env.world.gameEvent(null, GameEvent.NOTE_BLOCK_PLAY, target) - } - } + private data class Spell(val target: Vec3, val note: Int, val instrument: NoteBlockInstrument) : + RenderedSpell { + override fun cast(env: CastingEnvironment) { + IXplatAbstractions.INSTANCE.sendPacketNear( + target, + 128.0, + env.world, + MsgBeepS2C(target, note, instrument) + ) + env.world.gameEvent(null, GameEvent.NOTE_BLOCK_PLAY, target) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBlink.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBlink.kt index f7fd817308..d3aeceb827 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBlink.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBlink.kt @@ -13,54 +13,50 @@ import at.petrak.hexcasting.api.misc.MediaConstants import at.petrak.hexcasting.api.mod.HexConfig import at.petrak.hexcasting.api.mod.HexTags import at.petrak.hexcasting.common.casting.actions.spells.great.OpTeleport -import net.minecraft.world.entity.Entity import kotlin.math.absoluteValue import kotlin.math.roundToLong +import net.minecraft.world.entity.Entity object OpBlink : SpellAction { - override val argc = 2 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val target = args.getEntity(0, argc) - val delta = args.getDouble(1, argc) - env.assertEntityInRange(target) - - if (!target.canChangeDimensions() || target.type.`is`(HexTags.Entities.CANNOT_TELEPORT)) - throw MishapImmuneEntity(target) - - val dvec = target.lookAngle.scale(delta) - val endPos = target.position().add(dvec) - - if (!HexConfig.server().canTeleportInThisDimension(env.world.dimension())) - throw MishapBadLocation(endPos, "bad_dimension") - - env.assertVecInRange(target.position()) - env.assertVecInRange(endPos) - if (!env.isVecInWorld(endPos.subtract(0.0, 1.0, 0.0))) - throw MishapBadLocation(endPos, "too_close_to_out") - - - val targetMiddlePos = target.position().add(0.0, target.eyeHeight / 2.0, 0.0) - - return SpellAction.Result( - Spell(target, delta), - (MediaConstants.SHARD_UNIT * delta.absoluteValue * 0.5).roundToLong(), - listOf( - ParticleSpray.cloud(targetMiddlePos, 2.0, 50), - ParticleSpray.burst(targetMiddlePos.add(dvec), 2.0, 100) - ) - ) - } - - private data class Spell(val target: Entity, val delta: Double) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - if (!HexConfig.server().canTeleportInThisDimension(env.world.dimension())) - return - - val delta = target.lookAngle.scale(delta) - OpTeleport.teleportRespectSticky(target, delta, env.world) - } - } + override val argc = 2 + + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val target = args.getEntity(0, argc) + val delta = args.getDouble(1, argc) + env.assertEntityInRange(target) + + if (!target.canChangeDimensions() || target.type.`is`(HexTags.Entities.CANNOT_TELEPORT)) + throw MishapImmuneEntity(target) + + val dvec = target.lookAngle.scale(delta) + val endPos = target.position().add(dvec) + + if (!HexConfig.server().canTeleportInThisDimension(env.world.dimension())) + throw MishapBadLocation(endPos, "bad_dimension") + + env.assertVecInRange(target.position()) + env.assertVecInRange(endPos) + if (!env.isVecInWorld(endPos.subtract(0.0, 1.0, 0.0))) + throw MishapBadLocation(endPos, "too_close_to_out") + + val targetMiddlePos = target.position().add(0.0, target.eyeHeight / 2.0, 0.0) + + return SpellAction.Result( + Spell(target, delta), + (MediaConstants.SHARD_UNIT * delta.absoluteValue * 0.5).roundToLong(), + listOf( + ParticleSpray.cloud(targetMiddlePos, 2.0, 50), + ParticleSpray.burst(targetMiddlePos.add(dvec), 2.0, 100) + ) + ) + } + + private data class Spell(val target: Entity, val delta: Double) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + if (!HexConfig.server().canTeleportInThisDimension(env.world.dimension())) return + + val delta = target.lookAngle.scale(delta) + OpTeleport.teleportRespectSticky(target, delta, env.world) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBreakBlock.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBreakBlock.kt index 796e82ccd0..362b7365e7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBreakBlock.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBreakBlock.kt @@ -15,44 +15,42 @@ import net.minecraft.server.level.ServerPlayer import net.minecraft.world.phys.Vec3 object OpBreakBlock : SpellAction { - override val argc: Int - get() = 1 + override val argc: Int + get() = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val vecPos = args.getVec3(0, argc) - val pos = BlockPos.containing(vecPos) - env.assertPosInRangeForEditing(pos) + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val vecPos = args.getVec3(0, argc) + val pos = BlockPos.containing(vecPos) + env.assertPosInRangeForEditing(pos) - val isCheap = env.world.getBlockState(pos).`is`(HexTags.Blocks.CHEAP_TO_BREAK_BLOCK) + val isCheap = env.world.getBlockState(pos).`is`(HexTags.Blocks.CHEAP_TO_BREAK_BLOCK) - return SpellAction.Result( - Spell(pos), - if (isCheap) MediaConstants.DUST_UNIT / 100 else MediaConstants.DUST_UNIT / 8, - listOf(ParticleSpray.burst(Vec3.atCenterOf(pos), 1.0)) - ) - } + return SpellAction.Result( + Spell(pos), + if (isCheap) MediaConstants.DUST_UNIT / 100 else MediaConstants.DUST_UNIT / 8, + listOf(ParticleSpray.burst(Vec3.atCenterOf(pos), 1.0)) + ) + } - private data class Spell(val pos: BlockPos) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - val blockstate = env.world.getBlockState(pos) - val tier = HexConfig.server().opBreakHarvestLevel() + private data class Spell(val pos: BlockPos) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + val blockstate = env.world.getBlockState(pos) + val tier = HexConfig.server().opBreakHarvestLevel() - if ( - !blockstate.isAir - && blockstate.getDestroySpeed(env.world, pos) >= 0f // fix being able to break bedrock &c - && IXplatAbstractions.INSTANCE.isCorrectTierForDrops(tier, blockstate) - && IXplatAbstractions.INSTANCE.isBreakingAllowed( - env.world, - pos, - blockstate, - env.castingEntity as? ServerPlayer - ) - ) { - env.world.destroyBlock(pos, true, env.castingEntity) - } - } - } + if ( + !blockstate.isAir && + blockstate.getDestroySpeed(env.world, pos) >= 0f // fix being able to break bedrock &c + && + IXplatAbstractions.INSTANCE.isCorrectTierForDrops(tier, blockstate) && + IXplatAbstractions.INSTANCE.isBreakingAllowed( + env.world, + pos, + blockstate, + env.castingEntity as? ServerPlayer + ) + ) { + env.world.destroyBlock(pos, true, env.castingEntity) + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpColorize.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpColorize.kt index ba4c407c4a..c257a9d0a9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpColorize.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpColorize.kt @@ -12,34 +12,25 @@ import net.minecraft.Util import net.minecraft.world.item.ItemStack object OpColorize : SpellAction { - override val argc = 0 + override val argc = 0 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val (handStack) = env.getHeldItemToOperateOn(IXplatAbstractions.INSTANCE::isPigment) - ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY, "colorizer") // TODO: hack + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val (handStack) = + env.getHeldItemToOperateOn(IXplatAbstractions.INSTANCE::isPigment) + ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY, "colorizer") // TODO: hack - if (!IXplatAbstractions.INSTANCE.isPigment(handStack)) { - throw MishapBadOffhandItem.of( - handStack, - "colorizer" - ) - } + if (!IXplatAbstractions.INSTANCE.isPigment(handStack)) { + throw MishapBadOffhandItem.of(handStack, "colorizer") + } - return SpellAction.Result( - Spell(handStack), - MediaConstants.DUST_UNIT, - listOf() - ) - } + return SpellAction.Result(Spell(handStack), MediaConstants.DUST_UNIT, listOf()) + } - private data class Spell(val stack: ItemStack) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - val copy = stack.copy() - if (env.withdrawItem({ ItemStack.isSameItemSameTags(copy, it) }, 1, true)) - env.setPigment(FrozenPigment(copy, env.castingEntity?.uuid ?: Util.NIL_UUID)) - } - } + private data class Spell(val stack: ItemStack) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + val copy = stack.copy() + if (env.withdrawItem({ ItemStack.isSameItemSameTags(copy, it) }, 1, true)) + env.setPigment(FrozenPigment(copy, env.castingEntity?.uuid ?: Util.NIL_UUID)) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpConjureBlock.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpConjureBlock.kt index b77d7dd06a..444ba3dce5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpConjureBlock.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpConjureBlock.kt @@ -19,54 +19,59 @@ import net.minecraft.world.item.context.DirectionalPlaceContext import net.minecraft.world.phys.Vec3 class OpConjureBlock(val light: Boolean) : SpellAction { - override val argc = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val vecPos = args.getVec3(0, argc) - val pos = BlockPos.containing(vecPos) - env.assertPosInRangeForEditing(pos) + override val argc = 1 - val placeContext = DirectionalPlaceContext(env.world, pos, Direction.DOWN, ItemStack.EMPTY, Direction.UP) + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val vecPos = args.getVec3(0, argc) + val pos = BlockPos.containing(vecPos) + env.assertPosInRangeForEditing(pos) - val worldState = env.world.getBlockState(pos) - if (!worldState.canBeReplaced(placeContext)) - throw MishapBadBlock.of(pos, "replaceable") + val placeContext = + DirectionalPlaceContext(env.world, pos, Direction.DOWN, ItemStack.EMPTY, Direction.UP) - return SpellAction.Result( - Spell(pos, light), - MediaConstants.DUST_UNIT, - listOf(ParticleSpray.cloud(Vec3.atCenterOf(pos), 1.0)) - ) - } + val worldState = env.world.getBlockState(pos) + if (!worldState.canBeReplaced(placeContext)) throw MishapBadBlock.of(pos, "replaceable") - private data class Spell(val pos: BlockPos, val light: Boolean) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - if (!env.canEditBlockAt(pos)) - return + return SpellAction.Result( + Spell(pos, light), + MediaConstants.DUST_UNIT, + listOf(ParticleSpray.cloud(Vec3.atCenterOf(pos), 1.0)) + ) + } - val placeContext = DirectionalPlaceContext(env.world, pos, Direction.DOWN, ItemStack.EMPTY, Direction.UP) + private data class Spell(val pos: BlockPos, val light: Boolean) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + if (!env.canEditBlockAt(pos)) return - val worldState = env.world.getBlockState(pos) - if (worldState.canBeReplaced(placeContext)) { - val block = if (this.light) HexBlocks.CONJURED_LIGHT else HexBlocks.CONJURED_BLOCK + val placeContext = + DirectionalPlaceContext(env.world, pos, Direction.DOWN, ItemStack.EMPTY, Direction.UP) - if (!IXplatAbstractions.INSTANCE.isPlacingAllowed(env.world, pos, ItemStack(block), env.castingEntity as? ServerPlayer)) - return + val worldState = env.world.getBlockState(pos) + if (worldState.canBeReplaced(placeContext)) { + val block = if (this.light) HexBlocks.CONJURED_LIGHT else HexBlocks.CONJURED_BLOCK - val state = block.getStateForPlacement(placeContext) - if (state != null) { - // 1 = block updated + 2 = send to clients - env.world.setBlock(pos, state, 3) + if ( + !IXplatAbstractions.INSTANCE.isPlacingAllowed( + env.world, + pos, + ItemStack(block), + env.castingEntity as? ServerPlayer + ) + ) + return - val pigment = env.pigment + val state = block.getStateForPlacement(placeContext) + if (state != null) { + // 1 = block updated + 2 = send to clients + env.world.setBlock(pos, state, 3) - if (env.world.getBlockState(pos).block is BlockConjured) { - BlockConjured.setColor(env.world, pos, pigment) - } - } - } - } - } + val pigment = env.pigment + + if (env.world.getBlockState(pos).block is BlockConjured) { + BlockConjured.setColor(env.world, pos, pigment) + } + } + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpCreateFluid.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpCreateFluid.kt index 46c0662619..b2d6e1be31 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpCreateFluid.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpCreateFluid.kt @@ -18,47 +18,50 @@ import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.material.Fluid import net.minecraft.world.phys.Vec3 -class OpCreateFluid(val cost: Long, val bucket: Item, val cauldron: BlockState, val fluid: Fluid) : SpellAction { - override val argc = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val vecPos = args.getVec3(0, argc) - val pos = BlockPos.containing(vecPos) +class OpCreateFluid(val cost: Long, val bucket: Item, val cauldron: BlockState, val fluid: Fluid) : + SpellAction { + override val argc = 1 - if (!env.canEditBlockAt(pos) || !IXplatAbstractions.INSTANCE.isPlacingAllowed( - env.world, - pos, - ItemStack(bucket), - env.castingEntity as? ServerPlayer - ) - ) - throw MishapBadLocation(vecPos, "forbidden") + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val vecPos = args.getVec3(0, argc) + val pos = BlockPos.containing(vecPos) - return SpellAction.Result( - Spell(pos, bucket, cauldron, fluid), - cost, - listOf(ParticleSpray.burst(Vec3.atCenterOf(BlockPos(pos)), 1.0)) - ) - } + if ( + !env.canEditBlockAt(pos) || + !IXplatAbstractions.INSTANCE.isPlacingAllowed( + env.world, + pos, + ItemStack(bucket), + env.castingEntity as? ServerPlayer + ) + ) + throw MishapBadLocation(vecPos, "forbidden") - private data class Spell(val pos: BlockPos, val bucket: Item, val cauldron: BlockState, val fluid: Fluid) : RenderedSpell { - override fun cast(env: CastingEnvironment) { + return SpellAction.Result( + Spell(pos, bucket, cauldron, fluid), + cost, + listOf(ParticleSpray.burst(Vec3.atCenterOf(BlockPos(pos)), 1.0)) + ) + } - val state = env.world.getBlockState(pos) + private data class Spell( + val pos: BlockPos, + val bucket: Item, + val cauldron: BlockState, + val fluid: Fluid + ) : RenderedSpell { + override fun cast(env: CastingEnvironment) { - if (state.block == Blocks.CAULDRON) - env.world.setBlock(pos, cauldron, 3) - else if (!IXplatAbstractions.INSTANCE.tryPlaceFluid( - env.world, - env.castingHand, - pos, - fluid - ) && bucket is BucketItem) { - // make the player null so we don't give them a usage statistic for example - bucket.emptyContents(null, env.world, pos, null) - } - } - } + val state = env.world.getBlockState(pos) + + if (state.block == Blocks.CAULDRON) env.world.setBlock(pos, cauldron, 3) + else if ( + !IXplatAbstractions.INSTANCE.tryPlaceFluid(env.world, env.castingHand, pos, fluid) && + bucket is BucketItem + ) { + // make the player null so we don't give them a usage statistic for example + bucket.emptyContents(null, env.world, pos, null) + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpCycleVariant.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpCycleVariant.kt index e49e6e70af..be7d7911c6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpCycleVariant.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpCycleVariant.kt @@ -10,26 +10,23 @@ import at.petrak.hexcasting.xplat.IXplatAbstractions import net.minecraft.world.item.ItemStack object OpCycleVariant : SpellAction { - override val argc = 0 + override val argc = 0 - override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { - val (handStack) = env.getHeldItemToOperateOn { - IXplatAbstractions.INSTANCE.findVariantHolder(it) != null - } ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), "variant") // TODO: hack + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val (handStack) = + env.getHeldItemToOperateOn { IXplatAbstractions.INSTANCE.findVariantHolder(it) != null } + ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), "variant") // TODO: hack - val variantHolder = IXplatAbstractions.INSTANCE.findVariantHolder(handStack) - ?: throw MishapBadOffhandItem.of(handStack, "variant") + val variantHolder = + IXplatAbstractions.INSTANCE.findVariantHolder(handStack) + ?: throw MishapBadOffhandItem.of(handStack, "variant") - return SpellAction.Result( - Spell(variantHolder), - 0, - listOf() - ) - } + return SpellAction.Result(Spell(variantHolder), 0, listOf()) + } - private data class Spell(val variantHolder: ADVariantItem) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - variantHolder.variant = (variantHolder.variant + 1) % variantHolder.numVariants() - } - } -} \ No newline at end of file + private data class Spell(val variantHolder: ADVariantItem) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + variantHolder.variant = (variantHolder.variant + 1) % variantHolder.numVariants() + } + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpDestroyFluid.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpDestroyFluid.kt index 73b1ac569f..acbfdad10a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpDestroyFluid.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpDestroyFluid.kt @@ -21,117 +21,116 @@ import net.minecraft.world.level.material.Fluids import net.minecraft.world.phys.Vec3 object OpDestroyFluid : SpellAction { - override val argc = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val vecPos = args.getVec3(0, argc) - val pos = BlockPos.containing(vecPos) - env.assertPosInRangeForEditing(pos) + override val argc = 1 - return SpellAction.Result( - Spell(pos), - 2 * MediaConstants.CRYSTAL_UNIT, - listOf(ParticleSpray.burst(Vec3.atCenterOf(pos), 3.0)) - ) - } + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val vecPos = args.getVec3(0, argc) + val pos = BlockPos.containing(vecPos) + env.assertPosInRangeForEditing(pos) - const val MAX_DESTROY_COUNT = 1024 + return SpellAction.Result( + Spell(pos), + 2 * MediaConstants.CRYSTAL_UNIT, + listOf(ParticleSpray.burst(Vec3.atCenterOf(pos), 3.0)) + ) + } - private data class Spell(val basePos: BlockPos) : RenderedSpell { + const val MAX_DESTROY_COUNT = 1024 - override fun cast(env: CastingEnvironment) { - // Try draining from fluid handlers first, and if so, don't do the normal behavior - if (IXplatAbstractions.INSTANCE.drainAllFluid(env.world, basePos)) { - return - } else { - val state = env.world.getBlockState(basePos) - if (state.block is AbstractCauldronBlock && state.block != Blocks.CAULDRON) { - env.world.setBlock(basePos, Blocks.CAULDRON.defaultBlockState(), 3) - return - } - } + private data class Spell(val basePos: BlockPos) : RenderedSpell { - // SpongeBlock.java - val todo = ArrayDeque<BlockPos>() - val seen = HashSet<BlockPos>() + override fun cast(env: CastingEnvironment) { + // Try draining from fluid handlers first, and if so, don't do the normal behavior + if (IXplatAbstractions.INSTANCE.drainAllFluid(env.world, basePos)) { + return + } else { + val state = env.world.getBlockState(basePos) + if (state.block is AbstractCauldronBlock && state.block != Blocks.CAULDRON) { + env.world.setBlock(basePos, Blocks.CAULDRON.defaultBlockState(), 3) + return + } + } - // a little extra range on the initial cast to make it feel more intuitive - for (xShift in -2..2) for (yShift in -2..2) for (zShift in -2..2) { - todo.add(basePos.offset(xShift, yShift, zShift)) - } + // SpongeBlock.java + val todo = ArrayDeque<BlockPos>() + val seen = HashSet<BlockPos>() - var successes = 0 - while (todo.isNotEmpty() && successes <= MAX_DESTROY_COUNT) { - val here = todo.removeFirst() - if (env.canEditBlockAt(here) && seen.add(here)) { - // never seen this pos in my life - val fluid = env.world.getFluidState(here) - if (fluid != Fluids.EMPTY.defaultFluidState()) { - val blockstate = env.world.getBlockState(here) - if (IXplatAbstractions.INSTANCE.isBreakingAllowed( - env.world, - here, - blockstate, - env.castingEntity as? ServerPlayer - ) - ) { - val success = - if (blockstate.block is BucketPickup && !(blockstate.block as BucketPickup).pickupBlock( - env.world, - here, - blockstate - ).isEmpty - ) { - true - } else if (blockstate.block is LiquidBlock) { - env.world.setBlock(here, Blocks.AIR.defaultBlockState(), 3) - true - } else if (blockstate.tags.anyMatch { it == HexTags.Blocks.WATER_PLANTS }) { - val blockentity: BlockEntity? = - if (blockstate.hasBlockEntity()) env.world.getBlockEntity(here) else null - Block.dropResources(blockstate, env.world, here, blockentity) - env.world.setBlock(here, Blocks.AIR.defaultBlockState(), 3) - true - } else { - false - } + // a little extra range on the initial cast to make it feel more intuitive + for (xShift in -2..2) for (yShift in -2..2) for (zShift in -2..2) { + todo.add(basePos.offset(xShift, yShift, zShift)) + } - if (success) { - env.world.sendParticles( - ParticleTypes.SMOKE, - here.x + 0.5 + Math.random() * 0.4 - 0.2, - here.y + 0.5 + Math.random() * 0.4 - 0.2, - here.z + 0.5 + Math.random() * 0.4 - 0.2, - 2, - 0.0, - 0.05, - 0.0, - 0.0 - ) - successes++ - for (dir in Direction.values()) { - todo.add(here.relative(dir)) - } - } - } - } - } - } + var successes = 0 + while (todo.isNotEmpty() && successes <= MAX_DESTROY_COUNT) { + val here = todo.removeFirst() + if (env.canEditBlockAt(here) && seen.add(here)) { + // never seen this pos in my life + val fluid = env.world.getFluidState(here) + if (fluid != Fluids.EMPTY.defaultFluidState()) { + val blockstate = env.world.getBlockState(here) + if ( + IXplatAbstractions.INSTANCE.isBreakingAllowed( + env.world, + here, + blockstate, + env.castingEntity as? ServerPlayer + ) + ) { + val success = + if ( + blockstate.block is BucketPickup && + !(blockstate.block as BucketPickup) + .pickupBlock(env.world, here, blockstate) + .isEmpty + ) { + true + } else if (blockstate.block is LiquidBlock) { + env.world.setBlock(here, Blocks.AIR.defaultBlockState(), 3) + true + } else if (blockstate.tags.anyMatch { it == HexTags.Blocks.WATER_PLANTS }) { + val blockentity: BlockEntity? = + if (blockstate.hasBlockEntity()) env.world.getBlockEntity(here) else null + Block.dropResources(blockstate, env.world, here, blockentity) + env.world.setBlock(here, Blocks.AIR.defaultBlockState(), 3) + true + } else { + false + } - if (successes > 0) { - env.world.playSound( - null, - basePos.x + 0.5, - basePos.y + 0.5, - basePos.z + 0.5, - SoundEvents.FIRE_EXTINGUISH, - SoundSource.BLOCKS, - 1.0f, - 0.95f - ) - } - } - } + if (success) { + env.world.sendParticles( + ParticleTypes.SMOKE, + here.x + 0.5 + Math.random() * 0.4 - 0.2, + here.y + 0.5 + Math.random() * 0.4 - 0.2, + here.z + 0.5 + Math.random() * 0.4 - 0.2, + 2, + 0.0, + 0.05, + 0.0, + 0.0 + ) + successes++ + for (dir in Direction.values()) { + todo.add(here.relative(dir)) + } + } + } + } + } + } + + if (successes > 0) { + env.world.playSound( + null, + basePos.x + 0.5, + basePos.y + 0.5, + basePos.z + 0.5, + SoundEvents.FIRE_EXTINGUISH, + SoundSource.BLOCKS, + 1.0f, + 0.95f + ) + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpEdifySapling.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpEdifySapling.kt index 415d4c2a13..4615c40fbe 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpEdifySapling.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpEdifySapling.kt @@ -16,46 +16,49 @@ import net.minecraft.tags.BlockTags import net.minecraft.world.phys.Vec3 object OpEdifySapling : SpellAction { - override val argc = 1 + override val argc = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val vecPos = args.getVec3(0, argc) - val pos = BlockPos.containing(vecPos) - env.assertPosInRangeForEditing(pos) + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val vecPos = args.getVec3(0, argc) + val pos = BlockPos.containing(vecPos) + env.assertPosInRangeForEditing(pos) - val bs = env.world.getBlockState(pos) - if (!bs.`is`(BlockTags.SAPLINGS)) - throw MishapBadBlock.of(pos, "sapling") + val bs = env.world.getBlockState(pos) + if (!bs.`is`(BlockTags.SAPLINGS)) throw MishapBadBlock.of(pos, "sapling") - return SpellAction.Result( - Spell(pos), - MediaConstants.CRYSTAL_UNIT, - listOf(ParticleSpray(Vec3.atCenterOf(pos), Vec3(0.0, 2.0, 0.0), 0.1, Math.PI / 4, 100)) - ) - } + return SpellAction.Result( + Spell(pos), + MediaConstants.CRYSTAL_UNIT, + listOf(ParticleSpray(Vec3.atCenterOf(pos), Vec3(0.0, 2.0, 0.0), 0.1, Math.PI / 4, 100)) + ) + } - private data class Spell(val pos: BlockPos) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - val blockstate = env.world.getBlockState(pos) - if (!env.canEditBlockAt(pos) || - !IXplatAbstractions.INSTANCE.isBreakingAllowed(env.world, pos, blockstate, env.castingEntity as? ServerPlayer) - ) - return + private data class Spell(val pos: BlockPos) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + val blockstate = env.world.getBlockState(pos) + if ( + !env.canEditBlockAt(pos) || + !IXplatAbstractions.INSTANCE.isBreakingAllowed( + env.world, + pos, + blockstate, + env.castingEntity as? ServerPlayer + ) + ) + return - val bs = env.world.getBlockState(pos) - for (i in 0 until 8) { - val success = AkashicTreeGrower.INSTANCE.growTree( - env.world, - env.world.chunkSource.generator, - pos, - bs, - env.world.getRandom() - ) - if (success) break - } - } - } + val bs = env.world.getBlockState(pos) + for (i in 0 until 8) { + val success = + AkashicTreeGrower.INSTANCE.growTree( + env.world, + env.world.chunkSource.generator, + pos, + bs, + env.world.getRandom() + ) + if (success) break + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpErase.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpErase.kt index 85fc913276..e759179ed7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpErase.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpErase.kt @@ -10,45 +10,36 @@ import at.petrak.hexcasting.xplat.IXplatAbstractions import net.minecraft.world.item.ItemStack object OpErase : SpellAction { - override val argc = 0 - - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val (handStack) = env.getHeldItemToOperateOn { - val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(it) - val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) - - (hexHolder?.hasHex() == true) || - (datumHolder?.writeIota(null, true) == true) - } ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), "eraseable") // TODO: hack - - val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(handStack) - val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack) - - if ((hexHolder?.hasHex() != true) && - (datumHolder?.writeIota(null, true) != true) - ) { - throw MishapBadOffhandItem.of(handStack, "eraseable") - } - - return SpellAction.Result( - Spell(handStack), - MediaConstants.DUST_UNIT, listOf() - ) - } - - private data class Spell(val stack: ItemStack) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(stack) - val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(stack) - - if (hexHolder?.hasHex() == true) - hexHolder.clearHex() - - if (datumHolder != null && datumHolder.writeIota(null, true)) - datumHolder.writeIota(null, false) - } - } + override val argc = 0 + + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val (handStack) = + env.getHeldItemToOperateOn { + val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(it) + val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) + + (hexHolder?.hasHex() == true) || (datumHolder?.writeIota(null, true) == true) + } ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), "eraseable") // TODO: hack + + val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(handStack) + val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack) + + if ((hexHolder?.hasHex() != true) && (datumHolder?.writeIota(null, true) != true)) { + throw MishapBadOffhandItem.of(handStack, "eraseable") + } + + return SpellAction.Result(Spell(handStack), MediaConstants.DUST_UNIT, listOf()) + } + + private data class Spell(val stack: ItemStack) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(stack) + val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(stack) + + if (hexHolder?.hasHex() == true) hexHolder.clearHex() + + if (datumHolder != null && datumHolder.writeIota(null, true)) + datumHolder.writeIota(null, false) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpExplode.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpExplode.kt index 0bed07989c..ec20e3d52b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpExplode.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpExplode.kt @@ -16,52 +16,49 @@ import net.minecraft.world.phys.AABB import net.minecraft.world.phys.Vec3 class OpExplode(val fire: Boolean) : SpellAction { - override val argc: Int - get() = 2 + override val argc: Int + get() = 2 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - var pos = args.getVec3(0, argc) - val strength = args.getPositiveDoubleUnderInclusive(1, 10.0, argc) - env.assertVecInRange(pos) + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + var pos = args.getVec3(0, argc) + val strength = args.getPositiveDoubleUnderInclusive(1, 10.0, argc) + env.assertVecInRange(pos) - // Prevent the footgun of explosions exactly at an entity's eye position not doing damage - val eps = 0.01; - val epsv = Vec3(eps, eps, eps) - val aabb = AABB(pos.subtract(epsv), pos.add(epsv)) - val tooCloseToEyePos = env.world.getEntities(null, aabb) { - OpGetEntitiesBy.isReasonablySelectable(env, it) - }.any { it.eyePosition.distanceToSqr(pos) == 0.0 } - if (tooCloseToEyePos) { - pos = pos.add(0.0, 0.000001, 0.0) - } + // Prevent the footgun of explosions exactly at an entity's eye position not doing damage + val eps = 0.01 + val epsv = Vec3(eps, eps, eps) + val aabb = AABB(pos.subtract(epsv), pos.add(epsv)) + val tooCloseToEyePos = + env.world + .getEntities(null, aabb) { OpGetEntitiesBy.isReasonablySelectable(env, it) } + .any { it.eyePosition.distanceToSqr(pos) == 0.0 } + if (tooCloseToEyePos) { + pos = pos.add(0.0, 0.000001, 0.0) + } - val clampedStrength = Mth.clamp(strength, 0.0, 10.0) - val cost = MediaConstants.DUST_UNIT * (3 * clampedStrength + if (fire) 1.0 else 0.125) - return SpellAction.Result( - Spell(pos, strength, this.fire), - cost.toLong(), - listOf(ParticleSpray.burst(pos, strength, 50)) - ) - } + val clampedStrength = Mth.clamp(strength, 0.0, 10.0) + val cost = MediaConstants.DUST_UNIT * (3 * clampedStrength + if (fire) 1.0 else 0.125) + return SpellAction.Result( + Spell(pos, strength, this.fire), + cost.toLong(), + listOf(ParticleSpray.burst(pos, strength, 50)) + ) + } - private data class Spell(val pos: Vec3, val strength: Double, val fire: Boolean) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - // TODO: you can use this to explode things *outside* of the worldborder? - if (!env.canEditBlockAt(BlockPos.containing(pos))) - return + private data class Spell(val pos: Vec3, val strength: Double, val fire: Boolean) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + // TODO: you can use this to explode things *outside* of the worldborder? + if (!env.canEditBlockAt(BlockPos.containing(pos))) return - env.world.explode( - env.castingEntity, - pos.x, - pos.y, - pos.z, - strength.toFloat(), - this.fire, - Level.ExplosionInteraction.TNT - ) - } - } + env.world.explode( + env.castingEntity, + pos.x, + pos.y, + pos.z, + strength.toFloat(), + this.fire, + Level.ExplosionInteraction.TNT + ) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpExtinguish.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpExtinguish.kt index 0d731159dd..9ac887d357 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpExtinguish.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpExtinguish.kt @@ -23,110 +23,116 @@ import net.minecraft.world.phys.BlockHitResult import net.minecraft.world.phys.Vec3 object OpExtinguish : SpellAction { - override val argc = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - // TODO: sho - val vecPos = args.getVec3(0, argc) - val pos = BlockPos.containing(vecPos) - env.assertPosInRangeForEditing(pos) + override val argc = 1 - return SpellAction.Result( - Spell(pos), - MediaConstants.DUST_UNIT * 6, - listOf(ParticleSpray.burst(Vec3.atCenterOf(pos), 1.0)) - ) - } + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + // TODO: sho + val vecPos = args.getVec3(0, argc) + val pos = BlockPos.containing(vecPos) + env.assertPosInRangeForEditing(pos) - const val MAX_DESTROY_COUNT = 1024 + return SpellAction.Result( + Spell(pos), + MediaConstants.DUST_UNIT * 6, + listOf(ParticleSpray.burst(Vec3.atCenterOf(pos), 1.0)) + ) + } - private data class Spell(val target: BlockPos) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - // how many levels of "borrowed" code are we on now - val todo = ArrayDeque<BlockPos>() - val seen = HashSet<BlockPos>() - todo.add(target) + const val MAX_DESTROY_COUNT = 1024 - var successes = 0 - while (todo.isNotEmpty() && successes <= MAX_DESTROY_COUNT) { - val here = todo.removeFirst() - val distFromTarget = - target.distSqr(here) // max distance to prevent runaway shenanigans - if (env.canEditBlockAt(here) && distFromTarget < 10 * 10 && seen.add(here)) { - // never seen this pos in my life - val blockstate = env.world.getBlockState(here) - if (IXplatAbstractions.INSTANCE.isBreakingAllowed(env.world, here, blockstate, env.castingEntity as? ServerPlayer)) { - val success = - when (blockstate.block) { - is BaseFireBlock -> { - env.world.setBlock(here, Blocks.AIR.defaultBlockState(), 3); true - } + private data class Spell(val target: BlockPos) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + // how many levels of "borrowed" code are we on now + val todo = ArrayDeque<BlockPos>() + val seen = HashSet<BlockPos>() + todo.add(target) - is CampfireBlock -> { - if (blockstate.getValue(CampfireBlock.LIT)) { // check if campfire is lit before putting it out - val wilson = - Items.WOODEN_SHOVEL // summon shovel from the ether to do our bidding - val hereVec = Vec3.atCenterOf(here) - wilson.useOn( - UseOnContext( - env.world, - null, - InteractionHand.MAIN_HAND, - ItemStack(wilson), - BlockHitResult(hereVec, Direction.UP, here, false) - ) - ); true - } else false - } + var successes = 0 + while (todo.isNotEmpty() && successes <= MAX_DESTROY_COUNT) { + val here = todo.removeFirst() + val distFromTarget = target.distSqr(here) // max distance to prevent runaway shenanigans + if (env.canEditBlockAt(here) && distFromTarget < 10 * 10 && seen.add(here)) { + // never seen this pos in my life + val blockstate = env.world.getBlockState(here) + if ( + IXplatAbstractions.INSTANCE.isBreakingAllowed( + env.world, + here, + blockstate, + env.castingEntity as? ServerPlayer + ) + ) { + val success = + when (blockstate.block) { + is BaseFireBlock -> { + env.world.setBlock(here, Blocks.AIR.defaultBlockState(), 3) + true + } + is CampfireBlock -> { + if ( + blockstate.getValue(CampfireBlock.LIT) + ) { // check if campfire is lit before putting it out + val wilson = + Items.WOODEN_SHOVEL // summon shovel from the ether to do our bidding + val hereVec = Vec3.atCenterOf(here) + wilson.useOn( + UseOnContext( + env.world, + null, + InteractionHand.MAIN_HAND, + ItemStack(wilson), + BlockHitResult(hereVec, Direction.UP, here, false) + ) + ) + true + } else false + } + is AbstractCandleBlock -> { + if (blockstate.getValue(AbstractCandleBlock.LIT)) { // same check for candles + AbstractCandleBlock.extinguish(null, blockstate, env.world, here) + true + } else false + } + is NetherPortalBlock -> { + env.world.setBlock(here, Blocks.AIR.defaultBlockState(), 3) + true + } + else -> false + } - is AbstractCandleBlock -> { - if (blockstate.getValue(AbstractCandleBlock.LIT)) { // same check for candles - AbstractCandleBlock.extinguish(null, blockstate, env.world, here); true - } else false - } + if (success) { + env.world.sendParticles( + ParticleTypes.SMOKE, + here.x + 0.5 + Math.random() * 0.4 - 0.2, + here.y + 0.5 + Math.random() * 0.4 - 0.2, + here.z + 0.5 + Math.random() * 0.4 - 0.2, + 2, + 0.0, + 0.05, + 0.0, + 0.0 + ) + successes++ + } + for (dir in Direction.values()) { + todo.add(here.relative(dir)) + } + } + } + } - is NetherPortalBlock -> { - env.world.setBlock(here, Blocks.AIR.defaultBlockState(), 3); true - } - - else -> false - } - - if (success) { - env.world.sendParticles( - ParticleTypes.SMOKE, - here.x + 0.5 + Math.random() * 0.4 - 0.2, - here.y + 0.5 + Math.random() * 0.4 - 0.2, - here.z + 0.5 + Math.random() * 0.4 - 0.2, - 2, - 0.0, - 0.05, - 0.0, - 0.0 - ) - successes++ - } - for (dir in Direction.values()) { - todo.add(here.relative(dir)) - } - } - } - } - - if (successes > 0) { - env.world.playSound( - null, - target.x.toDouble(), - target.y.toDouble(), - target.z.toDouble(), - SoundEvents.FIRE_EXTINGUISH, - SoundSource.BLOCKS, - 1.0f, - 0.95f - ) - } - } - } + if (successes > 0) { + env.world.playSound( + null, + target.x.toDouble(), + target.y.toDouble(), + target.z.toDouble(), + SoundEvents.FIRE_EXTINGUISH, + SoundSource.BLOCKS, + 1.0f, + 0.95f + ) + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt index 9258cc059e..1d62962a26 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt @@ -13,6 +13,9 @@ import at.petrak.hexcasting.api.player.FlightAbility import at.petrak.hexcasting.common.lib.HexItems import at.petrak.hexcasting.common.lib.HexSounds import at.petrak.hexcasting.xplat.IXplatAbstractions +import kotlin.math.max +import kotlin.math.roundToInt +import kotlin.math.roundToLong import net.minecraft.Util import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerPlayer @@ -21,178 +24,215 @@ import net.minecraft.util.Mth import net.minecraft.world.item.DyeColor import net.minecraft.world.item.ItemStack import net.minecraft.world.phys.Vec3 -import kotlin.math.max -import kotlin.math.roundToInt -import kotlin.math.roundToLong class OpFlight(val type: Type) : SpellAction { - override val argc = 2 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val target = args.getPlayer(0, argc) - val theArg = args.getPositiveDouble(1, argc) - env.assertEntityInRange(target) - - val cost = when (this.type) { - Type.LimitRange -> theArg * MediaConstants.DUST_UNIT - // A second of flight should cost 1 shard - Type.LimitTime -> theArg * MediaConstants.SHARD_UNIT - }.roundToLong() - - // Convert to ticks - return SpellAction.Result( - Spell(this.type, target, theArg), - cost, - listOf(ParticleSpray(target.position(), Vec3(0.0, 2.0, 0.0), 0.0, 0.1)) - ) - } - - enum class Type { - LimitRange, - LimitTime; - - } - - data class Spell(val type: Type, val target: ServerPlayer, val theArg: Double) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - if (target.abilities.mayfly) { - // Don't accidentally clobber someone else's flight - // TODO make this a mishap? - return - } - - val dim = target.level().dimension() - val origin = target.position() - - val flight = when (this.type) { - Type.LimitRange -> FlightAbility(-1, dim, origin, theArg) - Type.LimitTime -> FlightAbility((theArg * 20.0).roundToInt(), dim, origin, -1.0) - } - - IXplatAbstractions.INSTANCE.setFlight(target, flight) - - target.abilities.mayfly = true - target.onUpdateAbilities() - } - } - - - companion object { - // blocks from the edge - private val DIST_DANGER_THRESHOLD = 4.0 - - // seconds left - private val TIME_DANGER_THRESHOLD = 7.0 * 20.0 - - @JvmStatic - fun tickAllPlayers(world: ServerLevel) { - for (player in world.players()) { - tickDownFlight(player) - } - } - - @JvmStatic - fun tickDownFlight(player: ServerPlayer) { - val flight = IXplatAbstractions.INSTANCE.getFlight(player) - - if (flight != null) { - val danger = getDanger(player, flight) - if (danger >= 1.0) { - IXplatAbstractions.INSTANCE.setFlight(player, null) - // stop shin smashing bonke - - if (!player.isCreative && !player.isSpectator) { - val abilities = player.abilities - abilities.flying = false - abilities.mayfly = false - player.onUpdateAbilities() - } - player.level().playSound(null, player.x, player.y, player.z, HexSounds.FLIGHT_FINISH, SoundSource.PLAYERS, 2f, 1f) - val superDangerSpray = ParticleSpray(player.position(), Vec3(0.0, 1.0, 0.0), Math.PI, 0.4, count = 20) - superDangerSpray.sprayParticles(player.serverLevel(), FrozenPigment(ItemStack(HexItems.DYE_PIGMENTS[DyeColor.RED]!!), Util.NIL_UUID)) - superDangerSpray.sprayParticles(player.serverLevel(), FrozenPigment(ItemStack(HexItems.DYE_PIGMENTS[DyeColor.BLACK]!!), Util.NIL_UUID)) - } else { - if (!player.abilities.mayfly) { - player.abilities.mayfly = true - player.onUpdateAbilities() - } - val time2 = if (flight.timeLeft >= 0) { - flight.timeLeft - 1 - } else { - flight.timeLeft - } - IXplatAbstractions.INSTANCE.setFlight( - player, - FlightAbility( - time2, - flight.dimension, - flight.origin, - flight.radius - ) - ) - - val particleCount = 5 - val dangerParticleCount = (particleCount * danger).roundToInt() - val okParticleCount = particleCount - dangerParticleCount - val oneDangerParticleCount = Mth.ceil(dangerParticleCount / 2.0) - val color = IXplatAbstractions.INSTANCE.getPigment(player) - - // TODO: have the particles go in the opposite direction of the velocity? - ParticleSpray(player.position(), Vec3(0.0, -0.6, 0.0), 0.6, Math.PI * 0.3, count = okParticleCount) - .sprayParticles(player.serverLevel(), color) - val dangerSpray = ParticleSpray(player.position(), Vec3(0.0, 1.0, 0.0), 0.3, Math.PI * 0.75, count = 0) - dangerSpray.copy(count = oneDangerParticleCount) - .sprayParticles(player.serverLevel(), FrozenPigment(ItemStack(HexItems.DYE_PIGMENTS[DyeColor.BLACK]!!), Util.NIL_UUID)) - dangerSpray.copy(count = oneDangerParticleCount) - .sprayParticles(player.serverLevel(), FrozenPigment(ItemStack(HexItems.DYE_PIGMENTS[DyeColor.RED]!!), Util.NIL_UUID)) - - if (player.level().random.nextFloat() < 0.02) - player.level().playSound(null, player.x, player.y, player.z, HexSounds.FLIGHT_AMBIENCE, SoundSource.PLAYERS, 0.2f, 1f) - - if (flight.radius >= 0.0) { - // Show the origin - val spoofedOrigin = flight.origin.add(0.0, 1.0, 0.0) - ParticleSpray(spoofedOrigin, Vec3(0.0, 1.0, 0.0), 0.5, Math.PI * 0.1, count = 5) - .sprayParticles(player.serverLevel(), color) - ParticleSpray(spoofedOrigin, Vec3(0.0, -1.0, 0.0), 1.5, Math.PI * 0.25, count = 5) - .sprayParticles(player.serverLevel(), color) - } - } - } - } - - // Return a number from 0 (totally fine) to 1 (danger will robinson, stop the flight) - // it's a double for particle reason - private fun getDanger(player: ServerPlayer, flight: FlightAbility): Double { - val radiusDanger = if (flight.radius >= 0.0) { - if (player.level().dimension() != flight.dimension) { - 1.0 - } else { - // Limit it only in X/Z - val posXZ = Vec3(player.x, 0.0, player.z) - val originXZ = Vec3(flight.origin.x, 0.0, flight.origin.z) - val dist = posXZ.distanceTo(originXZ) - val distFromEdge = flight.radius - dist - if (distFromEdge >= DIST_DANGER_THRESHOLD) { - 0.0 - } else if (dist > flight.radius) { - 1.0 - } else { - 1.0 - (distFromEdge / DIST_DANGER_THRESHOLD) - } - } - } else 0.0 - val timeDanger = if (flight.timeLeft >= 0) { - if (flight.timeLeft >= TIME_DANGER_THRESHOLD) { - 0.0 - } else { - val timeDanger = TIME_DANGER_THRESHOLD - flight.timeLeft - timeDanger / TIME_DANGER_THRESHOLD - } - } else 0.0 - return max(radiusDanger, timeDanger) - } - } + override val argc = 2 + + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val target = args.getPlayer(0, argc) + val theArg = args.getPositiveDouble(1, argc) + env.assertEntityInRange(target) + + val cost = + when (this.type) { + Type.LimitRange -> theArg * MediaConstants.DUST_UNIT + // A second of flight should cost 1 shard + Type.LimitTime -> theArg * MediaConstants.SHARD_UNIT + }.roundToLong() + + // Convert to ticks + return SpellAction.Result( + Spell(this.type, target, theArg), + cost, + listOf(ParticleSpray(target.position(), Vec3(0.0, 2.0, 0.0), 0.0, 0.1)) + ) + } + + enum class Type { + LimitRange, + LimitTime + } + + data class Spell(val type: Type, val target: ServerPlayer, val theArg: Double) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + if (target.abilities.mayfly) { + // Don't accidentally clobber someone else's flight + // TODO make this a mishap? + return + } + + val dim = target.level().dimension() + val origin = target.position() + + val flight = + when (this.type) { + Type.LimitRange -> FlightAbility(-1, dim, origin, theArg) + Type.LimitTime -> FlightAbility((theArg * 20.0).roundToInt(), dim, origin, -1.0) + } + + IXplatAbstractions.INSTANCE.setFlight(target, flight) + + target.abilities.mayfly = true + target.onUpdateAbilities() + } + } + + companion object { + // blocks from the edge + private val DIST_DANGER_THRESHOLD = 4.0 + + // seconds left + private val TIME_DANGER_THRESHOLD = 7.0 * 20.0 + + @JvmStatic + fun tickAllPlayers(world: ServerLevel) { + for (player in world.players()) { + tickDownFlight(player) + } + } + + @JvmStatic + fun tickDownFlight(player: ServerPlayer) { + val flight = IXplatAbstractions.INSTANCE.getFlight(player) + + if (flight != null) { + val danger = getDanger(player, flight) + if (danger >= 1.0) { + IXplatAbstractions.INSTANCE.setFlight(player, null) + // stop shin smashing bonke + + if (!player.isCreative && !player.isSpectator) { + val abilities = player.abilities + abilities.flying = false + abilities.mayfly = false + player.onUpdateAbilities() + } + player + .level() + .playSound( + null, + player.x, + player.y, + player.z, + HexSounds.FLIGHT_FINISH, + SoundSource.PLAYERS, + 2f, + 1f + ) + val superDangerSpray = + ParticleSpray(player.position(), Vec3(0.0, 1.0, 0.0), Math.PI, 0.4, count = 20) + superDangerSpray.sprayParticles( + player.serverLevel(), + FrozenPigment(ItemStack(HexItems.DYE_PIGMENTS[DyeColor.RED]!!), Util.NIL_UUID) + ) + superDangerSpray.sprayParticles( + player.serverLevel(), + FrozenPigment(ItemStack(HexItems.DYE_PIGMENTS[DyeColor.BLACK]!!), Util.NIL_UUID) + ) + } else { + if (!player.abilities.mayfly) { + player.abilities.mayfly = true + player.onUpdateAbilities() + } + val time2 = + if (flight.timeLeft >= 0) { + flight.timeLeft - 1 + } else { + flight.timeLeft + } + IXplatAbstractions.INSTANCE.setFlight( + player, + FlightAbility(time2, flight.dimension, flight.origin, flight.radius) + ) + + val particleCount = 5 + val dangerParticleCount = (particleCount * danger).roundToInt() + val okParticleCount = particleCount - dangerParticleCount + val oneDangerParticleCount = Mth.ceil(dangerParticleCount / 2.0) + val color = IXplatAbstractions.INSTANCE.getPigment(player) + + // TODO: have the particles go in the opposite direction of the velocity? + ParticleSpray( + player.position(), + Vec3(0.0, -0.6, 0.0), + 0.6, + Math.PI * 0.3, + count = okParticleCount + ) + .sprayParticles(player.serverLevel(), color) + val dangerSpray = + ParticleSpray(player.position(), Vec3(0.0, 1.0, 0.0), 0.3, Math.PI * 0.75, count = 0) + dangerSpray + .copy(count = oneDangerParticleCount) + .sprayParticles( + player.serverLevel(), + FrozenPigment(ItemStack(HexItems.DYE_PIGMENTS[DyeColor.BLACK]!!), Util.NIL_UUID) + ) + dangerSpray + .copy(count = oneDangerParticleCount) + .sprayParticles( + player.serverLevel(), + FrozenPigment(ItemStack(HexItems.DYE_PIGMENTS[DyeColor.RED]!!), Util.NIL_UUID) + ) + + if (player.level().random.nextFloat() < 0.02) + player + .level() + .playSound( + null, + player.x, + player.y, + player.z, + HexSounds.FLIGHT_AMBIENCE, + SoundSource.PLAYERS, + 0.2f, + 1f + ) + + if (flight.radius >= 0.0) { + // Show the origin + val spoofedOrigin = flight.origin.add(0.0, 1.0, 0.0) + ParticleSpray(spoofedOrigin, Vec3(0.0, 1.0, 0.0), 0.5, Math.PI * 0.1, count = 5) + .sprayParticles(player.serverLevel(), color) + ParticleSpray(spoofedOrigin, Vec3(0.0, -1.0, 0.0), 1.5, Math.PI * 0.25, count = 5) + .sprayParticles(player.serverLevel(), color) + } + } + } + } + + // Return a number from 0 (totally fine) to 1 (danger will robinson, stop the flight) + // it's a double for particle reason + private fun getDanger(player: ServerPlayer, flight: FlightAbility): Double { + val radiusDanger = + if (flight.radius >= 0.0) { + if (player.level().dimension() != flight.dimension) { + 1.0 + } else { + // Limit it only in X/Z + val posXZ = Vec3(player.x, 0.0, player.z) + val originXZ = Vec3(flight.origin.x, 0.0, flight.origin.z) + val dist = posXZ.distanceTo(originXZ) + val distFromEdge = flight.radius - dist + if (distFromEdge >= DIST_DANGER_THRESHOLD) { + 0.0 + } else if (dist > flight.radius) { + 1.0 + } else { + 1.0 - (distFromEdge / DIST_DANGER_THRESHOLD) + } + } + } else 0.0 + val timeDanger = + if (flight.timeLeft >= 0) { + if (flight.timeLeft >= TIME_DANGER_THRESHOLD) { + 0.0 + } else { + val timeDanger = TIME_DANGER_THRESHOLD - flight.timeLeft + timeDanger / TIME_DANGER_THRESHOLD + } + } else 0.0 + return max(radiusDanger, timeDanger) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpIgnite.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpIgnite.kt index eeb7fae5cf..3fe9de443e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpIgnite.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpIgnite.kt @@ -25,59 +25,64 @@ import net.minecraft.world.phys.BlockHitResult import net.minecraft.world.phys.Vec3 object OpIgnite : SpellAction { - override val argc = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - when (val target = args[0]) { - is EntityIota -> { - val entity = args.getEntity(0, argc) - env.assertEntityInRange(entity) - return SpellAction.Result( - EntitySpell(entity), - MediaConstants.DUST_UNIT, - listOf(ParticleSpray.burst(entity.position(), 1.0)) - ) - } - is Vec3Iota -> { - val block = args.getBlockPos(0, argc) - env.assertPosInRangeForEditing(block) - return SpellAction.Result( - BlockSpell(block), - MediaConstants.DUST_UNIT, - listOf(ParticleSpray.burst(Vec3.atCenterOf(BlockPos(block)), 1.0)) - ) - } - else -> throw MishapInvalidIota.ofType(target, 0, "entity_or_vector") - } - } + override val argc = 1 - private data class BlockSpell(val pos: BlockPos) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - // help - if (!tryToClick(env, pos, Items.FIRE_CHARGE)) { - tryToClick(env, pos, Items.FLINT_AND_STEEL) - } - } + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + when (val target = args[0]) { + is EntityIota -> { + val entity = args.getEntity(0, argc) + env.assertEntityInRange(entity) + return SpellAction.Result( + EntitySpell(entity), + MediaConstants.DUST_UNIT, + listOf(ParticleSpray.burst(entity.position(), 1.0)) + ) + } + is Vec3Iota -> { + val block = args.getBlockPos(0, argc) + env.assertPosInRangeForEditing(block) + return SpellAction.Result( + BlockSpell(block), + MediaConstants.DUST_UNIT, + listOf(ParticleSpray.burst(Vec3.atCenterOf(BlockPos(block)), 1.0)) + ) + } + else -> throw MishapInvalidIota.ofType(target, 0, "entity_or_vector") + } + } - fun tryToClick(ctx: CastingEnvironment, pos: BlockPos, item: Item): Boolean { - return IXplatAbstractions.INSTANCE.isPlacingAllowed(ctx.world, pos, ItemStack(item), ctx.castingEntity as? ServerPlayer) && - item.useOn( - UseOnContext( - ctx.world, - null, - InteractionHand.MAIN_HAND, - ItemStack(item), - BlockHitResult(Vec3.atCenterOf(pos), Direction.UP, pos, false) - ) - ).consumesAction() - } - } + private data class BlockSpell(val pos: BlockPos) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + // help + if (!tryToClick(env, pos, Items.FIRE_CHARGE)) { + tryToClick(env, pos, Items.FLINT_AND_STEEL) + } + } - private data class EntitySpell(val entity: Entity) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - entity.setSecondsOnFire(8) - } - } -} \ No newline at end of file + fun tryToClick(ctx: CastingEnvironment, pos: BlockPos, item: Item): Boolean { + return IXplatAbstractions.INSTANCE.isPlacingAllowed( + ctx.world, + pos, + ItemStack(item), + ctx.castingEntity as? ServerPlayer + ) && + item + .useOn( + UseOnContext( + ctx.world, + null, + InteractionHand.MAIN_HAND, + ItemStack(item), + BlockHitResult(Vec3.atCenterOf(pos), Direction.UP, pos, false) + ) + ) + .consumesAction() + } + } + + private data class EntitySpell(val entity: Entity) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + entity.setSecondsOnFire(8) + } + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakeBattery.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakeBattery.kt index 5e86b23504..7ade04643c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakeBattery.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakeBattery.kt @@ -20,66 +20,61 @@ import net.minecraft.world.item.ItemStack // TODO: how to handle in cirles object OpMakeBattery : SpellAction { - override val argc = 1 + override val argc = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val entity = args.getItemEntity(0, argc) + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val entity = args.getItemEntity(0, argc) - val (handStack, hand) = env.getHeldItemToOperateOn { it.`is`(HexTags.Items.PHIAL_BASE) } - ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), "bottle") // TODO: hack + val (handStack, hand) = + env.getHeldItemToOperateOn { it.`is`(HexTags.Items.PHIAL_BASE) } + ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), "bottle") // TODO: hack - if (!handStack.`is`(HexTags.Items.PHIAL_BASE)) { - throw MishapBadOffhandItem.of( - handStack, - "bottle" - ) - } - if (handStack.count != 1) { - throw MishapBadOffhandItem.of( - handStack, - "only_one" - ) - } + if (!handStack.`is`(HexTags.Items.PHIAL_BASE)) { + throw MishapBadOffhandItem.of(handStack, "bottle") + } + if (handStack.count != 1) { + throw MishapBadOffhandItem.of(handStack, "only_one") + } - env.assertEntityInRange(entity) + env.assertEntityInRange(entity) - if (!isMediaItem(entity.item) || extractMedia( - entity.item, - drainForBatteries = true, - simulate = true - ) <= 0 - ) { - throw MishapBadItem.of( - entity, - "media_for_battery" - ) - } + if ( + !isMediaItem(entity.item) || + extractMedia(entity.item, drainForBatteries = true, simulate = true) <= 0 + ) { + throw MishapBadItem.of(entity, "media_for_battery") + } - return SpellAction.Result( - Spell(entity, handStack, hand), - MediaConstants.CRYSTAL_UNIT, - listOf(ParticleSpray.burst(entity.position(), 0.5)) - ) - } + return SpellAction.Result( + Spell(entity, handStack, hand), + MediaConstants.CRYSTAL_UNIT, + listOf(ParticleSpray.burst(entity.position(), 0.5)) + ) + } - private data class Spell(val itemEntity: ItemEntity, val handStack: ItemStack, val hand: InteractionHand?) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - if (!itemEntity.isAlive) - return + private data class Spell( + val itemEntity: ItemEntity, + val handStack: ItemStack, + val hand: InteractionHand? + ) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + if (!itemEntity.isAlive) return - val entityStack = itemEntity.item.copy() - val mediamount = extractMedia(entityStack, drainForBatteries = true) - if (mediamount > 0) { - if (!env.replaceItem({ it == handStack }, ItemMediaHolder.withMedia(ItemStack(HexItems.BATTERY), mediamount, mediamount), hand)) - return - } + val entityStack = itemEntity.item.copy() + val mediamount = extractMedia(entityStack, drainForBatteries = true) + if (mediamount > 0) { + if ( + !env.replaceItem( + { it == handStack }, + ItemMediaHolder.withMedia(ItemStack(HexItems.BATTERY), mediamount, mediamount), + hand + ) + ) + return + } - itemEntity.item = entityStack - if (entityStack.isEmpty) - itemEntity.kill() - } - } + itemEntity.item = entityStack + if (entityStack.isEmpty) itemEntity.kill() + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakePackagedSpell.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakePackagedSpell.kt index 2601a70696..e0c90a9084 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakePackagedSpell.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakePackagedSpell.kt @@ -20,68 +20,61 @@ import net.minecraft.world.item.ItemStack // TODO: How to handle in circles class OpMakePackagedSpell<T : ItemPackagedHex>(val itemType: T, val cost: Long) : SpellAction { - override val argc = 2 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val entity = args.getItemEntity(0, argc) - val patterns = args.getList(1, argc).toList() + override val argc = 2 - val (handStack) = env.getHeldItemToOperateOn { - val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(it) - it.`is`(itemType) && hexHolder != null && !hexHolder.hasHex() - } - ?: throw MishapBadOffhandItem(ItemStack.EMPTY.copy(), itemType.description) // TODO: hack + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val entity = args.getItemEntity(0, argc) + val patterns = args.getList(1, argc).toList() - val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(handStack) - if (!handStack.`is`(itemType)) { - throw MishapBadOffhandItem(handStack, itemType.description) - } else if (hexHolder == null || hexHolder.hasHex()) { - throw MishapBadOffhandItem.of(handStack, "iota.write") - } + val (handStack) = + env.getHeldItemToOperateOn { + val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(it) + it.`is`(itemType) && hexHolder != null && !hexHolder.hasHex() + } ?: throw MishapBadOffhandItem(ItemStack.EMPTY.copy(), itemType.description) // TODO: hack - env.assertEntityInRange(entity) - if (!isMediaItem(entity.item) || extractMedia( - entity.item, - drainForBatteries = true, - simulate = true - ) <= 0 - ) { - throw MishapBadItem.of( - entity, - "media_for_battery" - ) - } + val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(handStack) + if (!handStack.`is`(itemType)) { + throw MishapBadOffhandItem(handStack, itemType.description) + } else if (hexHolder == null || hexHolder.hasHex()) { + throw MishapBadOffhandItem.of(handStack, "iota.write") + } - val trueName = MishapOthersName.getTrueNameFromArgs(patterns, env.castingEntity as? ServerPlayer) - if (trueName != null) - throw MishapOthersName(trueName) + env.assertEntityInRange(entity) + if ( + !isMediaItem(entity.item) || + extractMedia(entity.item, drainForBatteries = true, simulate = true) <= 0 + ) { + throw MishapBadItem.of(entity, "media_for_battery") + } - return SpellAction.Result( - Spell(entity, patterns, handStack), - cost, - listOf(ParticleSpray.burst(entity.position(), 0.5)) - ) - } + val trueName = + MishapOthersName.getTrueNameFromArgs(patterns, env.castingEntity as? ServerPlayer) + if (trueName != null) throw MishapOthersName(trueName) - private inner class Spell(val itemEntity: ItemEntity, val patterns: List<Iota>, val stack: ItemStack) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(stack) - if (hexHolder != null - && !hexHolder.hasHex() - && itemEntity.isAlive - ) { - val entityStack = itemEntity.item.copy() - val mediamount = extractMedia(entityStack, drainForBatteries = true) - if (mediamount > 0) { - hexHolder.writeHex(patterns, env.pigment, mediamount) - } + return SpellAction.Result( + Spell(entity, patterns, handStack), + cost, + listOf(ParticleSpray.burst(entity.position(), 0.5)) + ) + } - itemEntity.item = entityStack - if (entityStack.isEmpty) - itemEntity.kill() - } - } - } + private inner class Spell( + val itemEntity: ItemEntity, + val patterns: List<Iota>, + val stack: ItemStack + ) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(stack) + if (hexHolder != null && !hexHolder.hasHex() && itemEntity.isAlive) { + val entityStack = itemEntity.item.copy() + val mediamount = extractMedia(entityStack, drainForBatteries = true) + if (mediamount > 0) { + hexHolder.writeHex(patterns, env.pigment, mediamount) + } + + itemEntity.item = entityStack + if (entityStack.isEmpty) itemEntity.kill() + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPlaceBlock.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPlaceBlock.kt index e71a3df9bd..2caa739989 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPlaceBlock.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPlaceBlock.kt @@ -25,82 +25,109 @@ import net.minecraft.world.phys.BlockHitResult import net.minecraft.world.phys.Vec3 object OpPlaceBlock : SpellAction { - override val argc: Int - get() = 1 + override val argc: Int + get() = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val pos = args.getBlockPos(0, argc) - env.assertPosInRangeForEditing(pos) + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val pos = args.getBlockPos(0, argc) + env.assertPosInRangeForEditing(pos) - val blockHit = BlockHitResult( - Vec3.atCenterOf(pos), env.castingEntity?.direction ?: Direction.NORTH, pos, false - ) - val itemUseCtx = env - .queryForMatchingStack { it.item is BlockItem } - ?.let { UseOnContext(env.world, env.castingEntity as? ServerPlayer, env.castingHand, it, blockHit) } - ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY, "placeable") - val placeContext = BlockPlaceContext(itemUseCtx) + val blockHit = + BlockHitResult( + Vec3.atCenterOf(pos), + env.castingEntity?.direction ?: Direction.NORTH, + pos, + false + ) + val itemUseCtx = + env + .queryForMatchingStack { it.item is BlockItem } + ?.let { + UseOnContext(env.world, env.castingEntity as? ServerPlayer, env.castingHand, it, blockHit) + } ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY, "placeable") + val placeContext = BlockPlaceContext(itemUseCtx) - val worldState = env.world.getBlockState(pos) - if (!worldState.canBeReplaced(placeContext)) - throw MishapBadBlock.of(pos, "replaceable") + val worldState = env.world.getBlockState(pos) + if (!worldState.canBeReplaced(placeContext)) throw MishapBadBlock.of(pos, "replaceable") - return SpellAction.Result( - Spell(pos), - MediaConstants.DUST_UNIT / 8, - listOf(ParticleSpray.cloud(Vec3.atCenterOf(pos), 1.0)) - ) - } + return SpellAction.Result( + Spell(pos), + MediaConstants.DUST_UNIT / 8, + listOf(ParticleSpray.cloud(Vec3.atCenterOf(pos), 1.0)) + ) + } - private data class Spell(val pos: BlockPos) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - val caster = env.castingEntity + private data class Spell(val pos: BlockPos) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + val caster = env.castingEntity - val blockHit = BlockHitResult( - Vec3.atCenterOf(pos), caster?.direction ?: Direction.NORTH, pos, false - ) + val blockHit = + BlockHitResult(Vec3.atCenterOf(pos), caster?.direction ?: Direction.NORTH, pos, false) - val bstate = env.world.getBlockState(pos) - val placeeStack = env.queryForMatchingStack { it.item is BlockItem } - if (placeeStack != null) { - if (!IXplatAbstractions.INSTANCE.isPlacingAllowed(env.world, pos, placeeStack, caster as? ServerPlayer)) - return + val bstate = env.world.getBlockState(pos) + val placeeStack = env.queryForMatchingStack { it.item is BlockItem } + if (placeeStack != null) { + if ( + !IXplatAbstractions.INSTANCE.isPlacingAllowed( + env.world, + pos, + placeeStack, + caster as? ServerPlayer + ) + ) + return - if (!placeeStack.isEmpty) { - // https://github.com/VazkiiMods/Psi/blob/master/src/main/java/vazkii/psi/common/spell/trick/block/PieceTrickPlaceBlock.java#L143 - val spoofedStack = placeeStack.copy() + if (!placeeStack.isEmpty) { + // https://github.com/VazkiiMods/Psi/blob/master/src/main/java/vazkii/psi/common/spell/trick/block/PieceTrickPlaceBlock.java#L143 + val spoofedStack = placeeStack.copy() - // we temporarily give the player the stack, place it using mc code, then give them the old stack back. - spoofedStack.count = 1 + // we temporarily give the player the stack, place it using mc code, then give them the + // old stack back. + spoofedStack.count = 1 - val itemUseCtx = UseOnContext(env.world, caster as? ServerPlayer, env.castingHand, spoofedStack, blockHit) - val placeContext = BlockPlaceContext(itemUseCtx) - if (bstate.canBeReplaced(placeContext)) { - if (env.withdrawItem({ it == placeeStack }, 1, false)) { - val res = spoofedStack.useOn(placeContext) + val itemUseCtx = + UseOnContext( + env.world, + caster as? ServerPlayer, + env.castingHand, + spoofedStack, + blockHit + ) + val placeContext = BlockPlaceContext(itemUseCtx) + if (bstate.canBeReplaced(placeContext)) { + if (env.withdrawItem({ it == placeeStack }, 1, false)) { + val res = spoofedStack.useOn(placeContext) - if (res != InteractionResult.FAIL) { - env.withdrawItem({ it == placeeStack }, 1, true) + if (res != InteractionResult.FAIL) { + env.withdrawItem({ it == placeeStack }, 1, true) - env.world.playSound( - caster as? ServerPlayer, - pos.x.toDouble(), pos.y.toDouble(), pos.z.toDouble(), - bstate.soundType.placeSound, SoundSource.BLOCKS, 1.0f, - 1.0f + (Math.random() * 0.5 - 0.25).toFloat() - ) - val particle = BlockParticleOption(ParticleTypes.BLOCK, bstate) - env.world.sendParticles( - particle, pos.x.toDouble(), pos.y.toDouble(), pos.z.toDouble(), - 4, 0.1, 0.2, 0.1, 0.1 - ) - } - } - } - } - } - } - } + env.world.playSound( + caster as? ServerPlayer, + pos.x.toDouble(), + pos.y.toDouble(), + pos.z.toDouble(), + bstate.soundType.placeSound, + SoundSource.BLOCKS, + 1.0f, + 1.0f + (Math.random() * 0.5 - 0.25).toFloat() + ) + val particle = BlockParticleOption(ParticleTypes.BLOCK, bstate) + env.world.sendParticles( + particle, + pos.x.toDouble(), + pos.y.toDouble(), + pos.z.toDouble(), + 4, + 0.1, + 0.2, + 0.1, + 0.1 + ) + } + } + } + } + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPotionEffect.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPotionEffect.kt index 6f7dc5a05e..4dda13bd14 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPotionEffect.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPotionEffect.kt @@ -9,45 +9,46 @@ import net.minecraft.world.effect.MobEffectInstance import net.minecraft.world.entity.LivingEntity class OpPotionEffect( - val effect: MobEffect, - val baseCost: Long, - val allowPotency: Boolean, - val potencyCubic: Boolean, + val effect: MobEffect, + val baseCost: Long, + val allowPotency: Boolean, + val potencyCubic: Boolean, ) : SpellAction { - override val argc: Int - get() = if (this.allowPotency) 3 else 2 + override val argc: Int + get() = if (this.allowPotency) 3 else 2 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val target = args.getLivingEntityButNotArmorStand(0, argc) - val duration = args.getPositiveDouble(1, argc) - val potency = if (this.allowPotency) - args.getDoubleBetween(2, 1.0, 127.0, argc) - else 1.0 - env.assertEntityInRange(target) + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val target = args.getLivingEntityButNotArmorStand(0, argc) + val duration = args.getPositiveDouble(1, argc) + val potency = if (this.allowPotency) args.getDoubleBetween(2, 1.0, 127.0, argc) else 1.0 + env.assertEntityInRange(target) + val cost = + this.baseCost * + duration * + if (potencyCubic) { + potency * potency * potency + } else { + potency * potency + } + return SpellAction.Result( + Spell(effect, target, duration, potency), + cost.toLong(), + listOf(ParticleSpray.cloud(target.position().add(0.0, target.eyeHeight / 2.0, 0.0), 1.0)) + ) + } - val cost = this.baseCost * duration * if (potencyCubic) { - potency * potency * potency - } else { - potency * potency - } - return SpellAction.Result( - Spell(effect, target, duration, potency), - cost.toLong(), - listOf(ParticleSpray.cloud(target.position().add(0.0, target.eyeHeight / 2.0, 0.0), 1.0)) - ) - } - - private class Spell(val effect: MobEffect, val target: LivingEntity, val duration: Double, val potency: Double) : - RenderedSpell { - override fun cast(env: CastingEnvironment) { - if (duration > 1.0 / 20.0) { - val effectInst = MobEffectInstance(effect, (duration * 20).toInt(), potency.toInt() - 1) - target.addEffect(effectInst) - } - } - } + private class Spell( + val effect: MobEffect, + val target: LivingEntity, + val duration: Double, + val potency: Double + ) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + if (duration > 1.0 / 20.0) { + val effectInst = MobEffectInstance(effect, (duration * 20).toInt(), potency.toInt() - 1) + target.addEffect(effectInst) + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPrint.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPrint.kt index 4fc5e565ca..ad289268f4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPrint.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPrint.kt @@ -13,28 +13,32 @@ import at.petrak.hexcasting.common.lib.hex.HexEvalSounds // TODO should this dump the whole stack object OpPrint : Action { - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + val stack = image.stack.toMutableList() - if (stack.isEmpty()) { - throw MishapNotEnoughArgs(1, 0) - } - val datum = stack[stack.lastIndex] + if (stack.isEmpty()) { + throw MishapNotEnoughArgs(1, 0) + } + val datum = stack[stack.lastIndex] - val image2 = image.withUsedOp().copy(stack = stack) - return OperationResult( - image2, - listOf( - OperatorSideEffect.AttemptSpell(Spell(datum), hasCastingSound = false, awardStat = false) - ), - continuation, - HexEvalSounds.SPELL, - ) - } + val image2 = image.withUsedOp().copy(stack = stack) + return OperationResult( + image2, + listOf( + OperatorSideEffect.AttemptSpell(Spell(datum), hasCastingSound = false, awardStat = false) + ), + continuation, + HexEvalSounds.SPELL, + ) + } - private data class Spell(val datum: Iota) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - env.printMessage(datum.display()) - } - } + private data class Spell(val datum: Iota) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + env.printMessage(datum.display()) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpRecharge.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpRecharge.kt index 0b7fcb6dfd..9a105df5b3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpRecharge.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpRecharge.kt @@ -16,66 +16,57 @@ import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.item.ItemStack object OpRecharge : SpellAction { - override val argc = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val entity = args.getItemEntity(0, argc) - - val (handStack) = env.getHeldItemToOperateOn { - val media = IXplatAbstractions.INSTANCE.findMediaHolder(it) - media != null && media.canRecharge() && media.insertMedia(-1, true) != 0L - } - ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), "rechargable") // TODO: hack - - val media = IXplatAbstractions.INSTANCE.findMediaHolder(handStack) - - if (media == null || !media.canRecharge()) - throw MishapBadOffhandItem.of( - handStack, - "rechargable" - ) - - env.assertEntityInRange(entity) - - if (!isMediaItem(entity.item)) { - throw MishapBadItem.of( - entity, - "media" - ) - } - - // TODO: why did this code exist - /* - if (media.insertMedia(-1, true) == 0L) - return null - */ - - return SpellAction.Result( - Spell(entity, handStack), - MediaConstants.SHARD_UNIT, - listOf(ParticleSpray.burst(entity.position(), 0.5)) - ) - } - - private data class Spell(val itemEntity: ItemEntity, val stack: ItemStack) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - val media = IXplatAbstractions.INSTANCE.findMediaHolder(stack) - - if (media != null && itemEntity.isAlive) { - val entityStack = itemEntity.item.copy() - - val emptySpace = media.insertMedia(-1, true) - - val mediaAmt = extractMedia(entityStack, emptySpace) - - media.insertMedia(mediaAmt, false) - - itemEntity.item = entityStack - if (entityStack.isEmpty) - itemEntity.kill() - } - } - } + override val argc = 1 + + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val entity = args.getItemEntity(0, argc) + + val (handStack) = + env.getHeldItemToOperateOn { + val media = IXplatAbstractions.INSTANCE.findMediaHolder(it) + media != null && media.canRecharge() && media.insertMedia(-1, true) != 0L + } ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), "rechargable") // TODO: hack + + val media = IXplatAbstractions.INSTANCE.findMediaHolder(handStack) + + if (media == null || !media.canRecharge()) + throw MishapBadOffhandItem.of(handStack, "rechargable") + + env.assertEntityInRange(entity) + + if (!isMediaItem(entity.item)) { + throw MishapBadItem.of(entity, "media") + } + + // TODO: why did this code exist + /* + if (media.insertMedia(-1, true) == 0L) + return null + */ + + return SpellAction.Result( + Spell(entity, handStack), + MediaConstants.SHARD_UNIT, + listOf(ParticleSpray.burst(entity.position(), 0.5)) + ) + } + + private data class Spell(val itemEntity: ItemEntity, val stack: ItemStack) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + val media = IXplatAbstractions.INSTANCE.findMediaHolder(stack) + + if (media != null && itemEntity.isAlive) { + val entityStack = itemEntity.item.copy() + + val emptySpace = media.insertMedia(-1, true) + + val mediaAmt = extractMedia(entityStack, emptySpace) + + media.insertMedia(mediaAmt, false) + + itemEntity.item = entityStack + if (entityStack.isEmpty) itemEntity.kill() + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpTheOnlyReasonAnyoneDownloadedPsi.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpTheOnlyReasonAnyoneDownloadedPsi.kt index 0b663b871c..5f9647363e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpTheOnlyReasonAnyoneDownloadedPsi.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpTheOnlyReasonAnyoneDownloadedPsi.kt @@ -17,29 +17,33 @@ import net.minecraft.world.item.context.UseOnContext import net.minecraft.world.phys.BlockHitResult import net.minecraft.world.phys.Vec3 - object OpTheOnlyReasonAnyoneDownloadedPsi : SpellAction { - override val argc = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val target = args.getBlockPos(0, argc) - env.assertPosInRangeForEditing(target) + override val argc = 1 + + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val target = args.getBlockPos(0, argc) + env.assertPosInRangeForEditing(target) - return SpellAction.Result( - Spell(target), - (MediaConstants.DUST_UNIT * 1.125).toLong(), - listOf(ParticleSpray.burst(Vec3.atCenterOf(BlockPos(target)), 1.0)) - ) - } + return SpellAction.Result( + Spell(target), + (MediaConstants.DUST_UNIT * 1.125).toLong(), + listOf(ParticleSpray.burst(Vec3.atCenterOf(BlockPos(target)), 1.0)) + ) + } - private data class Spell(val pos: BlockPos) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - // https://github.com/VazkiiMods/Psi/blob/master/src/main/java/vazkii/psi/common/spell/trick/PieceTrickOvergrow.java - val hit = BlockHitResult(Vec3.ZERO, Direction.UP, pos, false) - val fakeContext = UseOnContext(env.world, env.castingEntity as? ServerPlayer, InteractionHand.MAIN_HAND, ItemStack(Items.BONE_MEAL), hit) - Items.BONE_MEAL.useOn(fakeContext) - } - } + private data class Spell(val pos: BlockPos) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + // https://github.com/VazkiiMods/Psi/blob/master/src/main/java/vazkii/psi/common/spell/trick/PieceTrickOvergrow.java + val hit = BlockHitResult(Vec3.ZERO, Direction.UP, pos, false) + val fakeContext = + UseOnContext( + env.world, + env.castingEntity as? ServerPlayer, + InteractionHand.MAIN_HAND, + ItemStack(Items.BONE_MEAL), + hit + ) + Items.BONE_MEAL.useOn(fakeContext) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpAltiora.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpAltiora.kt index 515518cadc..87149b58ea 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpAltiora.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpAltiora.kt @@ -10,66 +10,89 @@ import at.petrak.hexcasting.api.misc.MediaConstants import at.petrak.hexcasting.api.player.AltioraAbility import at.petrak.hexcasting.common.lib.HexSounds import at.petrak.hexcasting.xplat.IXplatAbstractions +import kotlin.math.max import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerPlayer import net.minecraft.sounds.SoundSource import net.minecraft.world.phys.Vec3 -import kotlin.math.max object OpAltiora : SpellAction { - override val argc = 1 + override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { - val target = args.getPlayer(0, argc) - env.assertEntityInRange(target) + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val target = args.getPlayer(0, argc) + env.assertEntityInRange(target) - return SpellAction.Result( - Spell(target), - MediaConstants.CRYSTAL_UNIT, - listOf( - ParticleSpray.burst(target.position(), 0.5), - ParticleSpray(target.position(), Vec3(0.0, 2.0, 0.0), 0.0, 0.1) - ) - ) - } + return SpellAction.Result( + Spell(target), + MediaConstants.CRYSTAL_UNIT, + listOf( + ParticleSpray.burst(target.position(), 0.5), + ParticleSpray(target.position(), Vec3(0.0, 2.0, 0.0), 0.0, 0.1) + ) + ) + } - private data class Spell(val target: ServerPlayer) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - target.push(0.0, 1.5, 0.0) - // They won't move otherwise? - target.hurtMarked = true + private data class Spell(val target: ServerPlayer) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + target.push(0.0, 1.5, 0.0) + // They won't move otherwise? + target.hurtMarked = true - IXplatAbstractions.INSTANCE.setAltiora(target, AltioraAbility(GRACE_PERIOD)) - } - } + IXplatAbstractions.INSTANCE.setAltiora(target, AltioraAbility(GRACE_PERIOD)) + } + } - // TODO: this sends a packet to the player every tick. I need to find out what the monotonically increasing time value is - @JvmStatic - fun checkPlayerCollision(player: ServerPlayer) { - val altiora = IXplatAbstractions.INSTANCE.getAltiora(player); - if (altiora != null) { - if (altiora.gracePeriod == 0 && (player.onGround() || player.horizontalCollision)) { - IXplatAbstractions.INSTANCE.setAltiora(player, null) - player.level().playSound(null, player.x, player.y, player.z, HexSounds.FLIGHT_FINISH, SoundSource.PLAYERS, 2f, 1f) - } else { - val grace2 = max(altiora.gracePeriod - 1, 0) - IXplatAbstractions.INSTANCE.setAltiora(player, AltioraAbility(grace2)) + // TODO: this sends a packet to the player every tick. I need to find out what the monotonically + // increasing time value is + @JvmStatic + fun checkPlayerCollision(player: ServerPlayer) { + val altiora = IXplatAbstractions.INSTANCE.getAltiora(player) + if (altiora != null) { + if (altiora.gracePeriod == 0 && (player.onGround() || player.horizontalCollision)) { + IXplatAbstractions.INSTANCE.setAltiora(player, null) + player + .level() + .playSound( + null, + player.x, + player.y, + player.z, + HexSounds.FLIGHT_FINISH, + SoundSource.PLAYERS, + 2f, + 1f + ) + } else { + val grace2 = max(altiora.gracePeriod - 1, 0) + IXplatAbstractions.INSTANCE.setAltiora(player, AltioraAbility(grace2)) - if (player.level().random.nextFloat() < 0.02) - player.level().playSound(null, player.x, player.y, player.z, HexSounds.FLIGHT_AMBIENCE, SoundSource.PLAYERS, 0.2f, 1f) + if (player.level().random.nextFloat() < 0.02) + player + .level() + .playSound( + null, + player.x, + player.y, + player.z, + HexSounds.FLIGHT_AMBIENCE, + SoundSource.PLAYERS, + 0.2f, + 1f + ) - val color = IXplatAbstractions.INSTANCE.getPigment(player) - ParticleSpray(player.position(), Vec3(0.0, -0.2, 0.0), 0.4, Math.PI * 0.5, count = 3) - .sprayParticles(player.serverLevel(), color) - } - } - } + val color = IXplatAbstractions.INSTANCE.getPigment(player) + ParticleSpray(player.position(), Vec3(0.0, -0.2, 0.0), 0.4, Math.PI * 0.5, count = 3) + .sprayParticles(player.serverLevel(), color) + } + } + } - fun checkAllPlayers(world: ServerLevel) { - for (player in world.players()) { - checkPlayerCollision(player) - } - } + fun checkAllPlayers(world: ServerLevel) { + for (player in world.players()) { + checkPlayerCollision(player) + } + } - private val GRACE_PERIOD = 20 -} \ No newline at end of file + private val GRACE_PERIOD = 20 +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpBrainsweep.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpBrainsweep.kt index b6325f685a..fc934e9596 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpBrainsweep.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpBrainsweep.kt @@ -26,63 +26,69 @@ import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.phys.Vec3 object OpBrainsweep : SpellAction { - override val argc = 2 + override val argc = 2 - // this way you can hear the villager dying more : ) - override fun hasCastingSound(ctx: CastingEnvironment) = false + // this way you can hear the villager dying more : ) + override fun hasCastingSound(ctx: CastingEnvironment) = false - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val sacrifice = args.getMob(0, argc) - val vecPos = args.getVec3(1, argc) - val pos = BlockPos.containing(vecPos) + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val sacrifice = args.getMob(0, argc) + val vecPos = args.getVec3(1, argc) + val pos = BlockPos.containing(vecPos) - env.assertVecInRange(vecPos) - env.assertEntityInRange(sacrifice) + env.assertVecInRange(vecPos) + env.assertEntityInRange(sacrifice) - if (!env.canEditBlockAt(pos)) - throw MishapBadLocation(vecPos, "forbidden") + if (!env.canEditBlockAt(pos)) throw MishapBadLocation(vecPos, "forbidden") - if (sacrifice.type.`is`(HexTags.Entities.NO_BRAINSWEEPING)) - throw MishapBadBrainsweep(sacrifice, pos) + if (sacrifice.type.`is`(HexTags.Entities.NO_BRAINSWEEPING)) + throw MishapBadBrainsweep(sacrifice, pos) - if (IXplatAbstractions.INSTANCE.isBrainswept(sacrifice)) - throw MishapAlreadyBrainswept(sacrifice) + if (IXplatAbstractions.INSTANCE.isBrainswept(sacrifice)) + throw MishapAlreadyBrainswept(sacrifice) - val state = env.world.getBlockState(pos) + val state = env.world.getBlockState(pos) - val recman = env.world.recipeManager - val recipes = recman.getAllRecipesFor(HexRecipeStuffRegistry.BRAINSWEEP_TYPE) - val recipe = recipes.find { it.matches(state, sacrifice, env.world) } - ?: throw MishapBadBrainsweep(sacrifice, pos) + val recman = env.world.recipeManager + val recipes = recman.getAllRecipesFor(HexRecipeStuffRegistry.BRAINSWEEP_TYPE) + val recipe = + recipes.find { it.matches(state, sacrifice, env.world) } + ?: throw MishapBadBrainsweep(sacrifice, pos) - return SpellAction.Result( - Spell(pos, state, sacrifice, recipe), - recipe.mediaCost, - listOf(ParticleSpray.cloud(sacrifice.position(), 1.0), ParticleSpray.burst(Vec3.atCenterOf(pos), 0.3, 100)) - ) - } + return SpellAction.Result( + Spell(pos, state, sacrifice, recipe), + recipe.mediaCost, + listOf( + ParticleSpray.cloud(sacrifice.position(), 1.0), + ParticleSpray.burst(Vec3.atCenterOf(pos), 0.3, 100) + ) + ) + } - private data class Spell( - val pos: BlockPos, - val state: BlockState, - val sacrifice: Mob, - val recipe: BrainsweepRecipe - ) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - env.world.setBlockAndUpdate(pos, BrainsweepRecipe.copyProperties(state, recipe.result)) + private data class Spell( + val pos: BlockPos, + val state: BlockState, + val sacrifice: Mob, + val recipe: BrainsweepRecipe + ) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + env.world.setBlockAndUpdate(pos, BrainsweepRecipe.copyProperties(state, recipe.result)) - IXplatAbstractions.INSTANCE.setBrainsweepAddlData(sacrifice) - if (sacrifice is Villager && HexConfig.server().doVillagersTakeOffenseAtMindMurder()) { - env.castingEntity?.let { sacrifice.tellWitnessesThatIWasMurdered(it) } - } + IXplatAbstractions.INSTANCE.setBrainsweepAddlData(sacrifice) + if (sacrifice is Villager && HexConfig.server().doVillagersTakeOffenseAtMindMurder()) { + env.castingEntity?.let { sacrifice.tellWitnessesThatIWasMurdered(it) } + } - val sound = (sacrifice as AccessorLivingEntity).`hex$getDeathSound`() - if (sound != null) - env.world.playSound(null, sacrifice, sound, SoundSource.AMBIENT, 0.8f, 1f) - env.world.playSound(null, sacrifice, SoundEvents.PLAYER_LEVELUP, SoundSource.AMBIENT, 0.5f, 0.8f) - } - } + val sound = (sacrifice as AccessorLivingEntity).`hex$getDeathSound`() + if (sound != null) env.world.playSound(null, sacrifice, sound, SoundSource.AMBIENT, 0.8f, 1f) + env.world.playSound( + null, + sacrifice, + SoundEvents.PLAYER_LEVELUP, + SoundSource.AMBIENT, + 0.5f, + 0.8f + ) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpLightning.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpLightning.kt index 318b247ed4..270fec6e99 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpLightning.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpLightning.kt @@ -14,31 +14,30 @@ import net.minecraft.world.entity.LightningBolt import net.minecraft.world.phys.Vec3 object OpLightning : SpellAction { - override val argc = 1 + override val argc = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val target = args.getVec3(0, argc) - env.assertVecInRange(target) + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val target = args.getVec3(0, argc) + env.assertVecInRange(target) - if (!env.canEditBlockAt(BlockPos.containing(target))) - throw MishapBadLocation(target, "forbidden") + if (!env.canEditBlockAt(BlockPos.containing(target))) + throw MishapBadLocation(target, "forbidden") - return SpellAction.Result( - Spell(target), - 3 * MediaConstants.SHARD_UNIT, - listOf(ParticleSpray(target.add(0.0, 2.0, 0.0), Vec3(0.0, -1.0, 0.0), 0.5, 0.1)) - ) - } + return SpellAction.Result( + Spell(target), + 3 * MediaConstants.SHARD_UNIT, + listOf(ParticleSpray(target.add(0.0, 2.0, 0.0), Vec3(0.0, -1.0, 0.0), 0.5, 0.1)) + ) + } - private data class Spell(val target: Vec3) : RenderedSpell { - override fun cast(env: CastingEnvironment) { + private data class Spell(val target: Vec3) : RenderedSpell { + override fun cast(env: CastingEnvironment) { - val lightning = LightningBolt(EntityType.LIGHTNING_BOLT, env.world) - lightning.setPosRaw(target.x, target.y, target.z) - env.world.addWithUUID(lightning) // why the hell is it called this it doesnt even involve a uuid - } - } + val lightning = LightningBolt(EntityType.LIGHTNING_BOLT, env.world) + lightning.setPosRaw(target.x, target.y, target.z) + env.world.addWithUUID( + lightning + ) // why the hell is it called this it doesnt even involve a uuid + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpTeleport.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpTeleport.kt index abd39e52e1..87257ec426 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpTeleport.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpTeleport.kt @@ -23,120 +23,125 @@ import net.minecraft.world.item.enchantment.EnchantmentHelper import net.minecraft.world.level.ChunkPos import net.minecraft.world.phys.Vec3 -// TODO while we're making breaking changes I *really* want to have the vector in the entity's local space +// TODO while we're making breaking changes I *really* want to have the vector in the entity's local +// space // WRT its look vector object OpTeleport : SpellAction { - override val argc = 2 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - - val teleportee = args.getEntity(0, argc) - val delta = args.getVec3(1, argc) - env.assertEntityInRange(teleportee) - - if (!teleportee.canChangeDimensions() || teleportee.type.`is`(HexTags.Entities.CANNOT_TELEPORT)) - throw MishapImmuneEntity(teleportee) - - val targetPos = teleportee.position().add(delta) - if (!HexConfig.server().canTeleportInThisDimension(env.world.dimension())) - throw MishapBadLocation(targetPos, "bad_dimension") - - env.assertVecInWorld(targetPos) - if (!env.isVecInWorld(targetPos.subtract(0.0, 1.0, 0.0))) - throw MishapBadLocation(targetPos, "too_close_to_out") - - val targetMiddlePos = teleportee.position().add(0.0, teleportee.eyeHeight / 2.0, 0.0) - - return SpellAction.Result( - Spell(teleportee, delta), - 10 * MediaConstants.CRYSTAL_UNIT, - listOf(ParticleSpray.cloud(targetMiddlePos, 2.0), ParticleSpray.burst(targetMiddlePos.add(delta), 2.0)) - ) - } - - private data class Spell(val teleportee: Entity, val delta: Vec3) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - val distance = delta.length() - - teleportRespectSticky(teleportee, delta, env.world) - - if (teleportee is ServerPlayer && teleportee == env.castingEntity) { - // Drop items conditionally, based on distance teleported. - // MOST IMPORTANT: Never drop main hand item, since if it's a trinket, it will get duplicated later. - - val baseDropChance = distance / 10000.0 - - // Armor and hotbar items have a further reduced chance to be dropped since it's particularly annoying - // having to rearrange those. Also it makes sense for LORE REASONS probably, since the caster is more - // aware of items they use often. - for (armorItem in teleportee.inventory.armor) { - if (EnchantmentHelper.hasBindingCurse(armorItem)) - continue - - if (Math.random() < baseDropChance * 0.25) { - teleportee.drop(armorItem.copy(), true, false) - armorItem.shrink(armorItem.count) - } - } - - for ((pos, invItem) in teleportee.inventory.items.withIndex()) { - if (invItem == teleportee.mainHandItem) continue - val dropChance = if (pos < 9) baseDropChance * 0.5 else baseDropChance // hotbar - if (Math.random() < dropChance) { - teleportee.drop(invItem.copy(), true, false) - invItem.shrink(invItem.count) - } - } - - // we also don't drop the offhand just to be nice - } - } - } - - fun teleportRespectSticky(teleportee: Entity, delta: Vec3, world: ServerLevel) { - if (!HexConfig.server().canTeleportInThisDimension(world.dimension())) { - return - } - - val playersToUpdate = mutableListOf<ServerPlayer>() - val target = teleportee.position().add(delta) - - val cannotTeleport = teleportee.passengers.any { it.type.`is`(HexTags.Entities.CANNOT_TELEPORT) } - if (cannotTeleport) - return - - // A "sticky" entity teleports itself and its riders - val sticky = teleportee.type.`is`(HexTags.Entities.STICKY_TELEPORTERS) - - // TODO: this probably does funky things with stacks of passengers. I doubt this will come up in practice - // though - if (sticky) { - teleportee.stopRiding() - teleportee.indirectPassengers.filterIsInstance<ServerPlayer>().forEach(playersToUpdate::add) - // this handles teleporting the passengers - teleportee.teleportTo(target.x, target.y, target.z) - } else { - // Snap everyone off the stacks - teleportee.stopRiding() - teleportee.passengers.forEach(Entity::stopRiding) - if (teleportee is ServerPlayer) { - playersToUpdate.add(teleportee) - } else { - teleportee.setPos(teleportee.position().add(delta)) - } - } - - for (player in playersToUpdate) { - // See TeleportCommand - val chunkPos = ChunkPos(BlockPos.containing(delta)) - // the `1` is apparently for "distance." i'm not sure what it does but this is what - // /tp does - world.chunkSource.addRegionTicket(TicketType.POST_TELEPORT, chunkPos, 1, player.id) - player.connection.resetPosition() - player.setPos(target) - IXplatAbstractions.INSTANCE.sendPacketToPlayer(player, MsgBlinkS2C(delta)) - } - } + override val argc = 2 + + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + + val teleportee = args.getEntity(0, argc) + val delta = args.getVec3(1, argc) + env.assertEntityInRange(teleportee) + + if (!teleportee.canChangeDimensions() || teleportee.type.`is`(HexTags.Entities.CANNOT_TELEPORT)) + throw MishapImmuneEntity(teleportee) + + val targetPos = teleportee.position().add(delta) + if (!HexConfig.server().canTeleportInThisDimension(env.world.dimension())) + throw MishapBadLocation(targetPos, "bad_dimension") + + env.assertVecInWorld(targetPos) + if (!env.isVecInWorld(targetPos.subtract(0.0, 1.0, 0.0))) + throw MishapBadLocation(targetPos, "too_close_to_out") + + val targetMiddlePos = teleportee.position().add(0.0, teleportee.eyeHeight / 2.0, 0.0) + + return SpellAction.Result( + Spell(teleportee, delta), + 10 * MediaConstants.CRYSTAL_UNIT, + listOf( + ParticleSpray.cloud(targetMiddlePos, 2.0), + ParticleSpray.burst(targetMiddlePos.add(delta), 2.0) + ) + ) + } + + private data class Spell(val teleportee: Entity, val delta: Vec3) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + val distance = delta.length() + + teleportRespectSticky(teleportee, delta, env.world) + + if (teleportee is ServerPlayer && teleportee == env.castingEntity) { + // Drop items conditionally, based on distance teleported. + // MOST IMPORTANT: Never drop main hand item, since if it's a trinket, it will get + // duplicated later. + + val baseDropChance = distance / 10000.0 + + // Armor and hotbar items have a further reduced chance to be dropped since it's + // particularly annoying + // having to rearrange those. Also it makes sense for LORE REASONS probably, since the + // caster is more + // aware of items they use often. + for (armorItem in teleportee.inventory.armor) { + if (EnchantmentHelper.hasBindingCurse(armorItem)) continue + + if (Math.random() < baseDropChance * 0.25) { + teleportee.drop(armorItem.copy(), true, false) + armorItem.shrink(armorItem.count) + } + } + + for ((pos, invItem) in teleportee.inventory.items.withIndex()) { + if (invItem == teleportee.mainHandItem) continue + val dropChance = if (pos < 9) baseDropChance * 0.5 else baseDropChance // hotbar + if (Math.random() < dropChance) { + teleportee.drop(invItem.copy(), true, false) + invItem.shrink(invItem.count) + } + } + + // we also don't drop the offhand just to be nice + } + } + } + + fun teleportRespectSticky(teleportee: Entity, delta: Vec3, world: ServerLevel) { + if (!HexConfig.server().canTeleportInThisDimension(world.dimension())) { + return + } + + val playersToUpdate = mutableListOf<ServerPlayer>() + val target = teleportee.position().add(delta) + + val cannotTeleport = + teleportee.passengers.any { it.type.`is`(HexTags.Entities.CANNOT_TELEPORT) } + if (cannotTeleport) return + + // A "sticky" entity teleports itself and its riders + val sticky = teleportee.type.`is`(HexTags.Entities.STICKY_TELEPORTERS) + + // TODO: this probably does funky things with stacks of passengers. I doubt this will come up in + // practice + // though + if (sticky) { + teleportee.stopRiding() + teleportee.indirectPassengers.filterIsInstance<ServerPlayer>().forEach(playersToUpdate::add) + // this handles teleporting the passengers + teleportee.teleportTo(target.x, target.y, target.z) + } else { + // Snap everyone off the stacks + teleportee.stopRiding() + teleportee.passengers.forEach(Entity::stopRiding) + if (teleportee is ServerPlayer) { + playersToUpdate.add(teleportee) + } else { + teleportee.setPos(teleportee.position().add(delta)) + } + } + + for (player in playersToUpdate) { + // See TeleportCommand + val chunkPos = ChunkPos(BlockPos.containing(delta)) + // the `1` is apparently for "distance." i'm not sure what it does but this is what + // /tp does + world.chunkSource.addRegionTicket(TicketType.POST_TELEPORT, chunkPos, 1, player.id) + player.connection.resetPosition() + player.setPos(target) + IXplatAbstractions.INSTANCE.sendPacketToPlayer(player, MsgBlinkS2C(delta)) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpWeather.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpWeather.kt index ba648970cf..9c976dc978 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpWeather.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpWeather.kt @@ -7,33 +7,30 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.misc.MediaConstants class OpWeather(val rain: Boolean) : SpellAction { - override val argc = 0 + override val argc = 0 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - return SpellAction.Result( - Spell(rain), - if (this.rain) MediaConstants.CRYSTAL_UNIT else MediaConstants.SHARD_UNIT, - listOf() - ) - } + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + return SpellAction.Result( + Spell(rain), + if (this.rain) MediaConstants.CRYSTAL_UNIT else MediaConstants.SHARD_UNIT, + listOf() + ) + } - private data class Spell(val rain: Boolean) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - val w = env.world - if (w.isRaining != rain) { - w.levelData.isRaining = rain // i hex the rains down in minecraftia + private data class Spell(val rain: Boolean) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + val w = env.world + if (w.isRaining != rain) { + w.levelData.isRaining = rain // i hex the rains down in minecraftia - val (minTime, maxTime) = if (rain) (30 to 90) else (60 to 180) - val time = (w.random.nextInt(minTime, maxTime)) * 20 * 60 - if (rain) { - w.setWeatherParameters(0, time, true, w.random.nextDouble() < 0.05) - } else { - w.setWeatherParameters(time, 0, false, false) - } - } - } - } + val (minTime, maxTime) = if (rain) (30 to 90) else (60 to 180) + val time = (w.random.nextInt(minTime, maxTime)) * 20 * 60 + if (rain) { + w.setWeatherParameters(0, time, true, w.random.nextDouble() < 0.05) + } else { + w.setWeatherParameters(time, 0, false, false) + } + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpCreateSentinel.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpCreateSentinel.kt index 3b45740587..2e133966ca 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpCreateSentinel.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpCreateSentinel.kt @@ -14,35 +14,27 @@ import net.minecraft.server.level.ServerPlayer import net.minecraft.world.phys.Vec3 class OpCreateSentinel(val extendsRange: Boolean) : SpellAction { - override val argc = 1 + override val argc = 1 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - if (env.castingEntity !is ServerPlayer) - throw MishapBadCaster() + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + if (env.castingEntity !is ServerPlayer) throw MishapBadCaster() - val target = args.getVec3(0, argc) - env.assertVecInRange(target) + val target = args.getVec3(0, argc) + env.assertVecInRange(target) - return SpellAction.Result( - Spell(target, this.extendsRange), - MediaConstants.DUST_UNIT * if (extendsRange) 2 else 1, - listOf(ParticleSpray.burst(target, 2.0)) - ) - } + return SpellAction.Result( + Spell(target, this.extendsRange), + MediaConstants.DUST_UNIT * if (extendsRange) 2 else 1, + listOf(ParticleSpray.burst(target, 2.0)) + ) + } - private data class Spell(val target: Vec3, val extendsRange: Boolean) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - IXplatAbstractions.INSTANCE.setSentinel( - env.castingEntity as? ServerPlayer, - Sentinel( - extendsRange, - target, - env.world.dimension() - ) - ) - } - } + private data class Spell(val target: Vec3, val extendsRange: Boolean) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + IXplatAbstractions.INSTANCE.setSentinel( + env.castingEntity as? ServerPlayer, + Sentinel(extendsRange, target, env.world.dimension()) + ) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpDestroySentinel.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpDestroySentinel.kt index 43785a2adb..dee395bb12 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpDestroySentinel.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpDestroySentinel.kt @@ -12,33 +12,25 @@ import at.petrak.hexcasting.xplat.IXplatAbstractions import net.minecraft.server.level.ServerPlayer object OpDestroySentinel : SpellAction { - override val argc = 0 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - if (env.castingEntity !is ServerPlayer) - throw MishapBadCaster() + override val argc = 0 - val sentinel = IXplatAbstractions.INSTANCE.getSentinel(env.castingEntity as? ServerPlayer) + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + if (env.castingEntity !is ServerPlayer) throw MishapBadCaster() - // TODO why can't you remove things from other dimensions? - val dim = sentinel?.dimension - if (dim != null && dim != env.world.dimension()) - throw MishapLocationInWrongDimension(dim.location()) + val sentinel = IXplatAbstractions.INSTANCE.getSentinel(env.castingEntity as? ServerPlayer) - val particles = sentinel?.position?.let { listOf(ParticleSpray.cloud(it, 2.0)) } - ?: listOf() - return SpellAction.Result( - Spell, - MediaConstants.DUST_UNIT / 10, - particles - ) - } + // TODO why can't you remove things from other dimensions? + val dim = sentinel?.dimension + if (dim != null && dim != env.world.dimension()) + throw MishapLocationInWrongDimension(dim.location()) - private object Spell : RenderedSpell { - override fun cast(env: CastingEnvironment) { - IXplatAbstractions.INSTANCE.setSentinel(env.castingEntity as? ServerPlayer, null) - } - } + val particles = sentinel?.position?.let { listOf(ParticleSpray.cloud(it, 2.0)) } ?: listOf() + return SpellAction.Result(Spell, MediaConstants.DUST_UNIT / 10, particles) + } + + private object Spell : RenderedSpell { + override fun cast(env: CastingEnvironment) { + IXplatAbstractions.INSTANCE.setSentinel(env.castingEntity as? ServerPlayer, null) + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpGetSentinelPos.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpGetSentinelPos.kt index fa56812ca5..ad62dea7be 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpGetSentinelPos.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpGetSentinelPos.kt @@ -12,15 +12,17 @@ import at.petrak.hexcasting.xplat.IXplatAbstractions import net.minecraft.server.level.ServerPlayer object OpGetSentinelPos : ConstMediaAction { - override val argc = 0 - override val mediaCost: Long = MediaConstants.DUST_UNIT / 10 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - if (env.castingEntity !is ServerPlayer) - throw MishapBadCaster() + override val argc = 0 + override val mediaCost: Long = MediaConstants.DUST_UNIT / 10 - val sentinel = IXplatAbstractions.INSTANCE.getSentinel(env.castingEntity as? ServerPlayer) ?: return listOf(NullIota()) - if (sentinel.dimension != env.world.dimension()) - throw MishapLocationInWrongDimension(sentinel.dimension.location()) - return sentinel.position.asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + if (env.castingEntity !is ServerPlayer) throw MishapBadCaster() + + val sentinel = + IXplatAbstractions.INSTANCE.getSentinel(env.castingEntity as? ServerPlayer) + ?: return listOf(NullIota()) + if (sentinel.dimension != env.world.dimension()) + throw MishapLocationInWrongDimension(sentinel.dimension.location()) + return sentinel.position.asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpGetSentinelWayfind.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpGetSentinelWayfind.kt index cad52447ed..488897aad7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpGetSentinelWayfind.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/sentinel/OpGetSentinelWayfind.kt @@ -15,19 +15,21 @@ import net.minecraft.server.level.ServerPlayer // TODO I don't think anyone has ever used this operation in the history of the world. // TODO standardize "a negligible amount" of media to be 1/8 a dust object OpGetSentinelWayfind : ConstMediaAction { - override val argc = 1 - override val mediaCost: Long = MediaConstants.DUST_UNIT / 10 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - if (env.castingEntity !is ServerPlayer) - throw MishapBadCaster() + override val argc = 1 + override val mediaCost: Long = MediaConstants.DUST_UNIT / 10 - val from = args.getVec3(0, argc) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + if (env.castingEntity !is ServerPlayer) throw MishapBadCaster() - val sentinel = IXplatAbstractions.INSTANCE.getSentinel(env.castingEntity as? ServerPlayer) ?: return listOf(NullIota()) + val from = args.getVec3(0, argc) - if (sentinel.dimension != env.world.dimension()) - throw MishapLocationInWrongDimension(sentinel.dimension.location()) + val sentinel = + IXplatAbstractions.INSTANCE.getSentinel(env.castingEntity as? ServerPlayer) + ?: return listOf(NullIota()) - return sentinel.position.subtract(from).normalize().asActionResult - } + if (sentinel.dimension != env.world.dimension()) + throw MishapLocationInWrongDimension(sentinel.dimension.location()) + + return sentinel.position.subtract(from).normalize().asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt index 115ff4b6b5..fa00d05b2b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt @@ -12,50 +12,50 @@ import it.unimi.dsi.fastutil.ints.IntArrayList // "lehmer code" object OpAlwinfyHasAscendedToABeingOfPureMath : Action { - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() - - if (stack.isEmpty()) - throw MishapNotEnoughArgs(1, 0) - - val code = stack.getPositiveInt(stack.lastIndex) - stack.removeLast() - - val strides = IntArrayList() - for (f in FactorialIter()) { - if (f <= code) - strides.add(f) - else - break - } - - if (strides.size > stack.size) - throw MishapNotEnoughArgs(strides.size + 1, stack.size + 1) - var editTarget = stack.subList(stack.size - strides.size, stack.size) - val swap = editTarget.toMutableList() - var radix = code - for (divisor in strides.asReversed()) { - val index = radix / divisor - radix %= divisor - editTarget[0] = swap.removeAt(index) - // i hope this isn't O(n) - editTarget = editTarget.subList(1, editTarget.size) - } - - val image2 = image.withUsedOp().copy(stack = stack) - return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) - } - - private class FactorialIter : Iterator<Int> { - var acc = 1 - var n = 1 - override fun hasNext(): Boolean = true - - override fun next(): Int { - val out = this.acc - this.acc *= this.n - this.n++ - return out - } - } + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + val stack = image.stack.toMutableList() + + if (stack.isEmpty()) throw MishapNotEnoughArgs(1, 0) + + val code = stack.getPositiveInt(stack.lastIndex) + stack.removeLast() + + val strides = IntArrayList() + for (f in FactorialIter()) { + if (f <= code) strides.add(f) else break + } + + if (strides.size > stack.size) throw MishapNotEnoughArgs(strides.size + 1, stack.size + 1) + var editTarget = stack.subList(stack.size - strides.size, stack.size) + val swap = editTarget.toMutableList() + var radix = code + for (divisor in strides.asReversed()) { + val index = radix / divisor + radix %= divisor + editTarget[0] = swap.removeAt(index) + // i hope this isn't O(n) + editTarget = editTarget.subList(1, editTarget.size) + } + + val image2 = image.withUsedOp().copy(stack = stack) + return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) + } + + private class FactorialIter : Iterator<Int> { + var acc = 1 + var n = 1 + + override fun hasNext(): Boolean = true + + override fun next(): Int { + val out = this.acc + this.acc *= this.n + this.n++ + return out + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpDuplicateN.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpDuplicateN.kt index ca92c7f082..2543365bcd 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpDuplicateN.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpDuplicateN.kt @@ -7,19 +7,19 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.common.lib.hex.HexIotaTypes object OpDuplicateN : ConstMediaAction { - override val argc: Int - get() = 2 + override val argc: Int + get() = 2 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - var count = args.getPositiveInt(1, argc) + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + var count = args.getPositiveInt(1, argc) - if (count > HexIotaTypes.MAX_SERIALIZATION_TOTAL) { - // If we throw here, the message will point to us, which usually doesn't happen. - // So ensure that this check has no user-facing effects, just cap to MAX_SERIALIZATION_TOTAL, - // which will unconditionally trigger Too Many Iotas after we return. - count = HexIotaTypes.MAX_SERIALIZATION_TOTAL - } + if (count > HexIotaTypes.MAX_SERIALIZATION_TOTAL) { + // If we throw here, the message will point to us, which usually doesn't happen. + // So ensure that this check has no user-facing effects, just cap to MAX_SERIALIZATION_TOTAL, + // which will unconditionally trigger Too Many Iotas after we return. + count = HexIotaTypes.MAX_SERIALIZATION_TOTAL + } - return (List(count) { args[0] }) - } + return (List(count) { args[0] }) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFisherman.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFisherman.kt index c2c8874f28..98357ae7d4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFisherman.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFisherman.kt @@ -13,35 +13,38 @@ import kotlin.math.abs import kotlin.math.roundToInt object OpFisherman : Action { - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + val stack = image.stack.toMutableList() - if (stack.size < 2) - throw MishapNotEnoughArgs(2, stack.size) + if (stack.size < 2) throw MishapNotEnoughArgs(2, stack.size) - val depth = let { - val x = stack.last() - stack.removeLast() - val maxIdx = stack.size - 1 - if (x is DoubleIota) { - val double = x.double - val rounded = double.roundToInt() - if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded in -maxIdx..maxIdx) { - return@let rounded - } - } - throw MishapInvalidIota.of(x, 0, "int.between", -maxIdx, maxIdx) - } + val depth = let { + val x = stack.last() + stack.removeLast() + val maxIdx = stack.size - 1 + if (x is DoubleIota) { + val double = x.double + val rounded = double.roundToInt() + if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded in -maxIdx..maxIdx) { + return@let rounded + } + } + throw MishapInvalidIota.of(x, 0, "int.between", -maxIdx, maxIdx) + } - if (depth >= 0) { - val fish = stack.removeAt(stack.size - 1 - depth) - stack.add(fish) - } else { - val lure = stack.removeLast() - stack.add(stack.size + depth, lure) - } + if (depth >= 0) { + val fish = stack.removeAt(stack.size - 1 - depth) + stack.add(fish) + } else { + val lure = stack.removeLast() + stack.add(stack.size + depth, lure) + } - val image2 = image.withUsedOp().copy(stack = stack) - return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) - } + val image2 = image.withUsedOp().copy(stack = stack) + return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFishermanButItCopies.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFishermanButItCopies.kt index 91ed5b94a3..2e36b8f3fd 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFishermanButItCopies.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFishermanButItCopies.kt @@ -10,24 +10,27 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpFishermanButItCopies : Action { - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + val stack = image.stack.toMutableList() - if (stack.size < 2) - throw MishapNotEnoughArgs(2, stack.size) + if (stack.size < 2) throw MishapNotEnoughArgs(2, stack.size) - val depth = stack.getIntBetween(stack.lastIndex, -(stack.size - 2), stack.size - 2) - stack.removeLast() + val depth = stack.getIntBetween(stack.lastIndex, -(stack.size - 2), stack.size - 2) + stack.removeLast() - if (depth >= 0) { - val fish = stack[stack.size - 1 - depth] - stack.add(fish) - } else { - val lure = stack.last() - stack.add(stack.size - 1 + depth, lure) - } + if (depth >= 0) { + val fish = stack[stack.size - 1 - depth] + stack.add(fish) + } else { + val lure = stack.last() + stack.add(stack.size - 1 + depth, lure) + } - val image2 = image.withUsedOp().copy(stack = stack) - return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) - } + val image2 = image.withUsedOp().copy(stack = stack) + return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpMask.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpMask.kt index 3e15480bfd..8008a933eb 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpMask.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpMask.kt @@ -7,15 +7,14 @@ import it.unimi.dsi.fastutil.booleans.BooleanList import net.minecraft.resources.ResourceLocation class OpMask(val mask: BooleanList, val key: ResourceLocation) : ConstMediaAction { - override val argc: Int - get() = mask.size + override val argc: Int + get() = mask.size - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val out = ArrayList<Iota>(this.mask.size) - for ((i, include) in this.mask.withIndex()) { - if (include) - out.add(args[i]) - } - return out - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val out = ArrayList<Iota>(this.mask.size) + for ((i, include) in this.mask.withIndex()) { + if (include) out.add(args[i]) + } + return out + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpStackSize.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpStackSize.kt index eeec0f572b..cae575bcfe 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpStackSize.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpStackSize.kt @@ -9,10 +9,14 @@ import at.petrak.hexcasting.api.casting.iota.DoubleIota import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpStackSize : Action { - override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() - stack.add(DoubleIota(stack.size.toDouble())) - val image2 = image.withUsedOp().copy(stack = stack) - return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) - } + override fun operate( + env: CastingEnvironment, + image: CastingImage, + continuation: SpellContinuation + ): OperationResult { + val stack = image.stack.toMutableList() + stack.add(DoubleIota(stack.size.toDouble())) + val image2 = image.withUsedOp().copy(stack = stack) + return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpTwiddling.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpTwiddling.kt index b2f73c1bfd..bda06b3c0d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpTwiddling.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpTwiddling.kt @@ -5,9 +5,9 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota class OpTwiddling(val argumentCount: Int, val lookup: IntArray) : ConstMediaAction { - override val argc: Int - get() = this.argumentCount + override val argc: Int + get() = this.argumentCount - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> = - this.lookup.map(args::get) -} \ No newline at end of file + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> = + this.lookup.map(args::get) +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/SpecialHandlerMask.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/SpecialHandlerMask.kt index 29e0183358..5edfc626e2 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/SpecialHandlerMask.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/SpecialHandlerMask.kt @@ -19,70 +19,73 @@ import net.minecraft.network.chat.Component import net.minecraft.resources.ResourceLocation class SpecialHandlerMask(val mask: BooleanList) : SpecialHandler { - override fun act(): Action { - return InnerAction(this.mask) - } + override fun act(): Action { + return InnerAction(this.mask) + } - override fun getName(): Component { - val key = IXplatAbstractions.INSTANCE.specialHandlerRegistry.getResourceKey(HexSpecialHandlers.MASK).get() - val fingerprint = mask.map { if (it) '-' else 'v' }.joinToString("") - return HexAPI.instance().getSpecialHandlerI18nKey(key) - .asTranslatedComponent(fingerprint) - .lightPurple - } + override fun getName(): Component { + val key = + IXplatAbstractions.INSTANCE.specialHandlerRegistry + .getResourceKey(HexSpecialHandlers.MASK) + .get() + val fingerprint = mask.map { if (it) '-' else 'v' }.joinToString("") + return HexAPI.instance() + .getSpecialHandlerI18nKey(key) + .asTranslatedComponent(fingerprint) + .lightPurple + } - class InnerAction(val mask: BooleanList) : ConstMediaAction { - override val argc: Int - get() = this.mask.size + class InnerAction(val mask: BooleanList) : ConstMediaAction { + override val argc: Int + get() = this.mask.size - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val out = ArrayList<Iota>(this.mask.size) - for ((i, include) in this.mask.withIndex()) { - if (include) - out.add(args[i]) - } - return out - } - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val out = ArrayList<Iota>(this.mask.size) + for ((i, include) in this.mask.withIndex()) { + if (include) out.add(args[i]) + } + return out + } + } - class Factory : SpecialHandler.Factory<SpecialHandlerMask> { - override fun tryMatch(pat: HexPattern, env: CastingEnvironment): SpecialHandlerMask? { - val directions = pat.directions() + class Factory : SpecialHandler.Factory<SpecialHandlerMask> { + override fun tryMatch(pat: HexPattern, env: CastingEnvironment): SpecialHandlerMask? { + val directions = pat.directions() - var flatDir = pat.startDir - if (pat.angles.isNotEmpty() && pat.angles[0] == HexAngle.LEFT_BACK) { - flatDir = directions[0].rotatedBy(HexAngle.LEFT); - } + var flatDir = pat.startDir + if (pat.angles.isNotEmpty() && pat.angles[0] == HexAngle.LEFT_BACK) { + flatDir = directions[0].rotatedBy(HexAngle.LEFT) + } - // TODO: we could probably definitely do this with a long to make it faster - val mask = BooleanArrayList() - var i = 0; - while (i < directions.size) { - // Angle with respect to the *start direction* - val angle = directions[i].angleFrom(flatDir); - if (angle == HexAngle.FORWARD) { - mask.add(true) - i++ - continue; - } - if (i >= directions.size - 1) { - // then we're out of angles! - return null - } - val angle2 = directions[i + 1].angleFrom(flatDir); - if (angle == HexAngle.RIGHT && angle2 == HexAngle.LEFT) { - mask.add(false) - // skip both segments of the dip - i += 2 - continue - } - return null - } - return SpecialHandlerMask(mask) - } - } + // TODO: we could probably definitely do this with a long to make it faster + val mask = BooleanArrayList() + var i = 0 + while (i < directions.size) { + // Angle with respect to the *start direction* + val angle = directions[i].angleFrom(flatDir) + if (angle == HexAngle.FORWARD) { + mask.add(true) + i++ + continue + } + if (i >= directions.size - 1) { + // then we're out of angles! + return null + } + val angle2 = directions[i + 1].angleFrom(flatDir) + if (angle == HexAngle.RIGHT && angle2 == HexAngle.LEFT) { + mask.add(false) + // skip both segments of the dip + i += 2 + continue + } + return null + } + return SpecialHandlerMask(mask) + } + } - companion object { - public val NAME: ResourceLocation = modLoc("mask") - } -} \ No newline at end of file + companion object { + public val NAME: ResourceLocation = modLoc("mask") + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/BitwiseSetArithmetic.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/BitwiseSetArithmetic.kt index 715297a051..72659f9f36 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/BitwiseSetArithmetic.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/BitwiseSetArithmetic.kt @@ -16,32 +16,36 @@ import java.util.function.LongUnaryOperator import kotlin.math.roundToLong object BitwiseSetArithmetic : Arithmetic { - private val OPS = listOf( - AND, - OR, - XOR, - NOT - ) + private val OPS = listOf(AND, OR, XOR, NOT) - override fun arithName() = "bitwise_set_ops" + override fun arithName() = "bitwise_set_ops" - override fun opTypes() = OPS + override fun opTypes() = OPS - override fun getOperator(pattern: HexPattern): Operator = when (pattern) { - AND -> make2 { x, y -> x and y } - OR -> make2 { x, y -> x or y } - XOR -> make2 { x, y -> x xor y } - NOT -> make1 { x -> x.inv() } - else -> throw InvalidOperatorException("$pattern is not a valid operator in Arithmetic $this.") - } + override fun getOperator(pattern: HexPattern): Operator = + when (pattern) { + AND -> make2 { x, y -> x and y } + OR -> make2 { x, y -> x or y } + XOR -> make2 { x, y -> x xor y } + NOT -> make1 { x -> x.inv() } + else -> + throw InvalidOperatorException("$pattern is not a valid operator in Arithmetic $this.") + } - private fun make1(op: LongUnaryOperator): OperatorUnary = OperatorUnary(DoubleArithmetic.ACCEPTS) - { i: Iota -> DoubleIota(op.applyAsLong(downcast(i, DOUBLE).double.roundToLong()).toDouble()) } + private fun make1(op: LongUnaryOperator): OperatorUnary = + OperatorUnary(DoubleArithmetic.ACCEPTS) { i: Iota -> + DoubleIota(op.applyAsLong(downcast(i, DOUBLE).double.roundToLong()).toDouble()) + } - private fun make2(op: LongBinaryOperator): OperatorBinary = OperatorBinary(DoubleArithmetic.ACCEPTS) - { i: Iota, j: Iota -> DoubleIota( - op.applyAsLong( - downcast(i, DOUBLE).double.roundToLong(), - downcast(j, DOUBLE).double.roundToLong() - ).toDouble()) } -} \ No newline at end of file + private fun make2(op: LongBinaryOperator): OperatorBinary = + OperatorBinary(DoubleArithmetic.ACCEPTS) { i: Iota, j: Iota -> + DoubleIota( + op + .applyAsLong( + downcast(i, DOUBLE).double.roundToLong(), + downcast(j, DOUBLE).double.roundToLong() + ) + .toDouble() + ) + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/BoolArithmetic.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/BoolArithmetic.kt index 79e58793a7..97cdcf043c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/BoolArithmetic.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/BoolArithmetic.kt @@ -18,44 +18,49 @@ import it.unimi.dsi.fastutil.booleans.BooleanUnaryOperator import java.util.function.BiFunction object BoolArithmetic : Arithmetic { - private val OPS = listOf( - AND, - OR, - XOR, - GREATER, - LESS, - GREATER_EQ, - LESS_EQ, - NOT, - ABS - ) - - override fun arithName(): String = "bool_math" - - override fun opTypes() = OPS - - override fun getOperator(pattern: HexPattern): Operator = when (pattern) { - AND -> make2 { a, b -> a and b } - OR -> make2 { a, b -> a or b } - XOR -> make2 { a, b -> a xor b } - GREATER -> makeComp { x, y -> x > y } - LESS -> makeComp { x, y -> x < y } - GREATER_EQ -> makeComp { x, y -> DoubleIota.tolerates(x, y) || x >= y } - LESS_EQ -> makeComp { x, y -> DoubleIota.tolerates(x, y) || x <= y } - NOT -> make1 { a -> !a } - ABS -> OperatorUnary(ALL_BOOLS) { i: Iota -> DoubleIota( if (Operator.downcast(i, BOOLEAN).bool) 1.0 else 0.0 ) } - else -> throw InvalidOperatorException("$pattern is not a valid operator in Arithmetic $this.") - } - val ALL_BOOLS: IotaMultiPredicate = IotaMultiPredicate.all(IotaPredicate.ofType(BOOLEAN)) - - private fun make1(op: BooleanUnaryOperator): OperatorUnary { - return OperatorUnary(ALL_BOOLS) { i: Iota -> BooleanIota(op.apply(Operator.downcast(i, BOOLEAN).bool)) } - } - private fun make2(op: BooleanBinaryOperator): OperatorBinary { - return OperatorBinary(ALL_BOOLS) { i: Iota, j: Iota -> BooleanIota(op.apply(Operator.downcast(i, BOOLEAN).bool, Operator.downcast(j, BOOLEAN).bool)) } - } - private fun makeComp(op: BiFunction<Double, Double, Boolean>): OperatorBinary { - return OperatorBinary(DoubleArithmetic.ACCEPTS) - { i: Iota, j: Iota -> BooleanIota(op.apply(Operator.downcast(i, DOUBLE).double, Operator.downcast(j, DOUBLE).double)) } - } -} \ No newline at end of file + private val OPS = listOf(AND, OR, XOR, GREATER, LESS, GREATER_EQ, LESS_EQ, NOT, ABS) + + override fun arithName(): String = "bool_math" + + override fun opTypes() = OPS + + override fun getOperator(pattern: HexPattern): Operator = + when (pattern) { + AND -> make2 { a, b -> a and b } + OR -> make2 { a, b -> a or b } + XOR -> make2 { a, b -> a xor b } + GREATER -> makeComp { x, y -> x > y } + LESS -> makeComp { x, y -> x < y } + GREATER_EQ -> makeComp { x, y -> DoubleIota.tolerates(x, y) || x >= y } + LESS_EQ -> makeComp { x, y -> DoubleIota.tolerates(x, y) || x <= y } + NOT -> make1 { a -> !a } + ABS -> + OperatorUnary(ALL_BOOLS) { i: Iota -> + DoubleIota(if (Operator.downcast(i, BOOLEAN).bool) 1.0 else 0.0) + } + else -> + throw InvalidOperatorException("$pattern is not a valid operator in Arithmetic $this.") + } + + val ALL_BOOLS: IotaMultiPredicate = IotaMultiPredicate.all(IotaPredicate.ofType(BOOLEAN)) + + private fun make1(op: BooleanUnaryOperator): OperatorUnary { + return OperatorUnary(ALL_BOOLS) { i: Iota -> + BooleanIota(op.apply(Operator.downcast(i, BOOLEAN).bool)) + } + } + + private fun make2(op: BooleanBinaryOperator): OperatorBinary { + return OperatorBinary(ALL_BOOLS) { i: Iota, j: Iota -> + BooleanIota(op.apply(Operator.downcast(i, BOOLEAN).bool, Operator.downcast(j, BOOLEAN).bool)) + } + } + + private fun makeComp(op: BiFunction<Double, Double, Boolean>): OperatorBinary { + return OperatorBinary(DoubleArithmetic.ACCEPTS) { i: Iota, j: Iota -> + BooleanIota( + op.apply(Operator.downcast(i, DOUBLE).double, Operator.downcast(j, DOUBLE).double) + ) + } + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt index 075a17a76f..1fe5612d6f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt @@ -20,63 +20,82 @@ import java.util.function.DoubleUnaryOperator import kotlin.math.* object DoubleArithmetic : Arithmetic { - @JvmField - val OPS = listOf( - ADD, - SUB, - MUL, - DIV, - ABS, - POW, - FLOOR, - CEIL, - SIN, - COS, - TAN, - ARCSIN, - ARCCOS, - ARCTAN, - ARCTAN2, - LOG, - MOD - ) + @JvmField + val OPS = + listOf( + ADD, + SUB, + MUL, + DIV, + ABS, + POW, + FLOOR, + CEIL, + SIN, + COS, + TAN, + ARCSIN, + ARCCOS, + ARCTAN, + ARCTAN2, + LOG, + MOD + ) - /** - * An example of an IotaMultiPredicate, which returns true only if all arguments to the Operator are DoubleIotas. - */ - val ACCEPTS: IotaMultiPredicate = IotaMultiPredicate.all(IotaPredicate.ofType(HexIotaTypes.DOUBLE)) + /** + * An example of an IotaMultiPredicate, which returns true only if all arguments to the Operator + * are DoubleIotas. + */ + val ACCEPTS: IotaMultiPredicate = + IotaMultiPredicate.all(IotaPredicate.ofType(HexIotaTypes.DOUBLE)) - override fun arithName() = "double_math" + override fun arithName() = "double_math" - override fun opTypes() = OPS + override fun opTypes() = OPS - override fun getOperator(pattern: HexPattern): Operator { - return when (pattern) { - ADD -> make2 { a, b -> a + b } - SUB -> make2 { a, b -> a - b } - MUL -> make2 { a, b -> a * b } - DIV -> make2 { a, b -> if (b == 0.0) throw MishapDivideByZero.of(a, b) else a / b } - ABS -> make1 { a -> abs(a) } - // throw MishapDivideByZero if raising a negative number to a fractional power (ie. sqrt(-1) etc) - POW -> make2 { a, b -> if (a < 0 && !DoubleIota.tolerates(floor(b), b)) throw MishapDivideByZero.of(a, b, "exponent") else a.pow(b) } - FLOOR -> make1 { a -> floor(a) } - CEIL -> make1 { a -> ceil(a) } - SIN -> make1 { a -> sin(a) } - COS -> make1 { a -> cos(a) } - TAN -> make1 { a -> if (cos(a) == 0.0) throw MishapDivideByZero.tan(a) else tan(a) } - ARCSIN -> make1 { a -> asin(a.asDoubleBetween(-1.0, 1.0, 0)) } - ARCCOS -> make1 { a -> acos(a.asDoubleBetween(-1.0, 1.0, 0)) } - ARCTAN -> make1 { a -> atan(a) } - ARCTAN2 -> make2 { a, b -> atan2(a, b) } - LOG -> OperatorLog - MOD -> make2 { a, b -> if (b == 0.0) throw MishapDivideByZero.of(a, b) else a % b } - else -> throw InvalidOperatorException("$pattern is not a valid operator in Arithmetic $this.") - } - } + override fun getOperator(pattern: HexPattern): Operator { + return when (pattern) { + ADD -> make2 { a, b -> a + b } + SUB -> make2 { a, b -> a - b } + MUL -> make2 { a, b -> a * b } + DIV -> make2 { a, b -> if (b == 0.0) throw MishapDivideByZero.of(a, b) else a / b } + ABS -> make1 { a -> abs(a) } + // throw MishapDivideByZero if raising a negative number to a fractional power (ie. sqrt(-1) + // etc) + POW -> + make2 { a, b -> + if (a < 0 && !DoubleIota.tolerates(floor(b), b)) + throw MishapDivideByZero.of(a, b, "exponent") + else a.pow(b) + } + FLOOR -> make1 { a -> floor(a) } + CEIL -> make1 { a -> ceil(a) } + SIN -> make1 { a -> sin(a) } + COS -> make1 { a -> cos(a) } + TAN -> make1 { a -> if (cos(a) == 0.0) throw MishapDivideByZero.tan(a) else tan(a) } + ARCSIN -> make1 { a -> asin(a.asDoubleBetween(-1.0, 1.0, 0)) } + ARCCOS -> make1 { a -> acos(a.asDoubleBetween(-1.0, 1.0, 0)) } + ARCTAN -> make1 { a -> atan(a) } + ARCTAN2 -> make2 { a, b -> atan2(a, b) } + LOG -> OperatorLog + MOD -> make2 { a, b -> if (b == 0.0) throw MishapDivideByZero.of(a, b) else a % b } + else -> + throw InvalidOperatorException("$pattern is not a valid operator in Arithmetic $this.") + } + } - fun make1(op: DoubleUnaryOperator) = OperatorUnary(ACCEPTS) - { i: Iota -> DoubleIota(op.applyAsDouble(Operator.downcast(i, HexIotaTypes.DOUBLE).double)) } + fun make1(op: DoubleUnaryOperator) = + OperatorUnary(ACCEPTS) { i: Iota -> + DoubleIota(op.applyAsDouble(Operator.downcast(i, HexIotaTypes.DOUBLE).double)) + } - fun make2(op: DoubleBinaryOperator) = OperatorBinary(ACCEPTS) - { i: Iota, j: Iota -> DoubleIota(op.applyAsDouble(Operator.downcast(i, HexIotaTypes.DOUBLE).double, Operator.downcast(j, HexIotaTypes.DOUBLE).double)) } + fun make2(op: DoubleBinaryOperator) = + OperatorBinary(ACCEPTS) { i: Iota, j: Iota -> + DoubleIota( + op.applyAsDouble( + Operator.downcast(i, HexIotaTypes.DOUBLE).double, + Operator.downcast(j, HexIotaTypes.DOUBLE).double + ) + ) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/ListArithmetic.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/ListArithmetic.kt index 35a34e61ec..c648da64a7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/ListArithmetic.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/ListArithmetic.kt @@ -20,45 +20,43 @@ import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.LIST import java.util.function.BinaryOperator object ListArithmetic : Arithmetic { - private val OPS = listOf( - INDEX, - SLICE, - APPEND, - UNAPPEND, - ADD, - ABS, - REV, - INDEX_OF, - REMOVE, - REPLACE, - CONS, - UNCONS - ) + private val OPS = + listOf(INDEX, SLICE, APPEND, UNAPPEND, ADD, ABS, REV, INDEX_OF, REMOVE, REPLACE, CONS, UNCONS) - override fun arithName() = "list_ops" + override fun arithName() = "list_ops" - override fun opTypes(): Iterable<HexPattern> = OPS + override fun opTypes(): Iterable<HexPattern> = OPS - override fun getOperator(pattern: HexPattern): Operator { - return when (pattern) { - INDEX -> OperatorIndex - SLICE -> OperatorSlice - APPEND -> OperatorAppend - UNAPPEND -> OperatorUnappend - ADD -> make2 { list0, list1 -> list0 + list1 } - ABS -> OperatorUnary(all(IotaPredicate.ofType(LIST))) { iota: Iota -> DoubleIota(downcast(iota, LIST).list.size().toDouble()) } - REV -> OperatorUnary(all(IotaPredicate.ofType(LIST))) { iota: Iota -> ListIota(downcast(iota, LIST).list.toList().asReversed()) } - INDEX_OF -> OperatorIndexOf - REMOVE -> OperatorRemove - REPLACE -> OperatorReplace - CONS -> OperatorBinary(pair(IotaPredicate.ofType(LIST), IotaPredicate.TRUE)) { list, iota -> ListIota(SpellList.LPair(iota, downcast(list, LIST).list)) } - UNCONS -> OperatorUnCons - else -> throw InvalidOperatorException("$pattern is not a valid operator in Arithmetic $this.") - } - } + override fun getOperator(pattern: HexPattern): Operator { + return when (pattern) { + INDEX -> OperatorIndex + SLICE -> OperatorSlice + APPEND -> OperatorAppend + UNAPPEND -> OperatorUnappend + ADD -> make2 { list0, list1 -> list0 + list1 } + ABS -> + OperatorUnary(all(IotaPredicate.ofType(LIST))) { iota: Iota -> + DoubleIota(downcast(iota, LIST).list.size().toDouble()) + } + REV -> + OperatorUnary(all(IotaPredicate.ofType(LIST))) { iota: Iota -> + ListIota(downcast(iota, LIST).list.toList().asReversed()) + } + INDEX_OF -> OperatorIndexOf + REMOVE -> OperatorRemove + REPLACE -> OperatorReplace + CONS -> + OperatorBinary(pair(IotaPredicate.ofType(LIST), IotaPredicate.TRUE)) { list, iota -> + ListIota(SpellList.LPair(iota, downcast(list, LIST).list)) + } + UNCONS -> OperatorUnCons + else -> + throw InvalidOperatorException("$pattern is not a valid operator in Arithmetic $this.") + } + } - private fun make2(op: BinaryOperator<List<Iota>>): OperatorBinary = OperatorBinary(all(IotaPredicate.ofType(LIST))) - { i: Iota, j: Iota -> ListIota( - op.apply(downcast(i, LIST).list.toList(), downcast(j, LIST).list.toList()) - ) } + private fun make2(op: BinaryOperator<List<Iota>>): OperatorBinary = + OperatorBinary(all(IotaPredicate.ofType(LIST))) { i: Iota, j: Iota -> + ListIota(op.apply(downcast(i, LIST).list.toList(), downcast(j, LIST).list.toList())) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/ListSetArithmetic.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/ListSetArithmetic.kt index d412c66652..63d1e1273c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/ListSetArithmetic.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/ListSetArithmetic.kt @@ -16,28 +16,29 @@ import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.LIST import java.util.function.BinaryOperator object ListSetArithmetic : Arithmetic { - private val OPS = listOf( - AND, - OR, - XOR, - UNIQUE - ) + private val OPS = listOf(AND, OR, XOR, UNIQUE) - override fun arithName() = "list_set_ops" + override fun arithName() = "list_set_ops" - override fun opTypes() = OPS + override fun opTypes() = OPS - override fun getOperator(pattern: HexPattern): Operator = when (pattern) { - AND -> make2 { list0, list1 -> list0.filter { x -> list1.any { Iota.tolerates(x, it) } } } - OR -> make2 { list0, list1 -> list0 + list1.filter { x -> list0.none { Iota.tolerates(x, it) } } } - XOR -> make2 { list0, list1 -> list0.filter { x0 -> list1.none {Iota.tolerates(x0, it) } } + list1.filter { x1 -> list0.none { Iota.tolerates(x1, it) } } } - UNIQUE -> OperatorUnique - else -> throw InvalidOperatorException("$pattern is not a valid operator in Arithmetic $this.") - } + override fun getOperator(pattern: HexPattern): Operator = + when (pattern) { + AND -> make2 { list0, list1 -> list0.filter { x -> list1.any { Iota.tolerates(x, it) } } } + OR -> + make2 { list0, list1 -> list0 + list1.filter { x -> list0.none { Iota.tolerates(x, it) } } } + XOR -> + make2 { list0, list1 -> + list0.filter { x0 -> list1.none { Iota.tolerates(x0, it) } } + + list1.filter { x1 -> list0.none { Iota.tolerates(x1, it) } } + } + UNIQUE -> OperatorUnique + else -> + throw InvalidOperatorException("$pattern is not a valid operator in Arithmetic $this.") + } - - private fun make2(op: BinaryOperator<List<Iota>>): OperatorBinary = OperatorBinary(all(IotaPredicate.ofType(LIST))) - { i: Iota, j: Iota -> ListIota( - op.apply(downcast(i, LIST).list.toList(), downcast(j, LIST).list.toList()) - ) } -} \ No newline at end of file + private fun make2(op: BinaryOperator<List<Iota>>): OperatorBinary = + OperatorBinary(all(IotaPredicate.ofType(LIST))) { i: Iota, j: Iota -> + ListIota(op.apply(downcast(i, LIST).list.toList(), downcast(j, LIST).list.toList())) + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/Vec3Arithmetic.java b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/Vec3Arithmetic.java index 3049177a97..ff3edfd505 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/Vec3Arithmetic.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/Vec3Arithmetic.java @@ -1,43 +1,32 @@ package at.petrak.hexcasting.common.casting.arithmetic; +import static at.petrak.hexcasting.api.casting.arithmetic.operator.Operator.downcast; +import static at.petrak.hexcasting.common.lib.hex.HexIotaTypes.*; + import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic; import at.petrak.hexcasting.api.casting.arithmetic.engine.InvalidOperatorException; +import at.petrak.hexcasting.api.casting.arithmetic.operator.*; import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate; import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate; -import at.petrak.hexcasting.api.casting.arithmetic.operator.*; import at.petrak.hexcasting.api.casting.iota.DoubleIota; import at.petrak.hexcasting.api.casting.iota.Vec3Iota; import at.petrak.hexcasting.api.casting.math.HexPattern; import at.petrak.hexcasting.common.casting.arithmetic.operator.vec.OperatorPack; import at.petrak.hexcasting.common.casting.arithmetic.operator.vec.OperatorUnpack; import at.petrak.hexcasting.common.casting.arithmetic.operator.vec.OperatorVec3Delegating; -import net.minecraft.world.phys.Vec3; - import java.util.List; import java.util.function.BiFunction; import java.util.function.Function; - -import static at.petrak.hexcasting.api.casting.arithmetic.operator.Operator.downcast; -import static at.petrak.hexcasting.common.lib.hex.HexIotaTypes.*; +import net.minecraft.world.phys.Vec3; public enum Vec3Arithmetic implements Arithmetic { INSTANCE; - public static final List<HexPattern> OPS = List.of( - PACK, - UNPACK, - ADD, - SUB, - MUL, - DIV, - ABS, - POW, - FLOOR, - CEIL, - MOD - ); + public static final List<HexPattern> OPS = + List.of(PACK, UNPACK, ADD, SUB, MUL, DIV, ABS, POW, FLOOR, CEIL, MOD); - public static final IotaMultiPredicate ACCEPTS = IotaMultiPredicate.any(IotaPredicate.ofType(VEC3), IotaPredicate.ofType(DOUBLE)); + public static final IotaMultiPredicate ACCEPTS = + IotaMultiPredicate.any(IotaPredicate.ofType(VEC3), IotaPredicate.ofType(DOUBLE)); @Override public String arithName() { @@ -74,21 +63,29 @@ public Operator getOperator(HexPattern pattern) { } else if (pattern.equals(MOD)) { return make2Fallback(pattern); } - throw new InvalidOperatorException(pattern + " is not a valid operator in Arithmetic " + this + "."); + throw new InvalidOperatorException( + pattern + " is not a valid operator in Arithmetic " + this + "."); } + public static OperatorUnary make1(Function<Vec3, Vec3> op) { return new OperatorUnary(ACCEPTS, i -> new Vec3Iota(op.apply(downcast(i, VEC3).getVec3()))); } + public static OperatorUnary make1Double(Function<Vec3, Double> op) { return new OperatorUnary(ACCEPTS, i -> new DoubleIota(op.apply(downcast(i, VEC3).getVec3()))); } + public static OperatorVec3Delegating make2Fallback(HexPattern pattern) { return new OperatorVec3Delegating(null, pattern); } - public static OperatorVec3Delegating make2Double(HexPattern pattern, BiFunction<Vec3, Vec3, Double> op) { + + public static OperatorVec3Delegating make2Double( + HexPattern pattern, BiFunction<Vec3, Vec3, Double> op) { return new OperatorVec3Delegating(op.andThen(DoubleIota::new), pattern); } - public static OperatorVec3Delegating make2Vec(HexPattern pattern, BiFunction<Vec3, Vec3, Vec3> op) { + + public static OperatorVec3Delegating make2Vec( + HexPattern pattern, BiFunction<Vec3, Vec3, Vec3> op) { return new OperatorVec3Delegating(op.andThen(Vec3Iota::new), pattern); } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/OperatorLog.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/OperatorLog.kt index 0a36d8ac16..f3b12a2523 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/OperatorLog.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/OperatorLog.kt @@ -1,6 +1,5 @@ package at.petrak.hexcasting.common.casting.arithmetic.operator -import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate @@ -12,12 +11,12 @@ import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.DOUBLE import kotlin.math.log object OperatorLog : OperatorBasic(2, IotaMultiPredicate.all(IotaPredicate.ofType(DOUBLE))) { - override fun apply(iotas: Iterable<Iota>, env : CastingEnvironment): Iterable<Iota> { - val it = iotas.iterator().withIndex() - val value = it.nextDouble(arity) - val base = it.nextDouble(arity) - if (value <= 0.0 || base <= 0.0 || base == 1.0) - throw MishapDivideByZero.of(iotas.first(), iotas.last(), "logarithm") - return log(value, base).asActionResult - } -} \ No newline at end of file + override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { + val it = iotas.iterator().withIndex() + val value = it.nextDouble(arity) + val base = it.nextDouble(arity) + if (value <= 0.0 || base <= 0.0 || base == 1.0) + throw MishapDivideByZero.of(iotas.first(), iotas.last(), "logarithm") + return log(value, base).asActionResult + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/OperatorUtils.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/OperatorUtils.kt index 24247286c8..9004e41cdd 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/OperatorUtils.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/OperatorUtils.kt @@ -9,59 +9,71 @@ import kotlin.math.abs import kotlin.math.roundToInt fun Iterator<IndexedValue<Iota>>.nextList(argc: Int = 0): SpellList { - val (idx, x) = this.next() - if (x is ListIota) { - return x.list - } else { - throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "list") - } + val (idx, x) = this.next() + if (x is ListIota) { + return x.list + } else { + throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "list") + } } fun Iterator<IndexedValue<Iota>>.nextDouble(argc: Int = 0): Double { - val (idx, x) = this.next() - if (x is DoubleIota) return x.double - throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "double") + val (idx, x) = this.next() + if (x is DoubleIota) return x.double + throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "double") } fun Iterator<IndexedValue<Iota>>.nextInt(argc: Int = 0): Int { - val (idx, x) = this.next() - if (x is DoubleIota) { - val double = x.double - val rounded = double.roundToInt() - if (abs(double - rounded) <= DoubleIota.TOLERANCE) { - return rounded - } - } - throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int") + val (idx, x) = this.next() + if (x is DoubleIota) { + val double = x.double + val rounded = double.roundToInt() + if (abs(double - rounded) <= DoubleIota.TOLERANCE) { + return rounded + } + } + throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int") } fun Iterator<IndexedValue<Iota>>.nextPositiveIntUnder(max: Int, argc: Int = 0): Int { - val (idx, x) = this.next() - if (x is DoubleIota) { - val double = x.double - val rounded = double.roundToInt() - if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded in 0 until max) { - return rounded - } - } - throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int.positive.less.equal", max) + val (idx, x) = this.next() + if (x is DoubleIota) { + val double = x.double + val rounded = double.roundToInt() + if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded in 0 until max) { + return rounded + } + } + throw MishapInvalidIota.of( + x, + if (argc == 0) idx else argc - (idx + 1), + "int.positive.less.equal", + max + ) } fun Iterator<IndexedValue<Iota>>.nextPositiveIntUnderInclusive(max: Int, argc: Int = 0): Int { - val (idx, x) = this.next() - if (x is DoubleIota) { - val double = x.double - val rounded = double.roundToInt() - if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded in 0..max) { - return rounded - } - } - throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int.positive.less.equal", max) + val (idx, x) = this.next() + if (x is DoubleIota) { + val double = x.double + val rounded = double.roundToInt() + if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded in 0..max) { + return rounded + } + } + throw MishapInvalidIota.of( + x, + if (argc == 0) idx else argc - (idx + 1), + "int.positive.less.equal", + max + ) } /** - * Returns the double if it is between [min] and [max] (inclusive), and throws a mishap otherwise. [idx] should be - * the double's index from the top of the stack (i.e. top iota has [idx]=0, second from the top has [idx]=1, etc.). + * Returns the double if it is between [min] and [max] (inclusive), and throws a mishap otherwise. + * [idx] should be the double's index from the top of the stack (i.e. top iota has [idx]=0, second + * from the top has [idx]=1, etc.). */ -fun Double.asDoubleBetween(min: Double, max: Double, idx: Int) = if (this in min .. max) this - else throw MishapInvalidIota.of(DoubleIota(this), idx, "double.between", min, max) \ No newline at end of file +fun Double.asDoubleBetween(min: Double, max: Double, idx: Int) = + if (this in min..max) this + else throw MishapInvalidIota.of(DoubleIota(this), idx, "double.between", min, max) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorAppend.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorAppend.kt index 724e5f6746..6fbfbef70f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorAppend.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorAppend.kt @@ -1,6 +1,5 @@ package at.petrak.hexcasting.common.casting.arithmetic.operator.list -import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate @@ -10,11 +9,12 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.common.casting.arithmetic.operator.nextList import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.* -object OperatorAppend : OperatorBasic(2, IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.TRUE)) { - override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { - val it = iotas.iterator().withIndex() - val list = it.nextList(arity).toMutableList() - list.add(it.next().value) - return list.asActionResult - } -} \ No newline at end of file +object OperatorAppend : + OperatorBasic(2, IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.TRUE)) { + override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { + val it = iotas.iterator().withIndex() + val list = it.nextList(arity).toMutableList() + list.add(it.next().value) + return list.asActionResult + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorIndex.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorIndex.kt index 2ecb5fc140..bf4bedb9bf 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorIndex.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorIndex.kt @@ -1,21 +1,24 @@ package at.petrak.hexcasting.common.casting.arithmetic.operator.list +import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate -import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator -import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.NullIota import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.* import kotlin.math.roundToInt -object OperatorIndex : OperatorBasic(2, IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.ofType(DOUBLE))) { - override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { - val it = iotas.iterator() - val list = downcast(it.next(), LIST).list.toMutableList() - val index = downcast(it.next(), DOUBLE).double - val x = list.getOrElse(index.roundToInt()) { NullIota() } - return listOf(x) - } +object OperatorIndex : + OperatorBasic( + 2, + IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.ofType(DOUBLE)) + ) { + override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { + val it = iotas.iterator() + val list = downcast(it.next(), LIST).list.toMutableList() + val index = downcast(it.next(), DOUBLE).double + val x = list.getOrElse(index.roundToInt()) { NullIota() } + return listOf(x) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorIndexOf.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorIndexOf.kt index a3d711d57a..991919462b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorIndexOf.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorIndexOf.kt @@ -1,6 +1,5 @@ package at.petrak.hexcasting.common.casting.arithmetic.operator.list -import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate @@ -10,11 +9,12 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.common.casting.arithmetic.operator.nextList import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.* -object OperatorIndexOf : OperatorBasic(2, IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.TRUE)) { - override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { - val it = iotas.iterator().withIndex() - val list = it.nextList(arity).toList() - val toFind = it.next().value - return list.indexOfFirst { Iota.tolerates(toFind, it) }.asActionResult - } -} \ No newline at end of file +object OperatorIndexOf : + OperatorBasic(2, IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.TRUE)) { + override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { + val it = iotas.iterator().withIndex() + val list = it.nextList(arity).toList() + val toFind = it.next().value + return list.indexOfFirst { Iota.tolerates(toFind, it) }.asActionResult + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorRemove.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorRemove.kt index 1a1af53cfc..79e03564d1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorRemove.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorRemove.kt @@ -1,6 +1,5 @@ package at.petrak.hexcasting.common.casting.arithmetic.operator.list -import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate @@ -11,14 +10,17 @@ import at.petrak.hexcasting.common.casting.arithmetic.operator.nextInt import at.petrak.hexcasting.common.casting.arithmetic.operator.nextList import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.* -object OperatorRemove : OperatorBasic(2, IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.ofType(DOUBLE))) { - override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { - val it = iotas.iterator().withIndex() - val list = it.nextList(arity).toMutableList() - val index = it.nextInt(arity) - if (index < 0 || index >= list.size) - return list.asActionResult - list.removeAt(index) - return list.asActionResult - } -} \ No newline at end of file +object OperatorRemove : + OperatorBasic( + 2, + IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.ofType(DOUBLE)) + ) { + override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { + val it = iotas.iterator().withIndex() + val list = it.nextList(arity).toMutableList() + val index = it.nextInt(arity) + if (index < 0 || index >= list.size) return list.asActionResult + list.removeAt(index) + return list.asActionResult + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorReplace.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorReplace.kt index ca976369c2..3e85f6df6c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorReplace.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorReplace.kt @@ -1,7 +1,6 @@ package at.petrak.hexcasting.common.casting.arithmetic.operator.list import at.petrak.hexcasting.api.casting.SpellList -import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate @@ -12,12 +11,20 @@ import at.petrak.hexcasting.common.casting.arithmetic.operator.nextList import at.petrak.hexcasting.common.casting.arithmetic.operator.nextPositiveIntUnder import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.* -object OperatorReplace : OperatorBasic(3, IotaMultiPredicate.triple(IotaPredicate.ofType(LIST), IotaPredicate.ofType(DOUBLE), IotaPredicate.TRUE)) { - override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { - val it = iotas.iterator().withIndex() - val list = it.nextList(arity) - val index = it.nextPositiveIntUnder(list.size(), arity) - val iota = it.next().value - return list.modifyAt(index) { SpellList.LPair(iota, it.cdr) }.asActionResult - } -} \ No newline at end of file +object OperatorReplace : + OperatorBasic( + 3, + IotaMultiPredicate.triple( + IotaPredicate.ofType(LIST), + IotaPredicate.ofType(DOUBLE), + IotaPredicate.TRUE + ) + ) { + override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { + val it = iotas.iterator().withIndex() + val list = it.nextList(arity) + val index = it.nextPositiveIntUnder(list.size(), arity) + val iota = it.next().value + return list.modifyAt(index) { SpellList.LPair(iota, it.cdr) }.asActionResult + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorSlice.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorSlice.kt index d4e8c5f8ec..32fe8e0e4d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorSlice.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorSlice.kt @@ -1,9 +1,8 @@ package at.petrak.hexcasting.common.casting.arithmetic.operator.list +import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate -import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator -import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic import at.petrak.hexcasting.api.casting.asActionResult import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota @@ -13,15 +12,22 @@ import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.* import kotlin.math.max import kotlin.math.min -object OperatorSlice : OperatorBasic(3, IotaMultiPredicate.triple(IotaPredicate.ofType(LIST), IotaPredicate.ofType(DOUBLE), IotaPredicate.ofType(DOUBLE))) { - override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { - val it = iotas.iterator().withIndex() - val list = it.nextList(arity).toList() - val index0 = it.nextPositiveIntUnderInclusive(list.size, arity) - val index1 = it.nextPositiveIntUnderInclusive(list.size, arity) +object OperatorSlice : + OperatorBasic( + 3, + IotaMultiPredicate.triple( + IotaPredicate.ofType(LIST), + IotaPredicate.ofType(DOUBLE), + IotaPredicate.ofType(DOUBLE) + ) + ) { + override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { + val it = iotas.iterator().withIndex() + val list = it.nextList(arity).toList() + val index0 = it.nextPositiveIntUnderInclusive(list.size, arity) + val index1 = it.nextPositiveIntUnderInclusive(list.size, arity) - if (index0 == index1) - return emptyList<Iota>().asActionResult - return list.subList(min(index0, index1), max(index0, index1)).asActionResult - } -} \ No newline at end of file + if (index0 == index1) return emptyList<Iota>().asActionResult + return list.subList(min(index0, index1), max(index0, index1)).asActionResult + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorUnCons.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorUnCons.kt index 54f0de69c2..063a08264d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorUnCons.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorUnCons.kt @@ -1,6 +1,5 @@ package at.petrak.hexcasting.common.casting.arithmetic.operator.list -import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate @@ -12,11 +11,10 @@ import at.petrak.hexcasting.common.casting.arithmetic.operator.nextList import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.LIST object OperatorUnCons : OperatorBasic(1, IotaMultiPredicate.all(IotaPredicate.ofType(LIST))) { - override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { - val it = iotas.iterator().withIndex() - val list = it.nextList(arity) - if (list.nonEmpty) - return listOf(ListIota(list.cdr), list.car) - return listOf(ListIota(list), NullIota()) - } -} \ No newline at end of file + override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { + val it = iotas.iterator().withIndex() + val list = it.nextList(arity) + if (list.nonEmpty) return listOf(ListIota(list.cdr), list.car) + return listOf(ListIota(list), NullIota()) + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorUnappend.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorUnappend.kt index 6d60362b0d..6160b75730 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorUnappend.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorUnappend.kt @@ -1,6 +1,5 @@ package at.petrak.hexcasting.common.casting.arithmetic.operator.list -import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate @@ -12,10 +11,10 @@ import at.petrak.hexcasting.common.casting.arithmetic.operator.nextList import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.* object OperatorUnappend : OperatorBasic(1, IotaMultiPredicate.all(IotaPredicate.ofType(LIST))) { - override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { - val it = iotas.iterator().withIndex() - val list = it.nextList(arity).toMutableList() - val last = list.removeLastOrNull() ?: NullIota() - return listOf(ListIota(list), last) - } -} \ No newline at end of file + override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { + val it = iotas.iterator().withIndex() + val list = it.nextList(arity).toMutableList() + val last = list.removeLastOrNull() ?: NullIota() + return listOf(ListIota(list), last) + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorUnique.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorUnique.kt index b3cb19ec28..01e23f0ca8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorUnique.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/list/OperatorUnique.kt @@ -1,28 +1,27 @@ package at.petrak.hexcasting.common.casting.arithmetic.operator.list -import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate import at.petrak.hexcasting.api.casting.asActionResult import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota -import at.petrak.hexcasting.common.casting.arithmetic.operator.nextList import at.petrak.hexcasting.common.casting.actions.math.bit.OpToSet +import at.petrak.hexcasting.common.casting.arithmetic.operator.nextList import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.LIST object OperatorUnique : OperatorBasic(1, IotaMultiPredicate.all(IotaPredicate.ofType(LIST))) { - override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { - val it = iotas.iterator().withIndex() - val list = it.nextList(OpToSet.argc) - val out = mutableListOf<Iota>() + override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> { + val it = iotas.iterator().withIndex() + val list = it.nextList(OpToSet.argc) + val out = mutableListOf<Iota>() - for (subiota in list) { - if (out.none { Iota.tolerates(it, subiota) }) { - out.add(subiota) - } - } + for (subiota in list) { + if (out.none { Iota.tolerates(it, subiota) }) { + out.add(subiota) + } + } - return out.asActionResult - } -} \ No newline at end of file + return out.asActionResult + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/vec/OperatorPack.java b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/vec/OperatorPack.java index d30b8edcbc..ce935e7e60 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/vec/OperatorPack.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/vec/OperatorPack.java @@ -1,7 +1,5 @@ package at.petrak.hexcasting.common.casting.arithmetic.operator.vec; - -import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator; import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic; import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate; import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate; @@ -9,11 +7,10 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.Vec3Iota; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import java.util.List; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; -import java.util.List; - public class OperatorPack extends OperatorBasic { private OperatorPack() { super(3, IotaMultiPredicate.all(IotaPredicate.ofType(HexIotaTypes.DOUBLE))); @@ -22,12 +19,14 @@ private OperatorPack() { public static OperatorPack INSTANCE = new OperatorPack(); @Override - public @NotNull Iterable<Iota> apply(Iterable<? extends Iota> iotas, @NotNull CastingEnvironment env) { + public @NotNull Iterable<Iota> apply( + Iterable<? extends Iota> iotas, @NotNull CastingEnvironment env) { var it = iotas.iterator(); - return List.of(new Vec3Iota(new Vec3( - downcast(it.next(), HexIotaTypes.DOUBLE).getDouble(), - downcast(it.next(), HexIotaTypes.DOUBLE).getDouble(), - downcast(it.next(), HexIotaTypes.DOUBLE).getDouble() - ))); + return List.of( + new Vec3Iota( + new Vec3( + downcast(it.next(), HexIotaTypes.DOUBLE).getDouble(), + downcast(it.next(), HexIotaTypes.DOUBLE).getDouble(), + downcast(it.next(), HexIotaTypes.DOUBLE).getDouble()))); } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/vec/OperatorUnpack.java b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/vec/OperatorUnpack.java index adaeed6981..d4f44e367e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/vec/OperatorUnpack.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/vec/OperatorUnpack.java @@ -1,7 +1,7 @@ package at.petrak.hexcasting.common.casting.arithmetic.operator.vec; +import static at.petrak.hexcasting.common.lib.hex.HexIotaTypes.VEC3; -import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator; import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic; import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate; import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate; @@ -9,11 +9,8 @@ import at.petrak.hexcasting.api.casting.iota.DoubleIota; import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; -import org.jetbrains.annotations.NotNull; - import java.util.List; - -import static at.petrak.hexcasting.common.lib.hex.HexIotaTypes.VEC3; +import org.jetbrains.annotations.NotNull; public class OperatorUnpack extends OperatorBasic { private OperatorUnpack() { @@ -23,7 +20,8 @@ private OperatorUnpack() { public static OperatorUnpack INSTANCE = new OperatorUnpack(); @Override - public @NotNull Iterable<Iota> apply(Iterable<? extends Iota> iotas, @NotNull CastingEnvironment env) { + public @NotNull Iterable<Iota> apply( + Iterable<? extends Iota> iotas, @NotNull CastingEnvironment env) { var it = iotas.iterator(); var vec = downcast(it.next(), VEC3).getVec3(); return List.of(new DoubleIota(vec.x), new DoubleIota(vec.y), new DoubleIota(vec.z)); diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/vec/OperatorVec3Delegating.java b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/vec/OperatorVec3Delegating.java index 25e543dfb9..477febdd80 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/vec/OperatorVec3Delegating.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/operator/vec/OperatorVec3Delegating.java @@ -1,32 +1,31 @@ package at.petrak.hexcasting.common.casting.arithmetic.operator.vec; -import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator; +import static at.petrak.hexcasting.common.lib.hex.HexIotaTypes.DOUBLE; +import static at.petrak.hexcasting.common.lib.hex.HexIotaTypes.VEC3; + +import at.petrak.hexcasting.api.casting.arithmetic.IterPair; +import at.petrak.hexcasting.api.casting.arithmetic.TripleIterable; import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic; import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate; import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate; -import at.petrak.hexcasting.api.casting.arithmetic.IterPair; -import at.petrak.hexcasting.api.casting.arithmetic.TripleIterable; import at.petrak.hexcasting.api.casting.eval.CastingEnvironment; -import at.petrak.hexcasting.api.casting.mishaps.Mishap; -import at.petrak.hexcasting.api.casting.mishaps.MishapDivideByZero; -import at.petrak.hexcasting.common.casting.arithmetic.DoubleArithmetic; import at.petrak.hexcasting.api.casting.iota.DoubleIota; import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.Vec3Iota; import at.petrak.hexcasting.api.casting.math.HexPattern; -import net.minecraft.world.phys.Vec3; -import org.jetbrains.annotations.NotNull; - +import at.petrak.hexcasting.api.casting.mishaps.Mishap; +import at.petrak.hexcasting.api.casting.mishaps.MishapDivideByZero; +import at.petrak.hexcasting.common.casting.arithmetic.DoubleArithmetic; import java.util.List; import java.util.Objects; import java.util.function.BiFunction; - -import static at.petrak.hexcasting.common.lib.hex.HexIotaTypes.DOUBLE; -import static at.petrak.hexcasting.common.lib.hex.HexIotaTypes.VEC3; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; public class OperatorVec3Delegating extends OperatorBasic { private final BiFunction<Vec3, Vec3, Iota> op; private final OperatorBasic fb; + public OperatorVec3Delegating(BiFunction<Vec3, Vec3, Iota> core, HexPattern fallback) { super(2, IotaMultiPredicate.any(IotaPredicate.ofType(VEC3), IotaPredicate.ofType(DOUBLE))); op = core; @@ -34,7 +33,8 @@ public OperatorVec3Delegating(BiFunction<Vec3, Vec3, Iota> core, HexPattern fall } @Override - public @NotNull Iterable<Iota> apply(Iterable<? extends Iota> iotas, @NotNull CastingEnvironment env) throws Mishap { + public @NotNull Iterable<Iota> apply( + Iterable<? extends Iota> iotas, @NotNull CastingEnvironment env) throws Mishap { var it = iotas.iterator(); var left = it.next(); var right = it.next(); @@ -42,14 +42,22 @@ public OperatorVec3Delegating(BiFunction<Vec3, Vec3, Iota> core, HexPattern fall if (op != null && left instanceof Vec3Iota lh && right instanceof Vec3Iota rh) { return List.of(op.apply(lh.getVec3(), rh.getVec3())); } - var lh = left instanceof Vec3Iota l ? l.getVec3() : triplicate(downcast(left, DOUBLE).getDouble()); - var rh = right instanceof Vec3Iota r ? r.getVec3() : triplicate(downcast(right, DOUBLE).getDouble()); + var lh = + left instanceof Vec3Iota l ? l.getVec3() : triplicate(downcast(left, DOUBLE).getDouble()); + var rh = + right instanceof Vec3Iota r + ? r.getVec3() + : triplicate(downcast(right, DOUBLE).getDouble()); return new TripleIterable<>( fb.apply(new IterPair<>(new DoubleIota(lh.x()), new DoubleIota(rh.x())), env), fb.apply(new IterPair<>(new DoubleIota(lh.y()), new DoubleIota(rh.y())), env), fb.apply(new IterPair<>(new DoubleIota(lh.z()), new DoubleIota(rh.z())), env), - (x, y, z) -> new Vec3Iota(new Vec3(downcast(x, DOUBLE).getDouble(), downcast(y, DOUBLE).getDouble(), downcast(z, DOUBLE).getDouble())) - ); + (x, y, z) -> + new Vec3Iota( + new Vec3( + downcast(x, DOUBLE).getDouble(), + downcast(y, DOUBLE).getDouble(), + downcast(z, DOUBLE).getDouble()))); } catch (MishapDivideByZero e) { throw MishapDivideByZero.of(left, right, e.getSuffix()); } @@ -58,4 +66,4 @@ public OperatorVec3Delegating(BiFunction<Vec3, Vec3, Iota> core, HexPattern fall public static Vec3 triplicate(double in) { return new Vec3(in, in, in); } -} \ No newline at end of file +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/command/BrainsweepCommand.java b/Common/src/main/java/at/petrak/hexcasting/common/command/BrainsweepCommand.java index 26781d33ec..e1485c683c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/command/BrainsweepCommand.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/command/BrainsweepCommand.java @@ -10,28 +10,40 @@ import net.minecraft.world.entity.Mob; public class BrainsweepCommand { - public static void add(LiteralArgumentBuilder<CommandSourceStack> cmd) { - cmd.then(Commands.literal("brainsweep") - .requires(dp -> dp.hasPermission(Commands.LEVEL_ADMINS)) - .then(Commands.argument("target", EntityArgument.entity()).executes(ctx -> { - var target = EntityArgument.getEntity(ctx, "target"); - if (target instanceof Mob mob) { - if (IXplatAbstractions.INSTANCE.isBrainswept(mob)) { - ctx.getSource().sendFailure( - Component.translatable("command.hexcasting.brainsweep.fail.already", - mob.getDisplayName())); - return 0; - } - HexAPI.instance().brainsweep(mob); - ctx.getSource().sendSuccess( - () -> Component.translatable("command.hexcasting.brainsweep", mob.getDisplayName()), true); - return 1; - } else { - ctx.getSource().sendFailure( - Component.translatable("command.hexcasting.brainsweep.fail.badtype", - target.getDisplayName())); - return 0; - } - }))); - } + public static void add(LiteralArgumentBuilder<CommandSourceStack> cmd) { + cmd.then( + Commands.literal("brainsweep") + .requires(dp -> dp.hasPermission(Commands.LEVEL_ADMINS)) + .then( + Commands.argument("target", EntityArgument.entity()) + .executes( + ctx -> { + var target = EntityArgument.getEntity(ctx, "target"); + if (target instanceof Mob mob) { + if (IXplatAbstractions.INSTANCE.isBrainswept(mob)) { + ctx.getSource() + .sendFailure( + Component.translatable( + "command.hexcasting.brainsweep.fail.already", + mob.getDisplayName())); + return 0; + } + HexAPI.instance().brainsweep(mob); + ctx.getSource() + .sendSuccess( + () -> + Component.translatable( + "command.hexcasting.brainsweep", mob.getDisplayName()), + true); + return 1; + } else { + ctx.getSource() + .sendFailure( + Component.translatable( + "command.hexcasting.brainsweep.fail.badtype", + target.getDisplayName())); + return 0; + } + }))); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/command/ListPerWorldPatternsCommand.java b/Common/src/main/java/at/petrak/hexcasting/common/command/ListPerWorldPatternsCommand.java index f39e14d47f..7c434c5635 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/command/ListPerWorldPatternsCommand.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/command/ListPerWorldPatternsCommand.java @@ -11,6 +11,8 @@ import at.petrak.hexcasting.server.ScrungledPatternsSave; import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import java.util.Collection; +import java.util.List; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.arguments.EntityArgument; @@ -22,150 +24,167 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; -import java.util.Collection; -import java.util.List; - public class ListPerWorldPatternsCommand { - public static void add(LiteralArgumentBuilder<CommandSourceStack> cmd) { - cmd.then(Commands.literal("perWorldPatterns") - .requires(dp -> dp.hasPermission(Commands.LEVEL_GAMEMASTERS)) - .then(Commands.literal("list") - .executes(ctx -> list(ctx.getSource()))) - .then(Commands.literal("give") - .then(Commands.argument("patternName", PatternResLocArgument.id()) - .executes(ctx -> - giveOne(ctx.getSource(), - getDefaultTarget(ctx.getSource()), - ResourceLocationArgument.getId(ctx, "patternName"), - PatternResLocArgument.getPattern(ctx, "patternName"))) - .then(Commands.argument("targets", EntityArgument.players()) - .executes(ctx -> - giveOne(ctx.getSource(), - EntityArgument.getPlayers(ctx, "targets"), - ResourceLocationArgument.getId(ctx, "patternName"), - PatternResLocArgument.getPattern(ctx, "patternName")))))) - .then(Commands.literal("giveAll") - .executes(ctx -> - giveAll(ctx.getSource(), - getDefaultTarget(ctx.getSource()))) - .then(Commands.argument("targets", EntityArgument.players()) - .executes(ctx -> - giveAll(ctx.getSource(), - EntityArgument.getPlayers(ctx, "targets"))))) - ); - } - - private static Collection<ServerPlayer> getDefaultTarget(CommandSourceStack source) { - if (source.getEntity() instanceof ServerPlayer player) { - return List.of(player); - } - return List.of(); - } - - private static int list(CommandSourceStack source) { - - var keys = IXplatAbstractions.INSTANCE.getActionRegistry().registryKeySet(); - var listing = keys - .stream() - .sorted((a, b) -> compareResLoc(a.location(), b.location())) - .toList(); - - var ow = source.getLevel().getServer().overworld(); - source.sendSuccess(() -> Component.translatable("command.hexcasting.pats.listing"), false); - for (var key : listing) { - var pat = PatternRegistryManifest.getCanonicalStrokesPerWorld(key, ow); - - source.sendSuccess(() -> Component.literal(key.location().toString()) - .append(": ") - .append(new PatternIota(pat).display()), false); - } - - return keys.size(); - } - - private static int giveAll(CommandSourceStack source, Collection<ServerPlayer> targets) { - if (!targets.isEmpty()) { - var ow = source.getLevel().getServer().overworld(); - var save = ScrungledPatternsSave.open(ow); - Registry<ActionRegistryEntry> regi = IXplatAbstractions.INSTANCE.getActionRegistry(); - - int count = 0; - for (var entry : regi.entrySet()) { - var key = entry.getKey(); - if (HexUtils.isOfTag(regi, key, HexTags.Actions.PER_WORLD_PATTERN)) { - var found = save.lookupReverse(key); - var signature = found.getFirst(); - var startDir = found.getSecond().canonicalStartDir(); - var pat = HexPattern.fromAngles(signature, startDir); - - var tag = new CompoundTag(); - tag.putString(ItemScroll.TAG_OP_ID, key.location().toString()); - tag.put(ItemScroll.TAG_PATTERN, pat.serializeToNBT()); - - var stack = new ItemStack(HexItems.SCROLL_LARGE); - stack.setTag(tag); - - for (var player : targets) { - var stackEntity = player.drop(stack, false); - if (stackEntity != null) { - stackEntity.setNoPickUpDelay(); - stackEntity.setThrower(player.getUUID()); - } - - count++; - } - } - } - - int finalCount = count; - source.sendSuccess(() -> - Component.translatable("command.hexcasting.pats.all", - finalCount, - targets.size() == 1 ? targets.iterator().next().getDisplayName() : targets.size()), - true); - return count; - } else { - return 0; - } - } - - private static int giveOne(CommandSourceStack source, Collection<ServerPlayer> targets, - ResourceLocation patternName, HexPattern pat) { - if (!targets.isEmpty()) { - var tag = new CompoundTag(); - tag.putString(ItemScroll.TAG_OP_ID, patternName.toString()); - tag.put(ItemScroll.TAG_PATTERN, pat.serializeToNBT()); - - var stack = new ItemStack(HexItems.SCROLL_LARGE); - stack.setTag(tag); - - source.sendSuccess(() -> - Component.translatable( - "command.hexcasting.pats.specific.success", - stack.getDisplayName(), - patternName, - targets.size() == 1 ? targets.iterator().next().getDisplayName() : targets.size()), - true); - - for (var player : targets) { - var stackEntity = player.drop(stack, false); - if (stackEntity != null) { - stackEntity.setNoPickUpDelay(); - stackEntity.setThrower(player.getUUID()); - } - } - - return targets.size(); - } else { - return 0; - } - } - - private static int compareResLoc(ResourceLocation a, ResourceLocation b) { - var ns = a.getNamespace().compareTo(b.getNamespace()); - if (ns != 0) { - return ns; - } - return a.getPath().compareTo(b.getPath()); - } + public static void add(LiteralArgumentBuilder<CommandSourceStack> cmd) { + cmd.then( + Commands.literal("perWorldPatterns") + .requires(dp -> dp.hasPermission(Commands.LEVEL_GAMEMASTERS)) + .then(Commands.literal("list").executes(ctx -> list(ctx.getSource()))) + .then( + Commands.literal("give") + .then( + Commands.argument("patternName", PatternResLocArgument.id()) + .executes( + ctx -> + giveOne( + ctx.getSource(), + getDefaultTarget(ctx.getSource()), + ResourceLocationArgument.getId(ctx, "patternName"), + PatternResLocArgument.getPattern(ctx, "patternName"))) + .then( + Commands.argument("targets", EntityArgument.players()) + .executes( + ctx -> + giveOne( + ctx.getSource(), + EntityArgument.getPlayers(ctx, "targets"), + ResourceLocationArgument.getId(ctx, "patternName"), + PatternResLocArgument.getPattern( + ctx, "patternName")))))) + .then( + Commands.literal("giveAll") + .executes(ctx -> giveAll(ctx.getSource(), getDefaultTarget(ctx.getSource()))) + .then( + Commands.argument("targets", EntityArgument.players()) + .executes( + ctx -> + giveAll( + ctx.getSource(), + EntityArgument.getPlayers(ctx, "targets")))))); + } + + private static Collection<ServerPlayer> getDefaultTarget(CommandSourceStack source) { + if (source.getEntity() instanceof ServerPlayer player) { + return List.of(player); + } + return List.of(); + } + + private static int list(CommandSourceStack source) { + + var keys = IXplatAbstractions.INSTANCE.getActionRegistry().registryKeySet(); + var listing = + keys.stream().sorted((a, b) -> compareResLoc(a.location(), b.location())).toList(); + + var ow = source.getLevel().getServer().overworld(); + source.sendSuccess(() -> Component.translatable("command.hexcasting.pats.listing"), false); + for (var key : listing) { + var pat = PatternRegistryManifest.getCanonicalStrokesPerWorld(key, ow); + + source.sendSuccess( + () -> + Component.literal(key.location().toString()) + .append(": ") + .append(new PatternIota(pat).display()), + false); + } + + return keys.size(); + } + + private static int giveAll(CommandSourceStack source, Collection<ServerPlayer> targets) { + if (!targets.isEmpty()) { + var ow = source.getLevel().getServer().overworld(); + var save = ScrungledPatternsSave.open(ow); + Registry<ActionRegistryEntry> regi = IXplatAbstractions.INSTANCE.getActionRegistry(); + + int count = 0; + for (var entry : regi.entrySet()) { + var key = entry.getKey(); + if (HexUtils.isOfTag(regi, key, HexTags.Actions.PER_WORLD_PATTERN)) { + var found = save.lookupReverse(key); + var signature = found.getFirst(); + var startDir = found.getSecond().canonicalStartDir(); + var pat = HexPattern.fromAngles(signature, startDir); + + var tag = new CompoundTag(); + tag.putString(ItemScroll.TAG_OP_ID, key.location().toString()); + tag.put(ItemScroll.TAG_PATTERN, pat.serializeToNBT()); + + var stack = new ItemStack(HexItems.SCROLL_LARGE); + stack.setTag(tag); + + for (var player : targets) { + var stackEntity = player.drop(stack, false); + if (stackEntity != null) { + stackEntity.setNoPickUpDelay(); + stackEntity.setThrower(player.getUUID()); + } + + count++; + } + } + } + + int finalCount = count; + source.sendSuccess( + () -> + Component.translatable( + "command.hexcasting.pats.all", + finalCount, + targets.size() == 1 + ? targets.iterator().next().getDisplayName() + : targets.size()), + true); + return count; + } else { + return 0; + } + } + + private static int giveOne( + CommandSourceStack source, + Collection<ServerPlayer> targets, + ResourceLocation patternName, + HexPattern pat) { + if (!targets.isEmpty()) { + var tag = new CompoundTag(); + tag.putString(ItemScroll.TAG_OP_ID, patternName.toString()); + tag.put(ItemScroll.TAG_PATTERN, pat.serializeToNBT()); + + var stack = new ItemStack(HexItems.SCROLL_LARGE); + stack.setTag(tag); + + source.sendSuccess( + () -> + Component.translatable( + "command.hexcasting.pats.specific.success", + stack.getDisplayName(), + patternName, + targets.size() == 1 + ? targets.iterator().next().getDisplayName() + : targets.size()), + true); + + for (var player : targets) { + var stackEntity = player.drop(stack, false); + if (stackEntity != null) { + stackEntity.setNoPickUpDelay(); + stackEntity.setThrower(player.getUUID()); + } + } + + return targets.size(); + } else { + return 0; + } + } + + private static int compareResLoc(ResourceLocation a, ResourceLocation b) { + var ns = a.getNamespace().compareTo(b.getNamespace()); + if (ns != 0) { + return ns; + } + return a.getPath().compareTo(b.getPath()); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/command/PatternResLocArgument.java b/Common/src/main/java/at/petrak/hexcasting/common/command/PatternResLocArgument.java index 6403a422c9..99acdc7e4a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/command/PatternResLocArgument.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/command/PatternResLocArgument.java @@ -10,6 +10,8 @@ import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import java.util.ArrayList; +import java.util.concurrent.CompletableFuture; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.arguments.ResourceLocationArgument; @@ -17,41 +19,41 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; -import java.util.ArrayList; -import java.util.concurrent.CompletableFuture; - public class PatternResLocArgument extends ResourceLocationArgument { - private static final DynamicCommandExceptionType ERROR_UNKNOWN_PATTERN = new DynamicCommandExceptionType( - (errorer) -> - Component.translatable("hexcasting.pattern.unknown", errorer) - ); + private static final DynamicCommandExceptionType ERROR_UNKNOWN_PATTERN = + new DynamicCommandExceptionType( + (errorer) -> Component.translatable("hexcasting.pattern.unknown", errorer)); - public static PatternResLocArgument id() { - return new PatternResLocArgument(); - } + public static PatternResLocArgument id() { + return new PatternResLocArgument(); + } - @Override - public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) { - var suggestions = new ArrayList<String>(); - var registry = IXplatAbstractions.INSTANCE.getActionRegistry(); - for (var key : registry.registryKeySet()) { - if (HexUtils.isOfTag(registry, key, HexTags.Actions.PER_WORLD_PATTERN)) { - suggestions.add(key.location().toString()); - } - } + @Override + public <S> CompletableFuture<Suggestions> listSuggestions( + CommandContext<S> context, SuggestionsBuilder builder) { + var suggestions = new ArrayList<String>(); + var registry = IXplatAbstractions.INSTANCE.getActionRegistry(); + for (var key : registry.registryKeySet()) { + if (HexUtils.isOfTag(registry, key, HexTags.Actions.PER_WORLD_PATTERN)) { + suggestions.add(key.location().toString()); + } + } - return SharedSuggestionProvider.suggest(suggestions, builder); - } + return SharedSuggestionProvider.suggest(suggestions, builder); + } - public static HexPattern getPattern( - CommandContext<CommandSourceStack> ctx, String argumentName) throws CommandSyntaxException { - var targetId = ctx.getArgument(argumentName, ResourceLocation.class); - var targetKey = ResourceKey.create(IXplatAbstractions.INSTANCE.getActionRegistry().key(), targetId); - var foundPat = PatternRegistryManifest.getCanonicalStrokesPerWorld(targetKey, ctx.getSource().getServer().overworld()); - if (foundPat == null) { - throw ERROR_UNKNOWN_PATTERN.create(targetId); - } else { - return foundPat; - } - } + public static HexPattern getPattern(CommandContext<CommandSourceStack> ctx, String argumentName) + throws CommandSyntaxException { + var targetId = ctx.getArgument(argumentName, ResourceLocation.class); + var targetKey = + ResourceKey.create(IXplatAbstractions.INSTANCE.getActionRegistry().key(), targetId); + var foundPat = + PatternRegistryManifest.getCanonicalStrokesPerWorld( + targetKey, ctx.getSource().getServer().overworld()); + if (foundPat == null) { + throw ERROR_UNKNOWN_PATTERN.create(targetId); + } else { + return foundPat; + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/command/PatternTexturesCommand.java b/Common/src/main/java/at/petrak/hexcasting/common/command/PatternTexturesCommand.java index 868f02e2de..d997924c17 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/command/PatternTexturesCommand.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/command/PatternTexturesCommand.java @@ -6,24 +6,34 @@ import net.minecraft.commands.Commands; import net.minecraft.network.chat.Component; -public class PatternTexturesCommand -{ - public static void add(LiteralArgumentBuilder<CommandSourceStack> cmd) { - // TODO: do we want these in release ?? - cmd.then(Commands.literal("textureToggle") - .requires(dp -> dp.hasPermission(Commands.LEVEL_ADMINS)) - .executes(ctx -> { - PatternTextureManager.useTextures = !PatternTextureManager.useTextures; - String log = (PatternTextureManager.useTextures ? "Enabled" : "Disabled") + " pattern texture rendering. This is meant for debugging."; - ctx.getSource().sendSuccess(() -> Component.literal(log), true); - return 1; - })); - cmd.then(Commands.literal("textureRepaint") - .requires(dp -> dp.hasPermission(Commands.LEVEL_ADMINS)) - .executes(ctx -> { - PatternTextureManager.repaint(); - ctx.getSource().sendSuccess(() -> Component.literal("Repainting pattern textures. This is meant for debugging."), true); - return 1; - })); - } -} \ No newline at end of file +public class PatternTexturesCommand { + public static void add(LiteralArgumentBuilder<CommandSourceStack> cmd) { + // TODO: do we want these in release ?? + cmd.then( + Commands.literal("textureToggle") + .requires(dp -> dp.hasPermission(Commands.LEVEL_ADMINS)) + .executes( + ctx -> { + PatternTextureManager.useTextures = !PatternTextureManager.useTextures; + String log = + (PatternTextureManager.useTextures ? "Enabled" : "Disabled") + + " pattern texture rendering. This is meant for debugging."; + ctx.getSource().sendSuccess(() -> Component.literal(log), true); + return 1; + })); + cmd.then( + Commands.literal("textureRepaint") + .requires(dp -> dp.hasPermission(Commands.LEVEL_ADMINS)) + .executes( + ctx -> { + PatternTextureManager.repaint(); + ctx.getSource() + .sendSuccess( + () -> + Component.literal( + "Repainting pattern textures. This is meant for debugging."), + true); + return 1; + })); + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/command/RecalcPatternsCommand.java b/Common/src/main/java/at/petrak/hexcasting/common/command/RecalcPatternsCommand.java index 89fee33d84..9a49f20652 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/command/RecalcPatternsCommand.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/command/RecalcPatternsCommand.java @@ -7,18 +7,21 @@ import net.minecraft.network.chat.Component; public class RecalcPatternsCommand { - public static void add(LiteralArgumentBuilder<CommandSourceStack> cmd) { - cmd.then(Commands.literal("recalcPatterns") - .requires(dp -> dp.hasPermission(Commands.LEVEL_ADMINS)) - .executes(ctx -> { - var world = ctx.getSource().getServer().overworld(); - var ds = world.getDataStorage(); - ds.set(ScrungledPatternsSave.TAG_SAVED_DATA, - ScrungledPatternsSave.createFromScratch(world.getSeed())); + public static void add(LiteralArgumentBuilder<CommandSourceStack> cmd) { + cmd.then( + Commands.literal("recalcPatterns") + .requires(dp -> dp.hasPermission(Commands.LEVEL_ADMINS)) + .executes( + ctx -> { + var world = ctx.getSource().getServer().overworld(); + var ds = world.getDataStorage(); + ds.set( + ScrungledPatternsSave.TAG_SAVED_DATA, + ScrungledPatternsSave.createFromScratch(world.getSeed())); - ctx.getSource().sendSuccess(() -> - Component.translatable("command.hexcasting.recalc"), true); - return 1; - })); - } + ctx.getSource() + .sendSuccess(() -> Component.translatable("command.hexcasting.recalc"), true); + return 1; + })); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/entities/EntityWallScroll.java b/Common/src/main/java/at/petrak/hexcasting/common/entities/EntityWallScroll.java index 03d916c8f7..b98d605649 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/entities/EntityWallScroll.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/entities/EntityWallScroll.java @@ -34,168 +34,183 @@ import org.jetbrains.annotations.Nullable; public class EntityWallScroll extends HangingEntity { - private static final EntityDataAccessor<Boolean> SHOWS_STROKE_ORDER = SynchedEntityData.defineId( - EntityWallScroll.class, - EntityDataSerializers.BOOLEAN); - - public ItemStack scroll; - @Nullable - public HexPattern pattern; - public boolean isAncient; - public int blockSize; - - public EntityWallScroll(EntityType<? extends EntityWallScroll> type, Level world) { - super(type, world); - } - - public EntityWallScroll(Level world, BlockPos pos, Direction dir, ItemStack scroll, boolean showStrokeOrder, - int blockSize) { - super(HexEntities.WALL_SCROLL, world, pos); - this.setDirection(dir); - this.blockSize = blockSize; - - this.entityData.set(SHOWS_STROKE_ORDER, showStrokeOrder); - this.scroll = scroll; - this.recalculateDisplay(); - this.recalculateBoundingBox(); - } - - public void recalculateDisplay() { - CompoundTag patternTag = NBTHelper.getCompound(scroll, ItemScroll.TAG_PATTERN); - if (patternTag != null) { - this.pattern = HexPattern.fromNBT(patternTag); - this.isAncient = NBTHelper.hasString(scroll, ItemScroll.TAG_OP_ID); - } else { - this.pattern = null; - this.isAncient = false; - } - } - - @Override - protected void defineSynchedData() { - super.defineSynchedData(); - this.entityData.define(SHOWS_STROKE_ORDER, false); - } - - public boolean getShowsStrokeOrder() { - return this.entityData.get(SHOWS_STROKE_ORDER); - } - - public void setShowsStrokeOrder(boolean b) { - this.entityData.set(SHOWS_STROKE_ORDER, b); - } - - @Override - public int getWidth() { - return 16 * blockSize; - } - - @Override - public int getHeight() { - return 16 * blockSize; - } - - @Override - public void dropItem(@Nullable Entity pBrokenEntity) { - if (this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { - this.playSound(SoundEvents.PAINTING_BREAK, 1.0F, 1.0F); - if (pBrokenEntity instanceof Player player) { - if (player.getAbilities().instabuild) { - return; - } - } - - this.spawnAtLocation(this.scroll); - } - } - - @Override - public InteractionResult interactAt(Player pPlayer, Vec3 pVec, InteractionHand pHand) { - var handStack = pPlayer.getItemInHand(pHand); - if (handStack.is(HexItems.AMETHYST_DUST) && !this.getShowsStrokeOrder()) { - if (!pPlayer.getAbilities().instabuild) { - handStack.shrink(1); - } - this.setShowsStrokeOrder(true); - - pPlayer.level().playSound(pPlayer, this, HexSounds.SCROLL_DUST, SoundSource.PLAYERS, 1f, 1f); - - if (pPlayer.level() instanceof ServerLevel slevel) { - IXplatAbstractions.INSTANCE.sendPacketNear(this.position(), 32.0, slevel, - new MsgRecalcWallScrollDisplayS2C(this.getId(), true)); - } else { - // Beat the packet roundtrip to the punch to get a quicker visual - this.recalculateDisplay(); - } - return InteractionResult.SUCCESS; - } - return super.interactAt(pPlayer, pVec, pHand); - } - - @Override - public void playPlacementSound() { - this.playSound(SoundEvents.PAINTING_PLACE, 1.0F, 1.0F); - } - - @Override - public Packet<ClientGamePacketListener> getAddEntityPacket() { - return IXplatAbstractions.INSTANCE.toVanillaClientboundPacket( - new MsgNewWallScrollS2C(new ClientboundAddEntityPacket(this), - pos, direction, scroll, getShowsStrokeOrder(), blockSize)); - } - - public void readSpawnData(BlockPos pos, Direction dir, ItemStack scrollItem, - boolean showsStrokeOrder, int blockSize) { - this.pos = pos; - this.scroll = scrollItem; - this.blockSize = blockSize; - - this.setDirection(dir); - this.setShowsStrokeOrder(showsStrokeOrder); - - this.recalculateDisplay(); - this.recalculateBoundingBox(); - } - - @Override - public void addAdditionalSaveData(CompoundTag tag) { - tag.putByte("direction", (byte) this.direction.ordinal()); - tag.put("scroll", HexUtils.serializeToNBT(this.scroll)); - tag.putBoolean("showsStrokeOrder", this.getShowsStrokeOrder()); - tag.putInt("blockSize", this.blockSize); - super.addAdditionalSaveData(tag); - } - - @Override - public void readAdditionalSaveData(CompoundTag tag) { - this.direction = Direction.values()[tag.getByte("direction")]; - this.scroll = ItemStack.of(tag.getCompound("scroll")); - this.blockSize = tag.getInt("blockSize"); - - this.setDirection(this.direction); - this.setShowsStrokeOrder(tag.getBoolean("showsStrokeOrder")); - - this.recalculateDisplay(); - this.recalculateBoundingBox(); - - super.readAdditionalSaveData(tag); - } - - @Override - public void moveTo(double pX, double pY, double pZ, float pYaw, float pPitch) { - this.setPos(pX, pY, pZ); - } - - @Override - public void lerpTo(double pX, double pY, double pZ, float pYaw, float pPitch, int pPosRotationIncrements, - boolean pTeleport) { - BlockPos blockpos = this.pos.offset((int) (pX - this.getX()), (int) (pY - this.getY()), (int) (pZ - this.getZ())); - this.setPos(blockpos.getX(), blockpos.getY(), blockpos.getZ()); - } - - @Nullable - @Override - public ItemStack getPickResult() { - return this.scroll.copy(); - } + private static final EntityDataAccessor<Boolean> SHOWS_STROKE_ORDER = + SynchedEntityData.defineId(EntityWallScroll.class, EntityDataSerializers.BOOLEAN); + + public ItemStack scroll; + @Nullable public HexPattern pattern; + public boolean isAncient; + public int blockSize; + + public EntityWallScroll(EntityType<? extends EntityWallScroll> type, Level world) { + super(type, world); + } + + public EntityWallScroll( + Level world, + BlockPos pos, + Direction dir, + ItemStack scroll, + boolean showStrokeOrder, + int blockSize) { + super(HexEntities.WALL_SCROLL, world, pos); + this.setDirection(dir); + this.blockSize = blockSize; + + this.entityData.set(SHOWS_STROKE_ORDER, showStrokeOrder); + this.scroll = scroll; + this.recalculateDisplay(); + this.recalculateBoundingBox(); + } + + public void recalculateDisplay() { + CompoundTag patternTag = NBTHelper.getCompound(scroll, ItemScroll.TAG_PATTERN); + if (patternTag != null) { + this.pattern = HexPattern.fromNBT(patternTag); + this.isAncient = NBTHelper.hasString(scroll, ItemScroll.TAG_OP_ID); + } else { + this.pattern = null; + this.isAncient = false; + } + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(SHOWS_STROKE_ORDER, false); + } + + public boolean getShowsStrokeOrder() { + return this.entityData.get(SHOWS_STROKE_ORDER); + } + + public void setShowsStrokeOrder(boolean b) { + this.entityData.set(SHOWS_STROKE_ORDER, b); + } + + @Override + public int getWidth() { + return 16 * blockSize; + } + + @Override + public int getHeight() { + return 16 * blockSize; + } + + @Override + public void dropItem(@Nullable Entity pBrokenEntity) { + if (this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { + this.playSound(SoundEvents.PAINTING_BREAK, 1.0F, 1.0F); + if (pBrokenEntity instanceof Player player) { + if (player.getAbilities().instabuild) { + return; + } + } + + this.spawnAtLocation(this.scroll); + } + } + + @Override + public InteractionResult interactAt(Player pPlayer, Vec3 pVec, InteractionHand pHand) { + var handStack = pPlayer.getItemInHand(pHand); + if (handStack.is(HexItems.AMETHYST_DUST) && !this.getShowsStrokeOrder()) { + if (!pPlayer.getAbilities().instabuild) { + handStack.shrink(1); + } + this.setShowsStrokeOrder(true); + + pPlayer.level().playSound(pPlayer, this, HexSounds.SCROLL_DUST, SoundSource.PLAYERS, 1f, 1f); + + if (pPlayer.level() instanceof ServerLevel slevel) { + IXplatAbstractions.INSTANCE.sendPacketNear( + this.position(), 32.0, slevel, new MsgRecalcWallScrollDisplayS2C(this.getId(), true)); + } else { + // Beat the packet roundtrip to the punch to get a quicker visual + this.recalculateDisplay(); + } + return InteractionResult.SUCCESS; + } + return super.interactAt(pPlayer, pVec, pHand); + } + + @Override + public void playPlacementSound() { + this.playSound(SoundEvents.PAINTING_PLACE, 1.0F, 1.0F); + } + + @Override + public Packet<ClientGamePacketListener> getAddEntityPacket() { + return IXplatAbstractions.INSTANCE.toVanillaClientboundPacket( + new MsgNewWallScrollS2C( + new ClientboundAddEntityPacket(this), + pos, + direction, + scroll, + getShowsStrokeOrder(), + blockSize)); + } + + public void readSpawnData( + BlockPos pos, Direction dir, ItemStack scrollItem, boolean showsStrokeOrder, int blockSize) { + this.pos = pos; + this.scroll = scrollItem; + this.blockSize = blockSize; + + this.setDirection(dir); + this.setShowsStrokeOrder(showsStrokeOrder); + + this.recalculateDisplay(); + this.recalculateBoundingBox(); + } + + @Override + public void addAdditionalSaveData(CompoundTag tag) { + tag.putByte("direction", (byte) this.direction.ordinal()); + tag.put("scroll", HexUtils.serializeToNBT(this.scroll)); + tag.putBoolean("showsStrokeOrder", this.getShowsStrokeOrder()); + tag.putInt("blockSize", this.blockSize); + super.addAdditionalSaveData(tag); + } + + @Override + public void readAdditionalSaveData(CompoundTag tag) { + this.direction = Direction.values()[tag.getByte("direction")]; + this.scroll = ItemStack.of(tag.getCompound("scroll")); + this.blockSize = tag.getInt("blockSize"); + + this.setDirection(this.direction); + this.setShowsStrokeOrder(tag.getBoolean("showsStrokeOrder")); + + this.recalculateDisplay(); + this.recalculateBoundingBox(); + + super.readAdditionalSaveData(tag); + } + + @Override + public void moveTo(double pX, double pY, double pZ, float pYaw, float pPitch) { + this.setPos(pX, pY, pZ); + } + + @Override + public void lerpTo( + double pX, + double pY, + double pZ, + float pYaw, + float pPitch, + int pPosRotationIncrements, + boolean pTeleport) { + BlockPos blockpos = + this.pos.offset( + (int) (pX - this.getX()), (int) (pY - this.getY()), (int) (pZ - this.getZ())); + this.setPos(blockpos.getX(), blockpos.getY(), blockpos.getZ()); + } + + @Nullable @Override + public ItemStack getPickResult() { + return this.scroll.copy(); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/entities/HexEntities.java b/Common/src/main/java/at/petrak/hexcasting/common/entities/HexEntities.java index 435062889d..4c6682bc3c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/entities/HexEntities.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/entities/HexEntities.java @@ -1,36 +1,39 @@ package at.petrak.hexcasting.common.entities; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.HexAPI; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.BiConsumer; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.MobCategory; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.function.BiConsumer; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class HexEntities { - public static void registerEntities(BiConsumer<EntityType<?>, ResourceLocation> r) { - for (var e : ENTITIES.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } + public static void registerEntities(BiConsumer<EntityType<?>, ResourceLocation> r) { + for (var e : ENTITIES.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } - private static final Map<ResourceLocation, EntityType<?>> ENTITIES = new LinkedHashMap<>(); + private static final Map<ResourceLocation, EntityType<?>> ENTITIES = new LinkedHashMap<>(); - public static final EntityType<EntityWallScroll> WALL_SCROLL = register("wall_scroll", - EntityType.Builder.<EntityWallScroll>of(EntityWallScroll::new, MobCategory.MISC) - .sized(0.5f, 0.5f).clientTrackingRange(10).updateInterval(Integer.MAX_VALUE) - .build(HexAPI.MOD_ID + ":wall_scroll")); + public static final EntityType<EntityWallScroll> WALL_SCROLL = + register( + "wall_scroll", + EntityType.Builder.<EntityWallScroll>of(EntityWallScroll::new, MobCategory.MISC) + .sized(0.5f, 0.5f) + .clientTrackingRange(10) + .updateInterval(Integer.MAX_VALUE) + .build(HexAPI.MOD_ID + ":wall_scroll")); - private static <T extends Entity> EntityType<T> register(String id, EntityType<T> type) { - var old = ENTITIES.put(modLoc(id), type); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + id); - } - return type; - } + private static <T extends Entity> EntityType<T> register(String id, EntityType<T> type) { + var old = ENTITIES.put(modLoc(id), type); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + id); + } + return type; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/impl/HexAPIImpl.java b/Common/src/main/java/at/petrak/hexcasting/common/impl/HexAPIImpl.java index 0ff996b907..f7f8bafd2b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/impl/HexAPIImpl.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/impl/HexAPIImpl.java @@ -5,12 +5,14 @@ import at.petrak.hexcasting.api.pigment.FrozenPigment; import at.petrak.hexcasting.api.player.Sentinel; import at.petrak.hexcasting.xplat.IXplatAbstractions; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.function.Consumer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ArmorItem; @@ -21,128 +23,124 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.function.Consumer; - public class HexAPIImpl implements HexAPI { - private static final ConcurrentMap<EntityType<?>, EntityVelocityGetter<?>> SPECIAL_VELOCITIES - = new ConcurrentHashMap<>(); - private static final ConcurrentMap<EntityType<?>, Consumer<?>> SPECIAL_BRAINSWEEPS - = new ConcurrentHashMap<>(); - - public <T extends Entity> void registerSpecialVelocityGetter(EntityType<T> key, - EntityVelocityGetter<T> getter) { - if (SPECIAL_VELOCITIES.containsKey(key)) { - HexAPI.LOGGER.warn("A special velocity getter was already registered to {}, clobbering it!", - key.toString()); - } - SPECIAL_VELOCITIES.put(key, getter); - } - - @Override - public Vec3 getEntityVelocitySpecial(Entity entity) { - EntityType<?> type = entity.getType(); - if (SPECIAL_VELOCITIES.containsKey(type)) { - var velGetter = SPECIAL_VELOCITIES.get(type); - var erasedGetter = (EntityVelocityGetter) velGetter; - return erasedGetter.getVelocity(entity); - } - return entity.getDeltaMovement(); - } - - //region brainsweeping - - @Override - public <T extends Mob> void registerCustomBrainsweepingBehavior(EntityType<T> key, Consumer<T> hook) { - if (SPECIAL_BRAINSWEEPS.containsKey(key)) { - HexAPI.LOGGER.warn("A special brainsweep hook was already registered to {}, clobbering it!", - key.toString()); - } - SPECIAL_BRAINSWEEPS.put(key, hook); - } - - @Override - public <T extends Mob> Consumer<T> getBrainsweepBehavior(EntityType<T> mobType) { - var behavior = SPECIAL_BRAINSWEEPS.getOrDefault(mobType, this.defaultBrainsweepingBehavior()); - return (Consumer<T>) behavior; - } - - @Override - public Consumer<Mob> defaultBrainsweepingBehavior() { - return mob -> { - mob.removeFreeWill(); - - // TODO: do we add this? -// if (mob instanceof InventoryCarrier inv) { -// inv.getInventory().removeAllItems().forEach(mob::spawnAtLocation); -// } - }; - } - - //endregion - @Override - public @Nullable Sentinel getSentinel(ServerPlayer player) { - return IXplatAbstractions.INSTANCE.getSentinel(player); - } - - @Override - public @Nullable ADMediaHolder findMediaHolder(ItemStack stack) { - return IXplatAbstractions.INSTANCE.findMediaHolder(stack); - } - - @Override - public FrozenPigment getColorizer(Player player) { - return IXplatAbstractions.INSTANCE.getPigment(player); - } - - ArmorMaterial ARMOR_MATERIAL = new ArmorMaterial() { - - @Override - public int getDurabilityForType(ArmorItem.Type type) { - return 0; - } - - @Override - public int getDefenseForType(ArmorItem.Type type) { - return 0; - } - - @Override - public int getEnchantmentValue() { - return 0; - } - - @NotNull - @Override - public SoundEvent getEquipSound() { - return SoundEvents.ARMOR_EQUIP_LEATHER; - } - - @NotNull - @Override - public Ingredient getRepairIngredient() { - return Ingredient.EMPTY; - } - - @Override - public String getName() { - return "robes"; - } - - @Override - public float getToughness() { - return 0; - } - - @Override - public float getKnockbackResistance() { - return 0; - } - }; - - @Override - public ArmorMaterial robesMaterial() { - return ARMOR_MATERIAL; - } + private static final ConcurrentMap<EntityType<?>, EntityVelocityGetter<?>> SPECIAL_VELOCITIES = + new ConcurrentHashMap<>(); + private static final ConcurrentMap<EntityType<?>, Consumer<?>> SPECIAL_BRAINSWEEPS = + new ConcurrentHashMap<>(); + + public <T extends Entity> void registerSpecialVelocityGetter( + EntityType<T> key, EntityVelocityGetter<T> getter) { + if (SPECIAL_VELOCITIES.containsKey(key)) { + HexAPI.LOGGER.warn( + "A special velocity getter was already registered to {}, clobbering it!", key.toString()); + } + SPECIAL_VELOCITIES.put(key, getter); + } + + @Override + public Vec3 getEntityVelocitySpecial(Entity entity) { + EntityType<?> type = entity.getType(); + if (SPECIAL_VELOCITIES.containsKey(type)) { + var velGetter = SPECIAL_VELOCITIES.get(type); + var erasedGetter = (EntityVelocityGetter) velGetter; + return erasedGetter.getVelocity(entity); + } + return entity.getDeltaMovement(); + } + + // region brainsweeping + + @Override + public <T extends Mob> void registerCustomBrainsweepingBehavior( + EntityType<T> key, Consumer<T> hook) { + if (SPECIAL_BRAINSWEEPS.containsKey(key)) { + HexAPI.LOGGER.warn( + "A special brainsweep hook was already registered to {}, clobbering it!", key.toString()); + } + SPECIAL_BRAINSWEEPS.put(key, hook); + } + + @Override + public <T extends Mob> Consumer<T> getBrainsweepBehavior(EntityType<T> mobType) { + var behavior = SPECIAL_BRAINSWEEPS.getOrDefault(mobType, this.defaultBrainsweepingBehavior()); + return (Consumer<T>) behavior; + } + + @Override + public Consumer<Mob> defaultBrainsweepingBehavior() { + return mob -> { + mob.removeFreeWill(); + + // TODO: do we add this? + // if (mob instanceof InventoryCarrier inv) { + // inv.getInventory().removeAllItems().forEach(mob::spawnAtLocation); + // } + }; + } + + // endregion + @Override + public @Nullable Sentinel getSentinel(ServerPlayer player) { + return IXplatAbstractions.INSTANCE.getSentinel(player); + } + + @Override + public @Nullable ADMediaHolder findMediaHolder(ItemStack stack) { + return IXplatAbstractions.INSTANCE.findMediaHolder(stack); + } + + @Override + public FrozenPigment getColorizer(Player player) { + return IXplatAbstractions.INSTANCE.getPigment(player); + } + + ArmorMaterial ARMOR_MATERIAL = + new ArmorMaterial() { + + @Override + public int getDurabilityForType(ArmorItem.Type type) { + return 0; + } + + @Override + public int getDefenseForType(ArmorItem.Type type) { + return 0; + } + + @Override + public int getEnchantmentValue() { + return 0; + } + + @NotNull @Override + public SoundEvent getEquipSound() { + return SoundEvents.ARMOR_EQUIP_LEATHER; + } + + @NotNull @Override + public Ingredient getRepairIngredient() { + return Ingredient.EMPTY; + } + + @Override + public String getName() { + return "robes"; + } + + @Override + public float getToughness() { + return 0; + } + + @Override + public float getKnockbackResistance() { + return 0; + } + }; + + @Override + public ArmorMaterial robesMaterial() { + return ARMOR_MATERIAL; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/HexBaubleItem.java b/Common/src/main/java/at/petrak/hexcasting/common/items/HexBaubleItem.java index ed208b1b64..ea39a7ba32 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/HexBaubleItem.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/HexBaubleItem.java @@ -10,5 +10,5 @@ * I feel like botnia probably does it this way becase it's older than xplat curios */ public interface HexBaubleItem { - Multimap<Attribute, AttributeModifier> getHexBaubleAttrs(ItemStack stack); + Multimap<Attribute, AttributeModifier> getHexBaubleAttrs(ItemStack stack); } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/ItemJewelerHammer.java b/Common/src/main/java/at/petrak/hexcasting/common/items/ItemJewelerHammer.java index d5b059f5f7..385c6df628 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/ItemJewelerHammer.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/ItemJewelerHammer.java @@ -10,12 +10,13 @@ import net.minecraft.world.level.block.state.BlockState; public class ItemJewelerHammer extends PickaxeItem { - public ItemJewelerHammer(Tier tier, int damageMod, float attackSpeedMod, Properties props) { - super(tier, damageMod, attackSpeedMod, props); - } + public ItemJewelerHammer(Tier tier, int damageMod, float attackSpeedMod, Properties props) { + super(tier, damageMod, attackSpeedMod, props); + } - public static boolean shouldFailToBreak(Player player, BlockState state, BlockPos pos) { - ItemStack stack = player.getMainHandItem(); - return stack.is(HexItems.JEWELER_HAMMER) && Block.isShapeFullBlock(state.getShape(player.level(), pos)); - } + public static boolean shouldFailToBreak(Player player, BlockState state, BlockPos pos) { + ItemStack stack = player.getMainHandItem(); + return stack.is(HexItems.JEWELER_HAMMER) + && Block.isShapeFullBlock(state.getShape(player.level(), pos)); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/ItemLens.java b/Common/src/main/java/at/petrak/hexcasting/common/items/ItemLens.java index 4b77873f29..dc6b1aa806 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/ItemLens.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/ItemLens.java @@ -4,6 +4,7 @@ import at.petrak.hexcasting.common.lib.HexAttributes; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; +import java.util.UUID; import net.minecraft.core.BlockSource; import net.minecraft.core.dispenser.OptionalDispenseItemBehavior; import net.minecraft.world.entity.EquipmentSlot; @@ -12,65 +13,72 @@ import net.minecraft.world.item.ArmorItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -//import net.minecraft.world.item.Wearable; +// import net.minecraft.world.item.Wearable; import net.minecraft.world.level.block.DispenserBlock; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.UUID; - public class ItemLens extends Item implements HexBaubleItem { // Wearable, - // The 0.1 is *additive* + // The 0.1 is *additive* - public static final AttributeModifier GRID_ZOOM = new AttributeModifier( - UUID.fromString("59d739b8-d419-45f7-a4ea-0efee0e3adf5"), - "Scrying Lens Zoom", 0.33, AttributeModifier.Operation.MULTIPLY_BASE); + public static final AttributeModifier GRID_ZOOM = + new AttributeModifier( + UUID.fromString("59d739b8-d419-45f7-a4ea-0efee0e3adf5"), + "Scrying Lens Zoom", + 0.33, + AttributeModifier.Operation.MULTIPLY_BASE); - public static final AttributeModifier SCRY_SIGHT = new AttributeModifier( - UUID.fromString("e2e6e5d4-f978-4c11-8fdc-82a5af83385c"), - "Scrying Lens Sight", 1.0, AttributeModifier.Operation.ADDITION); + public static final AttributeModifier SCRY_SIGHT = + new AttributeModifier( + UUID.fromString("e2e6e5d4-f978-4c11-8fdc-82a5af83385c"), + "Scrying Lens Sight", + 1.0, + AttributeModifier.Operation.ADDITION); - public ItemLens(Properties pProperties) { - super(pProperties); - DispenserBlock.registerBehavior(this, new OptionalDispenseItemBehavior() { - protected @NotNull - ItemStack execute(@NotNull BlockSource world, @NotNull ItemStack stack) { - this.setSuccess(ArmorItem.dispenseArmor(world, stack)); - return stack; - } - }); - } + public ItemLens(Properties pProperties) { + super(pProperties); + DispenserBlock.registerBehavior( + this, + new OptionalDispenseItemBehavior() { + protected @NotNull ItemStack execute( + @NotNull BlockSource world, @NotNull ItemStack stack) { + this.setSuccess(ArmorItem.dispenseArmor(world, stack)); + return stack; + } + }); + } - @Override - public Multimap<Attribute, AttributeModifier> getDefaultAttributeModifiers(EquipmentSlot slot) { - var out = HashMultimap.create(super.getDefaultAttributeModifiers(slot)); - if (slot == EquipmentSlot.HEAD || slot == EquipmentSlot.MAINHAND || slot == EquipmentSlot.OFFHAND) { - out.put(HexAttributes.GRID_ZOOM, GRID_ZOOM); - out.put(HexAttributes.SCRY_SIGHT, SCRY_SIGHT); - } - return out; - } + @Override + public Multimap<Attribute, AttributeModifier> getDefaultAttributeModifiers(EquipmentSlot slot) { + var out = HashMultimap.create(super.getDefaultAttributeModifiers(slot)); + if (slot == EquipmentSlot.HEAD + || slot == EquipmentSlot.MAINHAND + || slot == EquipmentSlot.OFFHAND) { + out.put(HexAttributes.GRID_ZOOM, GRID_ZOOM); + out.put(HexAttributes.SCRY_SIGHT, SCRY_SIGHT); + } + return out; + } - @Override - public Multimap<Attribute, AttributeModifier> getHexBaubleAttrs(ItemStack stack) { - HashMultimap<Attribute, AttributeModifier> out = HashMultimap.create(); - out.put(HexAttributes.GRID_ZOOM, GRID_ZOOM); - out.put(HexAttributes.SCRY_SIGHT, SCRY_SIGHT); - return out; - } + @Override + public Multimap<Attribute, AttributeModifier> getHexBaubleAttrs(ItemStack stack) { + HashMultimap<Attribute, AttributeModifier> out = HashMultimap.create(); + out.put(HexAttributes.GRID_ZOOM, GRID_ZOOM); + out.put(HexAttributes.SCRY_SIGHT, SCRY_SIGHT); + return out; + } - // In fabric impled with extension property? - @Nullable - @SoftImplement("forge") - public EquipmentSlot getEquipmentSlot(ItemStack stack) { - return EquipmentSlot.HEAD; - } + // In fabric impled with extension property? + @Nullable @SoftImplement("forge") + public EquipmentSlot getEquipmentSlot(ItemStack stack) { + return EquipmentSlot.HEAD; + } -// @Nullable -// @Override -// public SoundEvent getEquipSound() { -// return SoundEvents.AMETHYST_BLOCK_CHIME; -// } + // @Nullable + // @Override + // public SoundEvent getEquipSound() { + // return SoundEvents.AMETHYST_BLOCK_CHIME; + // } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/ItemLoreFragment.java b/Common/src/main/java/at/petrak/hexcasting/common/items/ItemLoreFragment.java index 3d2f347bee..e11d44809d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/ItemLoreFragment.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/ItemLoreFragment.java @@ -1,6 +1,11 @@ package at.petrak.hexcasting.common.items; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.common.lib.HexSounds; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import net.minecraft.advancements.Advancement; import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.network.chat.Component; @@ -15,69 +20,74 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class ItemLoreFragment extends Item { - public static final List<ResourceLocation> NAMES = List.of(new ResourceLocation[]{ - modLoc("lore/cardamom1"), - modLoc("lore/cardamom2"), - modLoc("lore/cardamom3"), - modLoc("lore/cardamom4"), - modLoc("lore/cardamom5"), - modLoc("lore/experiment1"), - modLoc("lore/experiment2"), - modLoc("lore/inventory"), - }); + public static final List<ResourceLocation> NAMES = + List.of( + new ResourceLocation[] { + modLoc("lore/cardamom1"), + modLoc("lore/cardamom2"), + modLoc("lore/cardamom3"), + modLoc("lore/cardamom4"), + modLoc("lore/cardamom5"), + modLoc("lore/experiment1"), + modLoc("lore/experiment2"), + modLoc("lore/inventory"), + }); - public static final String CRITEREON_KEY = "grant"; + public static final String CRITEREON_KEY = "grant"; - public ItemLoreFragment(Properties properties) { - super(properties); - } + public ItemLoreFragment(Properties properties) { + super(properties); + } - @Override - public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand usedHand) { - player.playSound(HexSounds.READ_LORE_FRAGMENT, 1f, 1f); + @Override + public InteractionResultHolder<ItemStack> use( + Level level, Player player, InteractionHand usedHand) { + player.playSound(HexSounds.READ_LORE_FRAGMENT, 1f, 1f); - var handStack = player.getItemInHand(usedHand); - if (!(player instanceof ServerPlayer splayer)) { - handStack.shrink(1); - return InteractionResultHolder.success(handStack); - } + var handStack = player.getItemInHand(usedHand); + if (!(player instanceof ServerPlayer splayer)) { + handStack.shrink(1); + return InteractionResultHolder.success(handStack); + } - Advancement unfoundLore = null; - var shuffled = new ArrayList<>(NAMES); - Collections.shuffle(shuffled); - for (var advID : shuffled) { - var adv = splayer.server.getAdvancements().getAdvancement(advID); - if (adv == null) { - continue; // uh oh - } + Advancement unfoundLore = null; + var shuffled = new ArrayList<>(NAMES); + Collections.shuffle(shuffled); + for (var advID : shuffled) { + var adv = splayer.server.getAdvancements().getAdvancement(advID); + if (adv == null) { + continue; // uh oh + } - if (!splayer.getAdvancements().getOrStartProgress(adv).isDone()) { - unfoundLore = adv; - break; - } - } + if (!splayer.getAdvancements().getOrStartProgress(adv).isDone()) { + unfoundLore = adv; + break; + } + } - if (unfoundLore == null) { - splayer.displayClientMessage(Component.translatable("item.hexcasting.lore_fragment.all"), true); - splayer.giveExperiencePoints(20); - level.playSound(null, player.position().x, player.position().y, player.position().z, - HexSounds.READ_LORE_FRAGMENT, SoundSource.PLAYERS, 1f, 1f); - } else { - // et voila! - splayer.getAdvancements().award(unfoundLore, CRITEREON_KEY); - } + if (unfoundLore == null) { + splayer.displayClientMessage( + Component.translatable("item.hexcasting.lore_fragment.all"), true); + splayer.giveExperiencePoints(20); + level.playSound( + null, + player.position().x, + player.position().y, + player.position().z, + HexSounds.READ_LORE_FRAGMENT, + SoundSource.PLAYERS, + 1f, + 1f); + } else { + // et voila! + splayer.getAdvancements().award(unfoundLore, CRITEREON_KEY); + } - CriteriaTriggers.CONSUME_ITEM.trigger(splayer, handStack); - splayer.awardStat(Stats.ITEM_USED.get(this)); - handStack.shrink(1); + CriteriaTriggers.CONSUME_ITEM.trigger(splayer, handStack); + splayer.awardStat(Stats.ITEM_USED.get(this)); + handStack.shrink(1); - return InteractionResultHolder.success(handStack); - } + return InteractionResultHolder.success(handStack); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/ItemStaff.java b/Common/src/main/java/at/petrak/hexcasting/common/items/ItemStaff.java index c571aadf58..c5d019cfa7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/ItemStaff.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/ItemStaff.java @@ -16,40 +16,41 @@ import net.minecraft.world.level.Level; public class ItemStaff extends Item { - // 0 = normal. 1 = old. 2 = cherry preview - public static final ResourceLocation FUNNY_LEVEL_PREDICATE = new ResourceLocation(HexAPI.MOD_ID, "funny_level"); - - public ItemStaff(Properties pProperties) { - super(pProperties); - } - - @Override - public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) { - if (player.isShiftKeyDown()) { - if (world.isClientSide()) { - player.playSound(HexSounds.STAFF_RESET, 1f, 1f); - } else if (player instanceof ServerPlayer serverPlayer) { - IXplatAbstractions.INSTANCE.clearCastingData(serverPlayer); - var packet = new MsgClearSpiralPatternsS2C(player.getUUID()); - IXplatAbstractions.INSTANCE.sendPacketToPlayer(serverPlayer, packet); - IXplatAbstractions.INSTANCE.sendPacketTracking(serverPlayer, packet); - } - } - - if (!world.isClientSide() && player instanceof ServerPlayer serverPlayer) { - var harness = IXplatAbstractions.INSTANCE.getStaffcastVM(serverPlayer, hand); - var patterns = IXplatAbstractions.INSTANCE.getPatternsSavedInUi(serverPlayer); - var descs = harness.generateDescs(); - - IXplatAbstractions.INSTANCE.sendPacketToPlayer(serverPlayer, - new MsgOpenSpellGuiS2C(hand, patterns, descs.getFirst(), descs.getSecond(), - 0)); // TODO: Fix! - } - - player.awardStat(Stats.ITEM_USED.get(this)); -// player.gameEvent(GameEvent.ITEM_INTERACT_START); - - return InteractionResultHolder.success(player.getItemInHand(hand)); - } - + // 0 = normal. 1 = old. 2 = cherry preview + public static final ResourceLocation FUNNY_LEVEL_PREDICATE = + new ResourceLocation(HexAPI.MOD_ID, "funny_level"); + + public ItemStaff(Properties pProperties) { + super(pProperties); + } + + @Override + public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) { + if (player.isShiftKeyDown()) { + if (world.isClientSide()) { + player.playSound(HexSounds.STAFF_RESET, 1f, 1f); + } else if (player instanceof ServerPlayer serverPlayer) { + IXplatAbstractions.INSTANCE.clearCastingData(serverPlayer); + var packet = new MsgClearSpiralPatternsS2C(player.getUUID()); + IXplatAbstractions.INSTANCE.sendPacketToPlayer(serverPlayer, packet); + IXplatAbstractions.INSTANCE.sendPacketTracking(serverPlayer, packet); + } + } + + if (!world.isClientSide() && player instanceof ServerPlayer serverPlayer) { + var harness = IXplatAbstractions.INSTANCE.getStaffcastVM(serverPlayer, hand); + var patterns = IXplatAbstractions.INSTANCE.getPatternsSavedInUi(serverPlayer); + var descs = harness.generateDescs(); + + IXplatAbstractions.INSTANCE.sendPacketToPlayer( + serverPlayer, + new MsgOpenSpellGuiS2C( + hand, patterns, descs.getFirst(), descs.getSecond(), 0)); // TODO: Fix! + } + + player.awardStat(Stats.ITEM_USED.get(this)); + // player.gameEvent(GameEvent.ITEM_INTERACT_START); + + return InteractionResultHolder.success(player.getItemInHand(hand)); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/armor/ItemRobes.java b/Common/src/main/java/at/petrak/hexcasting/common/items/armor/ItemRobes.java index 3ec73cbdc6..77c1ce280d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/armor/ItemRobes.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/armor/ItemRobes.java @@ -1,19 +1,14 @@ package at.petrak.hexcasting.common.items.armor; import at.petrak.hexcasting.api.HexAPI; -import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.item.ArmorItem; -/** - * To get the armor model in; - * On forge: cursed self-mixin - * On fabric: hook in ClientInit - */ +/** To get the armor model in; On forge: cursed self-mixin On fabric: hook in ClientInit */ public class ItemRobes extends ArmorItem { - public final ArmorItem.Type type; + public final ArmorItem.Type type; - public ItemRobes(ArmorItem.Type type, Properties properties) { - super(HexAPI.instance().robesMaterial(), type, properties); - this.type = type; - } + public ItemRobes(ArmorItem.Type type, Properties properties) { + super(HexAPI.instance().robesMaterial(), type, properties); + this.type = type; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/DebugUnlockerHolder.java b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/DebugUnlockerHolder.java index 045a6eeb76..0b19325bc3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/DebugUnlockerHolder.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/DebugUnlockerHolder.java @@ -4,52 +4,54 @@ import net.minecraft.world.item.ItemStack; public record DebugUnlockerHolder(ItemStack creativeUnlocker) implements ADMediaHolder { - @Override - public long getMedia() { - return Integer.MAX_VALUE; - } - - @Override - public long getMaxMedia() { - return Integer.MAX_VALUE - 1; - } - - @Override - public void setMedia(long media) { - // NO-OP - } - - @Override - public boolean canRecharge() { - return true; - } - - @Override - public boolean canProvide() { - return true; - } - - @Override - public int getConsumptionPriority() { - return 1000; - } - - @Override - public boolean canConstructBattery() { - return false; - } - - @Override - public long withdrawMedia(long cost, boolean simulate) { - ItemCreativeUnlocker.addToLongArray(creativeUnlocker, ItemCreativeUnlocker.TAG_EXTRACTIONS, cost); - - return cost < 0 ? getMedia() : cost; - } - - @Override - public long insertMedia(long amount, boolean simulate) { - ItemCreativeUnlocker.addToLongArray(creativeUnlocker, ItemCreativeUnlocker.TAG_INSERTIONS, amount); - - return amount; - } + @Override + public long getMedia() { + return Integer.MAX_VALUE; + } + + @Override + public long getMaxMedia() { + return Integer.MAX_VALUE - 1; + } + + @Override + public void setMedia(long media) { + // NO-OP + } + + @Override + public boolean canRecharge() { + return true; + } + + @Override + public boolean canProvide() { + return true; + } + + @Override + public int getConsumptionPriority() { + return 1000; + } + + @Override + public boolean canConstructBattery() { + return false; + } + + @Override + public long withdrawMedia(long cost, boolean simulate) { + ItemCreativeUnlocker.addToLongArray( + creativeUnlocker, ItemCreativeUnlocker.TAG_EXTRACTIONS, cost); + + return cost < 0 ? getMedia() : cost; + } + + @Override + public long insertMedia(long amount, boolean simulate) { + ItemCreativeUnlocker.addToLongArray( + creativeUnlocker, ItemCreativeUnlocker.TAG_INSERTIONS, amount); + + return amount; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemArtifact.java b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemArtifact.java index d70310437b..ab7af83357 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemArtifact.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemArtifact.java @@ -1,33 +1,33 @@ package at.petrak.hexcasting.common.items.magic; +import static at.petrak.hexcasting.common.items.storage.ItemFocus.NUM_VARIANTS; + import at.petrak.hexcasting.api.item.VariantItem; import at.petrak.hexcasting.api.mod.HexConfig; import net.minecraft.world.item.ItemStack; -import static at.petrak.hexcasting.common.items.storage.ItemFocus.NUM_VARIANTS; - public class ItemArtifact extends ItemPackagedHex implements VariantItem { - public ItemArtifact(Properties pProperties) { - super(pProperties); - } + public ItemArtifact(Properties pProperties) { + super(pProperties); + } - @Override - public boolean canDrawMediaFromInventory(ItemStack stack) { - return true; - } + @Override + public boolean canDrawMediaFromInventory(ItemStack stack) { + return true; + } - @Override - public boolean breakAfterDepletion() { - return false; - } + @Override + public boolean breakAfterDepletion() { + return false; + } - @Override - public int cooldown() { - return HexConfig.common().artifactCooldown(); - } + @Override + public int cooldown() { + return HexConfig.common().artifactCooldown(); + } - @Override - public int numVariants() { - return NUM_VARIANTS; - } + @Override + public int numVariants() { + return NUM_VARIANTS; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemCreativeUnlocker.java b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemCreativeUnlocker.java index 586f8b2c02..b7274a3e91 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemCreativeUnlocker.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemCreativeUnlocker.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.common.items.magic; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.circles.BlockEntityAbstractImpetus; import at.petrak.hexcasting.api.item.MediaHolderItem; import at.petrak.hexcasting.api.misc.DiscoveryHandlers; @@ -8,6 +10,10 @@ import at.petrak.hexcasting.common.items.ItemLoreFragment; import at.petrak.hexcasting.common.lib.HexItems; import at.petrak.hexcasting.common.lib.HexSounds; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; import net.minecraft.ChatFormatting; import net.minecraft.advancements.Advancement; import net.minecraft.locale.Language; @@ -29,245 +35,264 @@ import net.minecraft.world.level.block.entity.BlockEntity; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class ItemCreativeUnlocker extends Item implements MediaHolderItem { - public static final String DISPLAY_MEDIA = "media"; - public static final String DISPLAY_PATTERNS = "patterns"; - - static { - DiscoveryHandlers.addDebugItemDiscoverer((player, type) -> { - for (ItemStack item : player.getInventory().items) { - if (isDebug(item, type)) { - return item; - } - } - - // Technically possible with commands! - for (ItemStack item : player.getInventory().armor) { - if (isDebug(item, type)) { - return item; - } - } - - for (ItemStack item : player.getInventory().offhand) { - if (isDebug(item, type)) { - return item; - } - } - return ItemStack.EMPTY; - }); - } - - public static boolean isDebug(ItemStack stack) { - return isDebug(stack, null); - } - - public static boolean isDebug(ItemStack stack, String flag) { - if (!stack.is(HexItems.CREATIVE_UNLOCKER) || !stack.hasCustomHoverName()) { - return false; - } - var keywords = Arrays.asList(stack.getHoverName().getString().toLowerCase(Locale.ROOT).split(" ")); - if (!keywords.contains("debug")) { - return false; - } - return flag == null || keywords.contains(flag); - } - - public static Component infiniteMedia(Level level) { - String prefix = "item.hexcasting.creative_unlocker."; - - String emphasis = Language.getInstance().getOrDefault(prefix + "for_emphasis"); - MutableComponent emphasized = Component.empty(); - for (int i = 0; i < emphasis.length(); i++) { - emphasized.append(rainbow(Component.literal("" + emphasis.charAt(i)), i, level)); - } - - return emphasized; - } - - public static final String TAG_EXTRACTIONS = "extractions"; - public static final String TAG_INSERTIONS = "insertions"; - - public ItemCreativeUnlocker(Properties properties) { - super(properties); - } - - @Override - public long getMedia(ItemStack stack) { - return Long.MAX_VALUE; - } - - @Override - public long getMaxMedia(ItemStack stack) { - return Long.MAX_VALUE; - } - - @Override - public void setMedia(ItemStack stack, long media) { - // NO-OP - } - - @Override - public boolean canProvideMedia(ItemStack stack) { - return true; - } - - @Override - public boolean canRecharge(ItemStack stack) { - return true; - } - - public static void addToIntArray(ItemStack stack, String tag, int n) { - int[] arr = NBTHelper.getIntArray(stack, tag); - if (arr == null) { - arr = new int[0]; - } - int[] newArr = Arrays.copyOf(arr, arr.length + 1); - newArr[newArr.length - 1] = n; - NBTHelper.putIntArray(stack, tag, newArr); - } - - public static void addToLongArray(ItemStack stack, String tag, long n) { - long[] arr = NBTHelper.getLongArray(stack, tag); - if (arr == null) { - arr = new long[0]; - } - long[] newArr = Arrays.copyOf(arr, arr.length + 1); - newArr[newArr.length - 1] = n; - NBTHelper.putLongArray(stack, tag, newArr); - } - - @Override - public long withdrawMedia(ItemStack stack, long cost, boolean simulate) { - // In case it's withdrawn through other means - if (!simulate && isDebug(stack, DISPLAY_MEDIA)) { - addToLongArray(stack, TAG_EXTRACTIONS, cost); - } - - return cost < 0 ? getMedia(stack) : cost; - } - - @Override - public long insertMedia(ItemStack stack, long amount, boolean simulate) { - // In case it's inserted through other means - if (!simulate && isDebug(stack, DISPLAY_MEDIA)) { - addToLongArray(stack, TAG_INSERTIONS, amount); - } - - return amount < 0 ? getMaxMedia(stack) : amount; - } - - @Override - public boolean isFoil(ItemStack stack) { - return super.isFoil(stack) || isDebug(stack); - } - - @Override - public void inventoryTick(ItemStack stack, Level level, Entity entity, int slot, boolean selected) { - if (isDebug(stack, DISPLAY_MEDIA) && !level.isClientSide) { - debugDisplay(stack, TAG_EXTRACTIONS, "withdrawn", "all_media", entity); - debugDisplay(stack, TAG_INSERTIONS, "inserted", "infinite_media", entity); - } - } - - private void debugDisplay(ItemStack stack, String tag, String langKey, String allKey, Entity entity) { - long[] arr = NBTHelper.getLongArray(stack, tag); - if (arr != null) { - NBTHelper.remove(stack, tag); - for (long i : arr) { - if (i < 0) { - entity.sendSystemMessage(Component.translatable("hexcasting.debug.media_" + langKey, - stack.getDisplayName(), - Component.translatable("hexcasting.debug." + allKey).withStyle(ChatFormatting.GRAY)) - .withStyle(ChatFormatting.LIGHT_PURPLE)); - } else { - entity.sendSystemMessage(Component.translatable("hexcasting.debug.media_" + langKey + ".with_dust", - stack.getDisplayName(), - Component.literal("" + i).withStyle(ChatFormatting.WHITE), - Component.literal(String.format("%.2f", i * 1.0 / MediaConstants.DUST_UNIT)).withStyle( - ChatFormatting.WHITE)) - .withStyle(ChatFormatting.LIGHT_PURPLE)); - } - } - } - } - - @Override - public InteractionResult useOn(UseOnContext context) { - BlockEntity be = context.getLevel().getBlockEntity(context.getClickedPos()); - if (be instanceof BlockEntityAbstractImpetus impetus) { - impetus.setInfiniteMedia(); - context.getLevel().playSound(null, context.getClickedPos(), HexSounds.SPELL_CIRCLE_FIND_BLOCK, - SoundSource.PLAYERS, 1f, 1f); - return InteractionResult.sidedSuccess(context.getLevel().isClientSide()); - } - return InteractionResult.PASS; - } - - @Override - public ItemStack finishUsingItem(ItemStack stack, Level level, LivingEntity consumer) { - if (level instanceof ServerLevel slevel && consumer instanceof ServerPlayer player) { - var names = new ArrayList<>(ItemLoreFragment.NAMES); - names.add(0, modLoc("root")); - for (var name : names) { - var rootAdv = slevel.getServer().getAdvancements().getAdvancement(name); - if (rootAdv != null) { - var children = new ArrayList<Advancement>(); - children.add(rootAdv); - addChildren(rootAdv, children); - - var adman = player.getAdvancements(); - - for (var kid : children) { - var progress = adman.getOrStartProgress(kid); - if (!progress.isDone()) { - for (String crit : progress.getRemainingCriteria()) { - adman.award(kid, crit); - } - } - } - } - } - } - - ItemStack copy = stack.copy(); - super.finishUsingItem(stack, level, consumer); - return copy; - } - - private static MutableComponent rainbow(MutableComponent component, int shift, Level level) { - if (level == null) { - return component.withStyle(ChatFormatting.WHITE); - } - - return component.withStyle((s) -> s.withColor( - TextColor.fromRgb(Mth.hsvToRgb((level.getGameTime() + shift) * 2 % 360 / 360F, 1F, 1F)))); - } - - @Override - public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltipComponents, - TooltipFlag isAdvanced) { - Component emphasized = infiniteMedia(level); - - MutableComponent modName = Component.translatable("item.hexcasting.creative_unlocker.mod_name").withStyle( - (s) -> s.withColor(ItemMediaHolder.HEX_COLOR)); - - tooltipComponents.add( - Component.translatable("hexcasting.spelldata.onitem", emphasized).withStyle(ChatFormatting.GRAY)); - tooltipComponents.add(Component.translatable("item.hexcasting.creative_unlocker.tooltip", modName).withStyle(ChatFormatting.GRAY)); - } - - private static void addChildren(Advancement root, List<Advancement> out) { - for (Advancement kiddo : root.getChildren()) { - out.add(kiddo); - addChildren(kiddo, out); - } - } + public static final String DISPLAY_MEDIA = "media"; + public static final String DISPLAY_PATTERNS = "patterns"; + + static { + DiscoveryHandlers.addDebugItemDiscoverer( + (player, type) -> { + for (ItemStack item : player.getInventory().items) { + if (isDebug(item, type)) { + return item; + } + } + + // Technically possible with commands! + for (ItemStack item : player.getInventory().armor) { + if (isDebug(item, type)) { + return item; + } + } + + for (ItemStack item : player.getInventory().offhand) { + if (isDebug(item, type)) { + return item; + } + } + return ItemStack.EMPTY; + }); + } + + public static boolean isDebug(ItemStack stack) { + return isDebug(stack, null); + } + + public static boolean isDebug(ItemStack stack, String flag) { + if (!stack.is(HexItems.CREATIVE_UNLOCKER) || !stack.hasCustomHoverName()) { + return false; + } + var keywords = + Arrays.asList(stack.getHoverName().getString().toLowerCase(Locale.ROOT).split(" ")); + if (!keywords.contains("debug")) { + return false; + } + return flag == null || keywords.contains(flag); + } + + public static Component infiniteMedia(Level level) { + String prefix = "item.hexcasting.creative_unlocker."; + + String emphasis = Language.getInstance().getOrDefault(prefix + "for_emphasis"); + MutableComponent emphasized = Component.empty(); + for (int i = 0; i < emphasis.length(); i++) { + emphasized.append(rainbow(Component.literal("" + emphasis.charAt(i)), i, level)); + } + + return emphasized; + } + + public static final String TAG_EXTRACTIONS = "extractions"; + public static final String TAG_INSERTIONS = "insertions"; + + public ItemCreativeUnlocker(Properties properties) { + super(properties); + } + + @Override + public long getMedia(ItemStack stack) { + return Long.MAX_VALUE; + } + + @Override + public long getMaxMedia(ItemStack stack) { + return Long.MAX_VALUE; + } + + @Override + public void setMedia(ItemStack stack, long media) { + // NO-OP + } + + @Override + public boolean canProvideMedia(ItemStack stack) { + return true; + } + + @Override + public boolean canRecharge(ItemStack stack) { + return true; + } + + public static void addToIntArray(ItemStack stack, String tag, int n) { + int[] arr = NBTHelper.getIntArray(stack, tag); + if (arr == null) { + arr = new int[0]; + } + int[] newArr = Arrays.copyOf(arr, arr.length + 1); + newArr[newArr.length - 1] = n; + NBTHelper.putIntArray(stack, tag, newArr); + } + + public static void addToLongArray(ItemStack stack, String tag, long n) { + long[] arr = NBTHelper.getLongArray(stack, tag); + if (arr == null) { + arr = new long[0]; + } + long[] newArr = Arrays.copyOf(arr, arr.length + 1); + newArr[newArr.length - 1] = n; + NBTHelper.putLongArray(stack, tag, newArr); + } + + @Override + public long withdrawMedia(ItemStack stack, long cost, boolean simulate) { + // In case it's withdrawn through other means + if (!simulate && isDebug(stack, DISPLAY_MEDIA)) { + addToLongArray(stack, TAG_EXTRACTIONS, cost); + } + + return cost < 0 ? getMedia(stack) : cost; + } + + @Override + public long insertMedia(ItemStack stack, long amount, boolean simulate) { + // In case it's inserted through other means + if (!simulate && isDebug(stack, DISPLAY_MEDIA)) { + addToLongArray(stack, TAG_INSERTIONS, amount); + } + + return amount < 0 ? getMaxMedia(stack) : amount; + } + + @Override + public boolean isFoil(ItemStack stack) { + return super.isFoil(stack) || isDebug(stack); + } + + @Override + public void inventoryTick( + ItemStack stack, Level level, Entity entity, int slot, boolean selected) { + if (isDebug(stack, DISPLAY_MEDIA) && !level.isClientSide) { + debugDisplay(stack, TAG_EXTRACTIONS, "withdrawn", "all_media", entity); + debugDisplay(stack, TAG_INSERTIONS, "inserted", "infinite_media", entity); + } + } + + private void debugDisplay( + ItemStack stack, String tag, String langKey, String allKey, Entity entity) { + long[] arr = NBTHelper.getLongArray(stack, tag); + if (arr != null) { + NBTHelper.remove(stack, tag); + for (long i : arr) { + if (i < 0) { + entity.sendSystemMessage( + Component.translatable( + "hexcasting.debug.media_" + langKey, + stack.getDisplayName(), + Component.translatable("hexcasting.debug." + allKey) + .withStyle(ChatFormatting.GRAY)) + .withStyle(ChatFormatting.LIGHT_PURPLE)); + } else { + entity.sendSystemMessage( + Component.translatable( + "hexcasting.debug.media_" + langKey + ".with_dust", + stack.getDisplayName(), + Component.literal("" + i).withStyle(ChatFormatting.WHITE), + Component.literal(String.format("%.2f", i * 1.0 / MediaConstants.DUST_UNIT)) + .withStyle(ChatFormatting.WHITE)) + .withStyle(ChatFormatting.LIGHT_PURPLE)); + } + } + } + } + + @Override + public InteractionResult useOn(UseOnContext context) { + BlockEntity be = context.getLevel().getBlockEntity(context.getClickedPos()); + if (be instanceof BlockEntityAbstractImpetus impetus) { + impetus.setInfiniteMedia(); + context + .getLevel() + .playSound( + null, + context.getClickedPos(), + HexSounds.SPELL_CIRCLE_FIND_BLOCK, + SoundSource.PLAYERS, + 1f, + 1f); + return InteractionResult.sidedSuccess(context.getLevel().isClientSide()); + } + return InteractionResult.PASS; + } + + @Override + public ItemStack finishUsingItem(ItemStack stack, Level level, LivingEntity consumer) { + if (level instanceof ServerLevel slevel && consumer instanceof ServerPlayer player) { + var names = new ArrayList<>(ItemLoreFragment.NAMES); + names.add(0, modLoc("root")); + for (var name : names) { + var rootAdv = slevel.getServer().getAdvancements().getAdvancement(name); + if (rootAdv != null) { + var children = new ArrayList<Advancement>(); + children.add(rootAdv); + addChildren(rootAdv, children); + + var adman = player.getAdvancements(); + + for (var kid : children) { + var progress = adman.getOrStartProgress(kid); + if (!progress.isDone()) { + for (String crit : progress.getRemainingCriteria()) { + adman.award(kid, crit); + } + } + } + } + } + } + + ItemStack copy = stack.copy(); + super.finishUsingItem(stack, level, consumer); + return copy; + } + + private static MutableComponent rainbow(MutableComponent component, int shift, Level level) { + if (level == null) { + return component.withStyle(ChatFormatting.WHITE); + } + + return component.withStyle( + (s) -> + s.withColor( + TextColor.fromRgb( + Mth.hsvToRgb((level.getGameTime() + shift) * 2 % 360 / 360F, 1F, 1F)))); + } + + @Override + public void appendHoverText( + ItemStack stack, + @Nullable Level level, + List<Component> tooltipComponents, + TooltipFlag isAdvanced) { + Component emphasized = infiniteMedia(level); + + MutableComponent modName = + Component.translatable("item.hexcasting.creative_unlocker.mod_name") + .withStyle((s) -> s.withColor(ItemMediaHolder.HEX_COLOR)); + + tooltipComponents.add( + Component.translatable("hexcasting.spelldata.onitem", emphasized) + .withStyle(ChatFormatting.GRAY)); + tooltipComponents.add( + Component.translatable("item.hexcasting.creative_unlocker.tooltip", modName) + .withStyle(ChatFormatting.GRAY)); + } + + private static void addChildren(Advancement root, List<Advancement> out) { + for (Advancement kiddo : root.getChildren()) { + out.add(kiddo); + addChildren(kiddo, out); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemCypher.java b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemCypher.java index 6c17866772..3b9c9ed358 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemCypher.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemCypher.java @@ -1,33 +1,33 @@ package at.petrak.hexcasting.common.items.magic; +import static at.petrak.hexcasting.common.items.storage.ItemFocus.NUM_VARIANTS; + import at.petrak.hexcasting.api.item.VariantItem; import at.petrak.hexcasting.api.mod.HexConfig; import net.minecraft.world.item.ItemStack; -import static at.petrak.hexcasting.common.items.storage.ItemFocus.NUM_VARIANTS; - public class ItemCypher extends ItemPackagedHex implements VariantItem { - public ItemCypher(Properties pProperties) { - super(pProperties); - } + public ItemCypher(Properties pProperties) { + super(pProperties); + } - @Override - public boolean canDrawMediaFromInventory(ItemStack stack) { - return false; - } + @Override + public boolean canDrawMediaFromInventory(ItemStack stack) { + return false; + } - @Override - public boolean breakAfterDepletion() { - return true; - } + @Override + public boolean breakAfterDepletion() { + return true; + } - @Override - public int cooldown() { - return HexConfig.common().cypherCooldown(); - } + @Override + public int cooldown() { + return HexConfig.common().cypherCooldown(); + } - @Override - public int numVariants() { - return NUM_VARIANTS; - } + @Override + public int numVariants() { + return NUM_VARIANTS; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemMediaBattery.java b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemMediaBattery.java index 48fbd25ab7..b46cf8ae7d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemMediaBattery.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemMediaBattery.java @@ -1,29 +1,25 @@ package at.petrak.hexcasting.common.items.magic; -import at.petrak.hexcasting.api.misc.MediaConstants; -import net.minecraft.core.NonNullList; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.ItemStack; -import org.jetbrains.annotations.NotNull; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; public class ItemMediaBattery extends ItemMediaHolder { - public static final ResourceLocation MEDIA_PREDICATE = modLoc("media"); - public static final ResourceLocation MAX_MEDIA_PREDICATE = modLoc("max_media"); + public static final ResourceLocation MEDIA_PREDICATE = modLoc("media"); + public static final ResourceLocation MAX_MEDIA_PREDICATE = modLoc("max_media"); - public ItemMediaBattery(Properties pProperties) { - super(pProperties); - } + public ItemMediaBattery(Properties pProperties) { + super(pProperties); + } - @Override - public boolean canProvideMedia(ItemStack stack) { - return true; - } + @Override + public boolean canProvideMedia(ItemStack stack) { + return true; + } - @Override - public boolean canRecharge(ItemStack stack) { - return true; - } + @Override + public boolean canRecharge(ItemStack stack) { + return true; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemMediaHolder.java b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemMediaHolder.java index 5bc736a2fa..b4db037fc6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemMediaHolder.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemMediaHolder.java @@ -5,115 +5,118 @@ import at.petrak.hexcasting.api.utils.MathUtils; import at.petrak.hexcasting.api.utils.MediaHelper; import at.petrak.hexcasting.api.utils.NBTHelper; +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.util.List; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TextColor; -import net.minecraft.util.Mth; 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 org.jetbrains.annotations.Nullable; -import java.math.RoundingMode; -import java.text.DecimalFormat; -import java.util.List; - public abstract class ItemMediaHolder extends Item implements MediaHolderItem { - public static final String TAG_MEDIA = "hexcasting:media"; - public static final String TAG_MAX_MEDIA = "hexcasting:start_media"; - - public static final TextColor HEX_COLOR = TextColor.fromRgb(0xb38ef3); - - private static final DecimalFormat PERCENTAGE = new DecimalFormat("####"); - - static { - PERCENTAGE.setRoundingMode(RoundingMode.DOWN); - } - - private static final DecimalFormat DUST_AMOUNT = new DecimalFormat("###,###.##"); - - public ItemMediaHolder(Properties pProperties) { - super(pProperties); - } - - public static ItemStack withMedia(ItemStack stack, long media, long maxMedia) { - Item item = stack.getItem(); - if (item instanceof ItemMediaHolder) { - NBTHelper.putLong(stack, TAG_MEDIA, media); - NBTHelper.putLong(stack, TAG_MAX_MEDIA, maxMedia); - } - - return stack; - } - - @Override - public long getMedia(ItemStack stack) { - if (NBTHelper.hasInt(stack, TAG_MEDIA)) - return NBTHelper.getInt(stack, TAG_MEDIA); - - return NBTHelper.getLong(stack, TAG_MEDIA); - } - - @Override - public long getMaxMedia(ItemStack stack) { - if (NBTHelper.hasInt(stack, TAG_MAX_MEDIA)) - return NBTHelper.getInt(stack, TAG_MAX_MEDIA); - - return NBTHelper.getLong(stack, TAG_MAX_MEDIA); - } - - @Override - public void setMedia(ItemStack stack, long media) { - NBTHelper.putLong(stack, TAG_MEDIA, MathUtils.clamp(media, 0, getMaxMedia(stack))); - } - - @Override - public boolean isBarVisible(ItemStack pStack) { - return getMaxMedia(pStack) > 0; - } - - @Override - public int getBarColor(ItemStack pStack) { - var media = getMedia(pStack); - var maxMedia = getMaxMedia(pStack); - return MediaHelper.mediaBarColor(media, maxMedia); - } - - @Override - public int getBarWidth(ItemStack pStack) { - var media = getMedia(pStack); - var maxMedia = getMaxMedia(pStack); - return MediaHelper.mediaBarWidth(media, maxMedia); - } - - @Override - public boolean canBeDepleted() { - return false; - } - - @Override - public void appendHoverText(ItemStack pStack, @Nullable Level pLevel, List<Component> pTooltipComponents, - TooltipFlag pIsAdvanced) { - var maxMedia = getMaxMedia(pStack); - if (maxMedia > 0) { - var media = getMedia(pStack); - var fullness = getMediaFullness(pStack); - - var color = TextColor.fromRgb(MediaHelper.mediaBarColor(media, maxMedia)); - - var mediamount = Component.literal(DUST_AMOUNT.format(media / (float) MediaConstants.DUST_UNIT)); - var percentFull = Component.literal(PERCENTAGE.format(100f * fullness) + "%"); - var maxCapacity = Component.translatable("hexcasting.tooltip.media", DUST_AMOUNT.format(maxMedia / (float) MediaConstants.DUST_UNIT)); - - mediamount.withStyle(style -> style.withColor(HEX_COLOR)); - maxCapacity.withStyle(style -> style.withColor(HEX_COLOR)); - percentFull.withStyle(style -> style.withColor(color)); - - pTooltipComponents.add( - Component.translatable("hexcasting.tooltip.media_amount.advanced", - mediamount, maxCapacity, percentFull)); - } - - super.appendHoverText(pStack, pLevel, pTooltipComponents, pIsAdvanced); - } + public static final String TAG_MEDIA = "hexcasting:media"; + public static final String TAG_MAX_MEDIA = "hexcasting:start_media"; + + public static final TextColor HEX_COLOR = TextColor.fromRgb(0xb38ef3); + + private static final DecimalFormat PERCENTAGE = new DecimalFormat("####"); + + static { + PERCENTAGE.setRoundingMode(RoundingMode.DOWN); + } + + private static final DecimalFormat DUST_AMOUNT = new DecimalFormat("###,###.##"); + + public ItemMediaHolder(Properties pProperties) { + super(pProperties); + } + + public static ItemStack withMedia(ItemStack stack, long media, long maxMedia) { + Item item = stack.getItem(); + if (item instanceof ItemMediaHolder) { + NBTHelper.putLong(stack, TAG_MEDIA, media); + NBTHelper.putLong(stack, TAG_MAX_MEDIA, maxMedia); + } + + return stack; + } + + @Override + public long getMedia(ItemStack stack) { + if (NBTHelper.hasInt(stack, TAG_MEDIA)) return NBTHelper.getInt(stack, TAG_MEDIA); + + return NBTHelper.getLong(stack, TAG_MEDIA); + } + + @Override + public long getMaxMedia(ItemStack stack) { + if (NBTHelper.hasInt(stack, TAG_MAX_MEDIA)) return NBTHelper.getInt(stack, TAG_MAX_MEDIA); + + return NBTHelper.getLong(stack, TAG_MAX_MEDIA); + } + + @Override + public void setMedia(ItemStack stack, long media) { + NBTHelper.putLong(stack, TAG_MEDIA, MathUtils.clamp(media, 0, getMaxMedia(stack))); + } + + @Override + public boolean isBarVisible(ItemStack pStack) { + return getMaxMedia(pStack) > 0; + } + + @Override + public int getBarColor(ItemStack pStack) { + var media = getMedia(pStack); + var maxMedia = getMaxMedia(pStack); + return MediaHelper.mediaBarColor(media, maxMedia); + } + + @Override + public int getBarWidth(ItemStack pStack) { + var media = getMedia(pStack); + var maxMedia = getMaxMedia(pStack); + return MediaHelper.mediaBarWidth(media, maxMedia); + } + + @Override + public boolean canBeDepleted() { + return false; + } + + @Override + public void appendHoverText( + ItemStack pStack, + @Nullable Level pLevel, + List<Component> pTooltipComponents, + TooltipFlag pIsAdvanced) { + var maxMedia = getMaxMedia(pStack); + if (maxMedia > 0) { + var media = getMedia(pStack); + var fullness = getMediaFullness(pStack); + + var color = TextColor.fromRgb(MediaHelper.mediaBarColor(media, maxMedia)); + + var mediamount = + Component.literal(DUST_AMOUNT.format(media / (float) MediaConstants.DUST_UNIT)); + var percentFull = Component.literal(PERCENTAGE.format(100f * fullness) + "%"); + var maxCapacity = + Component.translatable( + "hexcasting.tooltip.media", + DUST_AMOUNT.format(maxMedia / (float) MediaConstants.DUST_UNIT)); + + mediamount.withStyle(style -> style.withColor(HEX_COLOR)); + maxCapacity.withStyle(style -> style.withColor(HEX_COLOR)); + percentFull.withStyle(style -> style.withColor(color)); + + pTooltipComponents.add( + Component.translatable( + "hexcasting.tooltip.media_amount.advanced", mediamount, maxCapacity, percentFull)); + } + + super.appendHoverText(pStack, pLevel, pTooltipComponents, pIsAdvanced); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemPackagedHex.java b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemPackagedHex.java index a189fd0703..ff57396f0b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemPackagedHex.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemPackagedHex.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.common.items.magic; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.ParticleSpray; import at.petrak.hexcasting.api.casting.eval.env.PackagedItemCastEnv; import at.petrak.hexcasting.api.casting.eval.vm.CastingVM; @@ -11,6 +13,8 @@ import at.petrak.hexcasting.api.utils.NBTHelper; import at.petrak.hexcasting.common.msgs.MsgNewSpiralPatternsS2C; import at.petrak.hexcasting.xplat.IXplatAbstractions; +import java.util.ArrayList; +import java.util.List; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; @@ -29,153 +33,148 @@ import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - -/** - * Item that holds a list of patterns in it ready to be cast - */ +/** Item that holds a list of patterns in it ready to be cast */ public abstract class ItemPackagedHex extends ItemMediaHolder implements HexHolderItem { - public static final String TAG_PROGRAM = "patterns"; - public static final String TAG_PIGMENT = "pigment"; - public static final ResourceLocation HAS_PATTERNS_PRED = modLoc("has_patterns"); - - public ItemPackagedHex(Properties pProperties) { - super(pProperties); - } - - public abstract boolean breakAfterDepletion(); - - public abstract int cooldown(); - - @Override - public boolean canRecharge(ItemStack stack) { - return !breakAfterDepletion(); - } - - @Override - public boolean canProvideMedia(ItemStack stack) { - return false; - } - - @Override - public boolean hasHex(ItemStack stack) { - return NBTHelper.hasList(stack, TAG_PROGRAM, Tag.TAG_COMPOUND); - } - - @Override - public @Nullable List<Iota> getHex(ItemStack stack, ServerLevel level) { - var patsTag = NBTHelper.getList(stack, TAG_PROGRAM, Tag.TAG_COMPOUND); - - if (patsTag == null) { - return null; - } - - var out = new ArrayList<Iota>(); - for (var patTag : patsTag) { - CompoundTag tag = NBTHelper.getAsCompound(patTag); - out.add(IotaType.deserialize(tag, level)); - } - return out; - } - - @Override - public void writeHex(ItemStack stack, List<Iota> program, @Nullable FrozenPigment pigment, long media) { - ListTag patsTag = new ListTag(); - for (Iota pat : program) { - patsTag.add(IotaType.serialize(pat)); - } - - NBTHelper.putList(stack, TAG_PROGRAM, patsTag); - if (pigment != null) - NBTHelper.putCompound(stack, TAG_PIGMENT, pigment.serializeToNBT()); - - withMedia(stack, media, media); - } - - @Override - public void clearHex(ItemStack stack) { - NBTHelper.remove(stack, TAG_PROGRAM); - NBTHelper.remove(stack, TAG_PIGMENT); - NBTHelper.remove(stack, TAG_MEDIA); - NBTHelper.remove(stack, TAG_MAX_MEDIA); - } - - @Override - public @Nullable FrozenPigment getPigment(ItemStack stack) { - var ctag = NBTHelper.getCompound(stack, TAG_PIGMENT); - if (ctag == null) - return null; - return FrozenPigment.fromNBT(ctag); - } - - @Override - public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand usedHand) { - var stack = player.getItemInHand(usedHand); - if (!hasHex(stack)) { - return InteractionResultHolder.fail(stack); - } - - if (world.isClientSide) { - return InteractionResultHolder.success(stack); - } - - List<Iota> instrs = getHex(stack, (ServerLevel) world); - if (instrs == null) { - return InteractionResultHolder.fail(stack); - } - var sPlayer = (ServerPlayer) player; - var ctx = new PackagedItemCastEnv(sPlayer, usedHand); - var harness = CastingVM.empty(ctx); - var clientView = harness.queueExecuteAndWrapIotas(instrs, sPlayer.serverLevel()); - - var patterns = instrs.stream() - .filter(i -> i instanceof PatternIota) - .map(i -> ((PatternIota) i).getPattern()) - .toList(); - var packet = new MsgNewSpiralPatternsS2C(sPlayer.getUUID(), patterns, 140); - IXplatAbstractions.INSTANCE.sendPacketToPlayer(sPlayer, packet); - IXplatAbstractions.INSTANCE.sendPacketTracking(sPlayer, packet); - - boolean broken = breakAfterDepletion() && getMedia(stack) == 0; - - Stat<?> stat; - if (broken) { - stat = Stats.ITEM_BROKEN.get(this); - } else { - stat = Stats.ITEM_USED.get(this); - } - player.awardStat(stat); - - sPlayer.getCooldowns().addCooldown(this, this.cooldown()); - - if (clientView.getResolutionType().getSuccess()) { - // Somehow we lost spraying particles on each new pattern, so do it here - // this also nicely prevents particle spam on trinkets - new ParticleSpray(player.position(), new Vec3(0.0, 1.5, 0.0), 0.4, Math.PI / 3, 30) - .sprayParticles(sPlayer.serverLevel(), ctx.getPigment()); - } - - var sound = ctx.getSound().sound(); - if (sound != null) { - var soundPos = sPlayer.position(); - sPlayer.level().playSound(null, soundPos.x, soundPos.y, soundPos.z, - sound, SoundSource.PLAYERS, 1f, 1f); - } - - if (broken) { - stack.shrink(1); - player.broadcastBreakEvent(usedHand); - return InteractionResultHolder.consume(stack); - } else { - return InteractionResultHolder.success(stack); - } - } - - @Override - public UseAnim getUseAnimation(ItemStack pStack) { - return UseAnim.BLOCK; - } + public static final String TAG_PROGRAM = "patterns"; + public static final String TAG_PIGMENT = "pigment"; + public static final ResourceLocation HAS_PATTERNS_PRED = modLoc("has_patterns"); + + public ItemPackagedHex(Properties pProperties) { + super(pProperties); + } + + public abstract boolean breakAfterDepletion(); + + public abstract int cooldown(); + + @Override + public boolean canRecharge(ItemStack stack) { + return !breakAfterDepletion(); + } + + @Override + public boolean canProvideMedia(ItemStack stack) { + return false; + } + + @Override + public boolean hasHex(ItemStack stack) { + return NBTHelper.hasList(stack, TAG_PROGRAM, Tag.TAG_COMPOUND); + } + + @Override + public @Nullable List<Iota> getHex(ItemStack stack, ServerLevel level) { + var patsTag = NBTHelper.getList(stack, TAG_PROGRAM, Tag.TAG_COMPOUND); + + if (patsTag == null) { + return null; + } + + var out = new ArrayList<Iota>(); + for (var patTag : patsTag) { + CompoundTag tag = NBTHelper.getAsCompound(patTag); + out.add(IotaType.deserialize(tag, level)); + } + return out; + } + + @Override + public void writeHex( + ItemStack stack, List<Iota> program, @Nullable FrozenPigment pigment, long media) { + ListTag patsTag = new ListTag(); + for (Iota pat : program) { + patsTag.add(IotaType.serialize(pat)); + } + + NBTHelper.putList(stack, TAG_PROGRAM, patsTag); + if (pigment != null) NBTHelper.putCompound(stack, TAG_PIGMENT, pigment.serializeToNBT()); + + withMedia(stack, media, media); + } + + @Override + public void clearHex(ItemStack stack) { + NBTHelper.remove(stack, TAG_PROGRAM); + NBTHelper.remove(stack, TAG_PIGMENT); + NBTHelper.remove(stack, TAG_MEDIA); + NBTHelper.remove(stack, TAG_MAX_MEDIA); + } + + @Override + public @Nullable FrozenPigment getPigment(ItemStack stack) { + var ctag = NBTHelper.getCompound(stack, TAG_PIGMENT); + if (ctag == null) return null; + return FrozenPigment.fromNBT(ctag); + } + + @Override + public InteractionResultHolder<ItemStack> use( + Level world, Player player, InteractionHand usedHand) { + var stack = player.getItemInHand(usedHand); + if (!hasHex(stack)) { + return InteractionResultHolder.fail(stack); + } + + if (world.isClientSide) { + return InteractionResultHolder.success(stack); + } + + List<Iota> instrs = getHex(stack, (ServerLevel) world); + if (instrs == null) { + return InteractionResultHolder.fail(stack); + } + var sPlayer = (ServerPlayer) player; + var ctx = new PackagedItemCastEnv(sPlayer, usedHand); + var harness = CastingVM.empty(ctx); + var clientView = harness.queueExecuteAndWrapIotas(instrs, sPlayer.serverLevel()); + + var patterns = + instrs.stream() + .filter(i -> i instanceof PatternIota) + .map(i -> ((PatternIota) i).getPattern()) + .toList(); + var packet = new MsgNewSpiralPatternsS2C(sPlayer.getUUID(), patterns, 140); + IXplatAbstractions.INSTANCE.sendPacketToPlayer(sPlayer, packet); + IXplatAbstractions.INSTANCE.sendPacketTracking(sPlayer, packet); + + boolean broken = breakAfterDepletion() && getMedia(stack) == 0; + + Stat<?> stat; + if (broken) { + stat = Stats.ITEM_BROKEN.get(this); + } else { + stat = Stats.ITEM_USED.get(this); + } + player.awardStat(stat); + + sPlayer.getCooldowns().addCooldown(this, this.cooldown()); + + if (clientView.getResolutionType().getSuccess()) { + // Somehow we lost spraying particles on each new pattern, so do it here + // this also nicely prevents particle spam on trinkets + new ParticleSpray(player.position(), new Vec3(0.0, 1.5, 0.0), 0.4, Math.PI / 3, 30) + .sprayParticles(sPlayer.serverLevel(), ctx.getPigment()); + } + + var sound = ctx.getSound().sound(); + if (sound != null) { + var soundPos = sPlayer.position(); + sPlayer + .level() + .playSound(null, soundPos.x, soundPos.y, soundPos.z, sound, SoundSource.PLAYERS, 1f, 1f); + } + + if (broken) { + stack.shrink(1); + player.broadcastBreakEvent(usedHand); + return InteractionResultHolder.consume(stack); + } else { + return InteractionResultHolder.success(stack); + } + } + + @Override + public UseAnim getUseAnimation(ItemStack pStack) { + return UseAnim.BLOCK; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemTrinket.java b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemTrinket.java index b936f1277a..f599b46b1f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemTrinket.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemTrinket.java @@ -1,33 +1,33 @@ package at.petrak.hexcasting.common.items.magic; +import static at.petrak.hexcasting.common.items.storage.ItemFocus.NUM_VARIANTS; + import at.petrak.hexcasting.api.item.VariantItem; import at.petrak.hexcasting.api.mod.HexConfig; import net.minecraft.world.item.ItemStack; -import static at.petrak.hexcasting.common.items.storage.ItemFocus.NUM_VARIANTS; - public class ItemTrinket extends ItemPackagedHex implements VariantItem { - public ItemTrinket(Properties pProperties) { - super(pProperties); - } + public ItemTrinket(Properties pProperties) { + super(pProperties); + } - @Override - public boolean canDrawMediaFromInventory(ItemStack stack) { - return false; - } + @Override + public boolean canDrawMediaFromInventory(ItemStack stack) { + return false; + } - @Override - public boolean breakAfterDepletion() { - return false; - } + @Override + public boolean breakAfterDepletion() { + return false; + } - @Override - public int cooldown() { - return HexConfig.common().trinketCooldown(); - } + @Override + public int cooldown() { + return HexConfig.common().trinketCooldown(); + } - @Override - public int numVariants() { - return NUM_VARIANTS; - } + @Override + public int numVariants() { + return NUM_VARIANTS; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemAmethystAndCopperPigment.java b/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemAmethystAndCopperPigment.java index a41b0ccdf1..de19f22274 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemAmethystAndCopperPigment.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemAmethystAndCopperPigment.java @@ -3,36 +3,35 @@ import at.petrak.hexcasting.api.addldata.ADPigment; import at.petrak.hexcasting.api.item.PigmentItem; import at.petrak.hexcasting.api.pigment.ColorProvider; +import java.util.UUID; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; -import java.util.UUID; - public class ItemAmethystAndCopperPigment extends Item implements PigmentItem { - public ItemAmethystAndCopperPigment(Properties pProperties) { - super(pProperties); - } + public ItemAmethystAndCopperPigment(Properties pProperties) { + super(pProperties); + } - @Override - public ColorProvider provideColor(ItemStack stack, UUID owner) { - return colorProvider; - } + @Override + public ColorProvider provideColor(ItemStack stack, UUID owner) { + return colorProvider; + } - protected MyColorProvider colorProvider = new MyColorProvider(); + protected MyColorProvider colorProvider = new MyColorProvider(); - protected class MyColorProvider extends ColorProvider { - private static final int[] COLORS = { - 0xff_54398a, // dark purple - 0xff_cfa0f3, // light purple - 0xff_fecbe6, // pink - 0xff_cfa0f3, // light purple - 0xff_e77c56, // dark copper - }; + protected class MyColorProvider extends ColorProvider { + private static final int[] COLORS = { + 0xff_54398a, // dark purple + 0xff_cfa0f3, // light purple + 0xff_fecbe6, // pink + 0xff_cfa0f3, // light purple + 0xff_e77c56, // dark copper + }; - @Override - protected int getRawColor(float time, Vec3 position) { - return ADPigment.morphBetweenColors(COLORS, new Vec3(0.1, 0.1, 0.1), time / 600, position); - } - } + @Override + protected int getRawColor(float time, Vec3 position) { + return ADPigment.morphBetweenColors(COLORS, new Vec3(0.1, 0.1, 0.1), time / 600, position); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemDyePigment.java b/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemDyePigment.java index 0259a03d54..f272c50835 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemDyePigment.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemDyePigment.java @@ -2,36 +2,35 @@ import at.petrak.hexcasting.api.item.PigmentItem; import at.petrak.hexcasting.api.pigment.ColorProvider; +import java.util.UUID; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; -import java.util.UUID; - public class ItemDyePigment extends Item implements PigmentItem { - private final DyeColor dyeColor; - - public ItemDyePigment(DyeColor dyeColor, Properties pProperties) { - super(pProperties); - this.dyeColor = dyeColor; - } - - public DyeColor getDyeColor() { - return dyeColor; - } - - @Override - public ColorProvider provideColor(ItemStack stack, UUID owner) { - return colorProvider; - } - - protected MyColorProvider colorProvider = new MyColorProvider(); - - protected class MyColorProvider extends ColorProvider { - @Override - protected int getRawColor(float time, Vec3 position) { - return dyeColor.getTextColor(); - } - } + private final DyeColor dyeColor; + + public ItemDyePigment(DyeColor dyeColor, Properties pProperties) { + super(pProperties); + this.dyeColor = dyeColor; + } + + public DyeColor getDyeColor() { + return dyeColor; + } + + @Override + public ColorProvider provideColor(ItemStack stack, UUID owner) { + return colorProvider; + } + + protected MyColorProvider colorProvider = new MyColorProvider(); + + protected class MyColorProvider extends ColorProvider { + @Override + protected int getRawColor(float time, Vec3 position) { + return dyeColor.getTextColor(); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemPridePigment.java b/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemPridePigment.java index ebd8225ccb..b5fdc25a38 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemPridePigment.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemPridePigment.java @@ -3,66 +3,66 @@ import at.petrak.hexcasting.api.addldata.ADPigment; import at.petrak.hexcasting.api.item.PigmentItem; import at.petrak.hexcasting.api.pigment.ColorProvider; +import java.util.Locale; +import java.util.UUID; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; -import java.util.Locale; -import java.util.UUID; - public class ItemPridePigment extends Item implements PigmentItem { - public enum Type { - AGENDER(new int[]{0x16a10c, 0xffffff, 0x7a8081, 0x302f30}), - AROACE(new int[]{0x7210bc, 0xebf367, 0xffffff, 0x82dceb, 0x2f4dd8}), - AROMANTIC(new int[]{0x16a10c, 0x82eb8b, 0xffffff, 0x7a8081, 0x302f30}), - ASEXUAL(new int[]{0x333233, 0x9a9fa1, 0xffffff, 0x7210bc}), - BISEXUAL(new int[]{0xdb45ff, 0x9c2bd0, 0x6894d4}), - DEMIBOY(new int[]{0x9a9fa1, 0xa9ffff, 0xffffff}), - DEMIGIRL(new int[]{0x9a9fa1, 0xfcb1ff, 0xffffff}), - GAY(new int[]{0xd82f3a, 0xe0883f, 0xebf367, 0x2db418, 0x2f4dd8}), -// ACHILLEAN(new int[]{0x028d6e, 0x22cdad, 0xffffff, 0xe49c7, 0x4f4aca}), - GENDERFLUID(new int[]{0xfbacf9, 0xffffff, 0x9c2bd0, 0x333233, 0x2f4dd8}), - GENDERQUEER(new int[]{0xca78ef, 0xffffff, 0x2db418}), - // how to do an intersex gradient escapes me - INTERSEX(new int[]{0xebf367, 0x7210bc}), - LESBIAN(new int[]{0xd82f3a, 0xefb87d, 0xffffff, 0xfbacf9, 0xa30262}), - NONBINARY(new int[]{0xebf367, 0xffffff, 0x7210bc, 0x333233}), - PANSEXUAL(new int[]{0xe278ef, 0xebf367, 0x6ac2e4}), - PLURAL(new int[]{0x30c69f, 0x347ddf, 0x6b3fbe, 0x000000}), - TRANSGENDER(new int[]{0xeb92ea, 0xffffff, 0x6ac2e4}); + public enum Type { + AGENDER(new int[] {0x16a10c, 0xffffff, 0x7a8081, 0x302f30}), + AROACE(new int[] {0x7210bc, 0xebf367, 0xffffff, 0x82dceb, 0x2f4dd8}), + AROMANTIC(new int[] {0x16a10c, 0x82eb8b, 0xffffff, 0x7a8081, 0x302f30}), + ASEXUAL(new int[] {0x333233, 0x9a9fa1, 0xffffff, 0x7210bc}), + BISEXUAL(new int[] {0xdb45ff, 0x9c2bd0, 0x6894d4}), + DEMIBOY(new int[] {0x9a9fa1, 0xa9ffff, 0xffffff}), + DEMIGIRL(new int[] {0x9a9fa1, 0xfcb1ff, 0xffffff}), + GAY(new int[] {0xd82f3a, 0xe0883f, 0xebf367, 0x2db418, 0x2f4dd8}), + // ACHILLEAN(new int[]{0x028d6e, 0x22cdad, 0xffffff, 0xe49c7, 0x4f4aca}), + GENDERFLUID(new int[] {0xfbacf9, 0xffffff, 0x9c2bd0, 0x333233, 0x2f4dd8}), + GENDERQUEER(new int[] {0xca78ef, 0xffffff, 0x2db418}), + // how to do an intersex gradient escapes me + INTERSEX(new int[] {0xebf367, 0x7210bc}), + LESBIAN(new int[] {0xd82f3a, 0xefb87d, 0xffffff, 0xfbacf9, 0xa30262}), + NONBINARY(new int[] {0xebf367, 0xffffff, 0x7210bc, 0x333233}), + PANSEXUAL(new int[] {0xe278ef, 0xebf367, 0x6ac2e4}), + PLURAL(new int[] {0x30c69f, 0x347ddf, 0x6b3fbe, 0x000000}), + TRANSGENDER(new int[] {0xeb92ea, 0xffffff, 0x6ac2e4}); - private final int[] colors; + private final int[] colors; - Type(int[] colors) { - this.colors = colors; - for (int i = 0; i < this.colors.length; i++) { - this.colors[i] |= 0xFF_000000; - } - } + Type(int[] colors) { + this.colors = colors; + for (int i = 0; i < this.colors.length; i++) { + this.colors[i] |= 0xFF_000000; + } + } - public String getName() { - return this.name().toLowerCase(Locale.ROOT); - } - } + public String getName() { + return this.name().toLowerCase(Locale.ROOT); + } + } - public final Type type; + public final Type type; - public ItemPridePigment(Type type, Properties pProperties) { - super(pProperties); - this.type = type; - } + public ItemPridePigment(Type type, Properties pProperties) { + super(pProperties); + this.type = type; + } - @Override - public ColorProvider provideColor(ItemStack stack, UUID owner) { - return colorProvider; - } + @Override + public ColorProvider provideColor(ItemStack stack, UUID owner) { + return colorProvider; + } - protected MyColorProvider colorProvider = new MyColorProvider(); + protected MyColorProvider colorProvider = new MyColorProvider(); - protected class MyColorProvider extends ColorProvider { - @Override - protected int getRawColor(float time, Vec3 position) { - return ADPigment.morphBetweenColors(type.colors, new Vec3(0.1, 0.1, 0.1), time / 400, position); - } - } + protected class MyColorProvider extends ColorProvider { + @Override + protected int getRawColor(float time, Vec3 position) { + return ADPigment.morphBetweenColors( + type.colors, new Vec3(0.1, 0.1, 0.1), time / 400, position); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemUUIDPigment.java b/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemUUIDPigment.java index c895177f47..81e8bc8693 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemUUIDPigment.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/pigment/ItemUUIDPigment.java @@ -6,68 +6,67 @@ import at.petrak.paucal.api.PaucalAPI; import com.google.gson.JsonElement; import com.google.gson.JsonPrimitive; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.Vec3; - import java.awt.*; import java.util.Random; import java.util.UUID; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; public class ItemUUIDPigment extends Item implements PigmentItem { - public ItemUUIDPigment(Properties pProperties) { - super(pProperties); - } - - @Override - public ColorProvider provideColor(ItemStack stack, UUID owner) { - return new MyColorProvider(owner); - } + public ItemUUIDPigment(Properties pProperties) { + super(pProperties); + } - protected static class MyColorProvider extends ColorProvider { - private final int[] colors; + @Override + public ColorProvider provideColor(ItemStack stack, UUID owner) { + return new MyColorProvider(owner); + } - MyColorProvider(UUID owner) { - var contributor = PaucalAPI.instance().getContributor(owner); - if (contributor != null) { - var colorList = contributor.otherVals().getAsJsonArray("hexcasting:colorizer"); - if (colorList != null) { - var colors = new int[colorList.size()]; - var ok = true; - for (int i = 0; i < colorList.size(); i++) { - JsonElement elt = colorList.get(i); - if (elt instanceof JsonPrimitive n && n.isNumber()) { - colors[i] = n.getAsNumber().intValue() | 0xff_000000; - } else { - ok = false; - break; - } - } - if (ok) { - this.colors = colors; - return; - } - } - } + protected static class MyColorProvider extends ColorProvider { + private final int[] colors; - // randomly scrungle the bits - var rand = new Random(owner.getLeastSignificantBits() ^ owner.getMostSignificantBits()); - var hue1 = rand.nextFloat(); - var saturation1 = rand.nextFloat(0.4f, 0.8f); - var brightness1 = rand.nextFloat(0.7f, 1.0f); - var hue2 = rand.nextFloat(); - var saturation2 = rand.nextFloat(0.7f, 1.0f); - var brightness2 = rand.nextFloat(0.2f, 0.7f); + MyColorProvider(UUID owner) { + var contributor = PaucalAPI.instance().getContributor(owner); + if (contributor != null) { + var colorList = contributor.otherVals().getAsJsonArray("hexcasting:colorizer"); + if (colorList != null) { + var colors = new int[colorList.size()]; + var ok = true; + for (int i = 0; i < colorList.size(); i++) { + JsonElement elt = colorList.get(i); + if (elt instanceof JsonPrimitive n && n.isNumber()) { + colors[i] = n.getAsNumber().intValue() | 0xff_000000; + } else { + ok = false; + break; + } + } + if (ok) { + this.colors = colors; + return; + } + } + } - var col1 = Color.HSBtoRGB(hue1, saturation1, brightness1); - var col2 = Color.HSBtoRGB(hue2, saturation2, brightness2); - this.colors = new int[]{col1, col2}; - } + // randomly scrungle the bits + var rand = new Random(owner.getLeastSignificantBits() ^ owner.getMostSignificantBits()); + var hue1 = rand.nextFloat(); + var saturation1 = rand.nextFloat(0.4f, 0.8f); + var brightness1 = rand.nextFloat(0.7f, 1.0f); + var hue2 = rand.nextFloat(); + var saturation2 = rand.nextFloat(0.7f, 1.0f); + var brightness2 = rand.nextFloat(0.2f, 0.7f); + var col1 = Color.HSBtoRGB(hue1, saturation1, brightness1); + var col2 = Color.HSBtoRGB(hue2, saturation2, brightness2); + this.colors = new int[] {col1, col2}; + } - @Override - protected int getRawColor(float time, Vec3 position) { - return ADPigment.morphBetweenColors(this.colors, new Vec3(0.1, 0.1, 0.1), time / 400, position); - } - } + @Override + protected int getRawColor(float time, Vec3 position) { + return ADPigment.morphBetweenColors( + this.colors, new Vec3(0.1, 0.1, 0.1), time / 400, position); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemAbacus.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemAbacus.java index ad8527581f..824352b4cb 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemAbacus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemAbacus.java @@ -6,6 +6,7 @@ import at.petrak.hexcasting.api.item.IotaHolderItem; import at.petrak.hexcasting.api.utils.NBTHelper; import at.petrak.hexcasting.common.lib.HexSounds; +import java.util.List; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionHand; @@ -17,61 +18,61 @@ import net.minecraft.world.level.Level; import org.jetbrains.annotations.Nullable; -import java.util.List; - public class ItemAbacus extends Item implements IotaHolderItem { - public static final String TAG_VALUE = "value"; + public static final String TAG_VALUE = "value"; - public ItemAbacus(Properties pProperties) { - super(pProperties); - } + public ItemAbacus(Properties pProperties) { + super(pProperties); + } - @Override - public @Nullable - CompoundTag readIotaTag(ItemStack stack) { - var datum = new DoubleIota(NBTHelper.getDouble(stack, TAG_VALUE)); - return IotaType.serialize(datum); - } + @Override + public @Nullable CompoundTag readIotaTag(ItemStack stack) { + var datum = new DoubleIota(NBTHelper.getDouble(stack, TAG_VALUE)); + return IotaType.serialize(datum); + } - @Override - public boolean writeable(ItemStack stack) { - return false; - } + @Override + public boolean writeable(ItemStack stack) { + return false; + } - @Override - public boolean canWrite(ItemStack stack, Iota datum) { - return false; - } + @Override + public boolean canWrite(ItemStack stack, Iota datum) { + return false; + } - @Override - public void writeDatum(ItemStack stack, Iota datum) { - // nope - } + @Override + public void writeDatum(ItemStack stack, Iota datum) { + // nope + } - @Override - public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) { - var stack = player.getItemInHand(hand); - if (player.isShiftKeyDown()) { - double oldNum = NBTHelper.getDouble(stack, TAG_VALUE); - stack.removeTagKey(TAG_VALUE); + @Override + public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) { + var stack = player.getItemInHand(hand); + if (player.isShiftKeyDown()) { + double oldNum = NBTHelper.getDouble(stack, TAG_VALUE); + stack.removeTagKey(TAG_VALUE); - player.playSound(HexSounds.ABACUS_SHAKE, 1f, 1f); + player.playSound(HexSounds.ABACUS_SHAKE, 1f, 1f); - var key = "hexcasting.tooltip.abacus.reset"; - if (oldNum == 69) { - key += ".nice"; - } - player.displayClientMessage(Component.translatable(key), true); + var key = "hexcasting.tooltip.abacus.reset"; + if (oldNum == 69) { + key += ".nice"; + } + player.displayClientMessage(Component.translatable(key), true); - return InteractionResultHolder.sidedSuccess(stack, world.isClientSide); - } else { - return InteractionResultHolder.pass(stack); - } - } + return InteractionResultHolder.sidedSuccess(stack, world.isClientSide); + } else { + return InteractionResultHolder.pass(stack); + } + } - @Override - public void appendHoverText(ItemStack pStack, @Nullable Level pLevel, List<Component> pTooltipComponents, - TooltipFlag pIsAdvanced) { - IotaHolderItem.appendHoverText(this, pStack, pTooltipComponents, pIsAdvanced); - } + @Override + public void appendHoverText( + ItemStack pStack, + @Nullable Level pLevel, + List<Component> pTooltipComponents, + TooltipFlag pIsAdvanced) { + IotaHolderItem.appendHoverText(this, pStack, pTooltipComponents, pIsAdvanced); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java index 8d08c9923f..996b62c087 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java @@ -1,10 +1,13 @@ package at.petrak.hexcasting.common.items.storage; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.item.IotaHolderItem; import at.petrak.hexcasting.api.item.VariantItem; import at.petrak.hexcasting.api.utils.NBTHelper; +import java.util.List; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; @@ -14,77 +17,76 @@ import net.minecraft.world.level.Level; import org.jetbrains.annotations.Nullable; -import java.util.List; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class ItemFocus extends Item implements IotaHolderItem, VariantItem { - // 0 = no overlay - // 1 = unsealed - // 2 = sealed - public static final ResourceLocation OVERLAY_PRED = modLoc("overlay_layer"); - public static final ResourceLocation VARIANT_PRED = modLoc("variant"); - public static final int NUM_VARIANTS = 8; - - public static final String TAG_DATA = "data"; - public static final String TAG_SEALED = "sealed"; - - public ItemFocus(Properties pProperties) { - super(pProperties); - } - - @Override - public @Nullable CompoundTag readIotaTag(ItemStack stack) { - return NBTHelper.getCompound(stack, TAG_DATA); - } - - @Override - public String getDescriptionId(ItemStack stack) { - return super.getDescriptionId(stack) + (NBTHelper.getBoolean(stack, TAG_SEALED) ? ".sealed" : ""); - } - - @Override - public boolean writeable(ItemStack stack) { - return !isSealed(stack); - } - - @Override - public boolean canWrite(ItemStack stack, Iota datum) { - return datum == null || !isSealed(stack); - } - - @Override - public void writeDatum(ItemStack stack, Iota datum) { - if (datum == null) { - stack.removeTagKey(TAG_DATA); - stack.removeTagKey(TAG_SEALED); - } else if (!isSealed(stack)) { - NBTHelper.put(stack, TAG_DATA, IotaType.serialize(datum)); - } - } - - @Override - public void appendHoverText(ItemStack pStack, @Nullable Level pLevel, List<Component> pTooltipComponents, - TooltipFlag pIsAdvanced) { - IotaHolderItem.appendHoverText(this, pStack, pTooltipComponents, pIsAdvanced); - } - - public static boolean isSealed(ItemStack stack) { - return NBTHelper.getBoolean(stack, TAG_SEALED); - } - - public static void seal(ItemStack stack) { - NBTHelper.putBoolean(stack, TAG_SEALED, true); - } - - @Override - public int numVariants() { - return NUM_VARIANTS; - } - - @Override - public void setVariant(ItemStack stack, int variant) { - if (!isSealed(stack)) - NBTHelper.putInt(stack, TAG_VARIANT, clampVariant(variant)); - } + // 0 = no overlay + // 1 = unsealed + // 2 = sealed + public static final ResourceLocation OVERLAY_PRED = modLoc("overlay_layer"); + public static final ResourceLocation VARIANT_PRED = modLoc("variant"); + public static final int NUM_VARIANTS = 8; + + public static final String TAG_DATA = "data"; + public static final String TAG_SEALED = "sealed"; + + public ItemFocus(Properties pProperties) { + super(pProperties); + } + + @Override + public @Nullable CompoundTag readIotaTag(ItemStack stack) { + return NBTHelper.getCompound(stack, TAG_DATA); + } + + @Override + public String getDescriptionId(ItemStack stack) { + return super.getDescriptionId(stack) + + (NBTHelper.getBoolean(stack, TAG_SEALED) ? ".sealed" : ""); + } + + @Override + public boolean writeable(ItemStack stack) { + return !isSealed(stack); + } + + @Override + public boolean canWrite(ItemStack stack, Iota datum) { + return datum == null || !isSealed(stack); + } + + @Override + public void writeDatum(ItemStack stack, Iota datum) { + if (datum == null) { + stack.removeTagKey(TAG_DATA); + stack.removeTagKey(TAG_SEALED); + } else if (!isSealed(stack)) { + NBTHelper.put(stack, TAG_DATA, IotaType.serialize(datum)); + } + } + + @Override + public void appendHoverText( + ItemStack pStack, + @Nullable Level pLevel, + List<Component> pTooltipComponents, + TooltipFlag pIsAdvanced) { + IotaHolderItem.appendHoverText(this, pStack, pTooltipComponents, pIsAdvanced); + } + + public static boolean isSealed(ItemStack stack) { + return NBTHelper.getBoolean(stack, TAG_SEALED); + } + + public static void seal(ItemStack stack) { + NBTHelper.putBoolean(stack, TAG_SEALED, true); + } + + @Override + public int numVariants() { + return NUM_VARIANTS; + } + + @Override + public void setVariant(ItemStack stack, int variant) { + if (!isSealed(stack)) NBTHelper.putInt(stack, TAG_VARIANT, clampVariant(variant)); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemScroll.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemScroll.java index 036e5129b4..3be3a671b7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemScroll.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemScroll.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.common.items.storage; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.PatternIota; import at.petrak.hexcasting.api.casting.math.HexPattern; @@ -10,6 +12,7 @@ import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import at.petrak.hexcasting.common.misc.PatternTooltip; import at.petrak.hexcasting.interop.inline.InlinePatternData; +import java.util.Optional; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -25,140 +28,137 @@ import net.minecraft.world.level.gameevent.GameEvent; import org.jetbrains.annotations.Nullable; -import java.util.Optional; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - /** - * TAG_OP_ID and TAG_PATTERN: "Ancient Scroll of %s" (Great Spells) - * <br> - * TAG_PATTERN: "Scroll" (custom) - * <br> - * (none): "Empty Scroll" - * <br> + * TAG_OP_ID and TAG_PATTERN: "Ancient Scroll of %s" (Great Spells) <br> + * TAG_PATTERN: "Scroll" (custom) <br> + * (none): "Empty Scroll" <br> * TAG_OP_ID: invalid */ public class ItemScroll extends Item implements IotaHolderItem { - public static final String TAG_OP_ID = "op_id"; - public static final String TAG_PATTERN = "pattern"; - public static final ResourceLocation ANCIENT_PREDICATE = modLoc("ancient"); - - public final int blockSize; - - public ItemScroll(Properties pProperties, int blockSize) { - super(pProperties); - this.blockSize = blockSize; - } - - @Override - public @Nullable - CompoundTag readIotaTag(ItemStack stack) { - CompoundTag pattern = NBTHelper.getCompound(stack, TAG_PATTERN); - if (pattern == null) { - return null; - } - // We store only the data part of the iota; pretend the rest of it's there - var out = new CompoundTag(); - out.putString(HexIotaTypes.KEY_TYPE, "hexcasting:pattern"); - out.put(HexIotaTypes.KEY_DATA, pattern); - return out; - } - - @Override - public boolean writeable(ItemStack stack) { - return true; - } - - @Override - public boolean canWrite(ItemStack stack, Iota datum) { - return datum instanceof PatternIota || datum == null; - } - - @Override - public void writeDatum(ItemStack stack, Iota datum) { - if (this.canWrite(stack, datum)) { - if (datum instanceof PatternIota pat) { - NBTHelper.putCompound(stack, TAG_PATTERN, pat.getPattern().serializeToNBT()); - } else if (datum == null) { - NBTHelper.remove(stack, TAG_PATTERN); - } - } - } - - @Override - public InteractionResult useOn(UseOnContext ctx) { - var posClicked = ctx.getClickedPos(); - var direction = ctx.getClickedFace(); - var posInFront = posClicked.relative(direction); - Player player = ctx.getPlayer(); - ItemStack itemstack = ctx.getItemInHand(); - if (player != null && !this.mayPlace(player, direction, itemstack, posInFront)) { - return InteractionResult.FAIL; - } - var level = ctx.getLevel(); - var scrollStack = itemstack.copy(); - scrollStack.setCount(1); - var scrollEntity = new EntityWallScroll(level, posInFront, direction, scrollStack, false, this.blockSize); - - // i guess - var stackTag = itemstack.getTag(); - if (stackTag != null) { - EntityType.updateCustomEntityTag(level, player, scrollEntity, stackTag); - } - - if (scrollEntity.survives()) { - if (!level.isClientSide) { - scrollEntity.playPlacementSound(); - level.gameEvent(player, GameEvent.ENTITY_PLACE, posClicked); - level.addFreshEntity(scrollEntity); - } - - itemstack.shrink(1); - return InteractionResult.sidedSuccess(level.isClientSide); - } else { - return InteractionResult.CONSUME; - } - } - - // [VanillaCopy] of HangingEntityItem - protected boolean mayPlace(Player pPlayer, Direction pDirection, ItemStack pHangingEntityStack, BlockPos pPos) { - return !pDirection.getAxis().isVertical() && pPlayer.mayUseItemAt(pPos, pDirection, pHangingEntityStack); - } - - @Override - public Component getName(ItemStack pStack) { - var descID = this.getDescriptionId(pStack); - var ancientId = NBTHelper.getString(pStack, TAG_OP_ID); - if (ancientId != null) { - return Component.translatable(descID + ".of", - Component.translatable("hexcasting.action." + ResourceLocation.tryParse(ancientId))); - } else if (NBTHelper.hasCompound(pStack, TAG_PATTERN)) { - var compound = NBTHelper.getCompound(pStack, ItemScroll.TAG_PATTERN); - var patternLabel = Component.literal(""); - if (compound != null) { - var pattern = HexPattern.fromNBT(compound); - patternLabel = Component.literal(": ").append(new InlinePatternData(pattern).asText(false)); - } - return Component.translatable(descID).append(patternLabel); - } else { - return Component.translatable(descID + ".empty"); - } - } - - // purposely no hover text - - @Override - public Optional<TooltipComponent> getTooltipImage(ItemStack stack) { - var compound = NBTHelper.getCompound(stack, ItemScroll.TAG_PATTERN); - if (compound != null) { - var pattern = HexPattern.fromNBT(compound); - return Optional.of(new PatternTooltip( - pattern, - NBTHelper.hasString(stack, ItemScroll.TAG_OP_ID) - ? PatternTooltipComponent.ANCIENT_BG - : PatternTooltipComponent.PRISTINE_BG)); - } - - return Optional.empty(); - } + public static final String TAG_OP_ID = "op_id"; + public static final String TAG_PATTERN = "pattern"; + public static final ResourceLocation ANCIENT_PREDICATE = modLoc("ancient"); + + public final int blockSize; + + public ItemScroll(Properties pProperties, int blockSize) { + super(pProperties); + this.blockSize = blockSize; + } + + @Override + public @Nullable CompoundTag readIotaTag(ItemStack stack) { + CompoundTag pattern = NBTHelper.getCompound(stack, TAG_PATTERN); + if (pattern == null) { + return null; + } + // We store only the data part of the iota; pretend the rest of it's there + var out = new CompoundTag(); + out.putString(HexIotaTypes.KEY_TYPE, "hexcasting:pattern"); + out.put(HexIotaTypes.KEY_DATA, pattern); + return out; + } + + @Override + public boolean writeable(ItemStack stack) { + return true; + } + + @Override + public boolean canWrite(ItemStack stack, Iota datum) { + return datum instanceof PatternIota || datum == null; + } + + @Override + public void writeDatum(ItemStack stack, Iota datum) { + if (this.canWrite(stack, datum)) { + if (datum instanceof PatternIota pat) { + NBTHelper.putCompound(stack, TAG_PATTERN, pat.getPattern().serializeToNBT()); + } else if (datum == null) { + NBTHelper.remove(stack, TAG_PATTERN); + } + } + } + + @Override + public InteractionResult useOn(UseOnContext ctx) { + var posClicked = ctx.getClickedPos(); + var direction = ctx.getClickedFace(); + var posInFront = posClicked.relative(direction); + Player player = ctx.getPlayer(); + ItemStack itemstack = ctx.getItemInHand(); + if (player != null && !this.mayPlace(player, direction, itemstack, posInFront)) { + return InteractionResult.FAIL; + } + var level = ctx.getLevel(); + var scrollStack = itemstack.copy(); + scrollStack.setCount(1); + var scrollEntity = + new EntityWallScroll(level, posInFront, direction, scrollStack, false, this.blockSize); + + // i guess + var stackTag = itemstack.getTag(); + if (stackTag != null) { + EntityType.updateCustomEntityTag(level, player, scrollEntity, stackTag); + } + + if (scrollEntity.survives()) { + if (!level.isClientSide) { + scrollEntity.playPlacementSound(); + level.gameEvent(player, GameEvent.ENTITY_PLACE, posClicked); + level.addFreshEntity(scrollEntity); + } + + itemstack.shrink(1); + return InteractionResult.sidedSuccess(level.isClientSide); + } else { + return InteractionResult.CONSUME; + } + } + + // [VanillaCopy] of HangingEntityItem + protected boolean mayPlace( + Player pPlayer, Direction pDirection, ItemStack pHangingEntityStack, BlockPos pPos) { + return !pDirection.getAxis().isVertical() + && pPlayer.mayUseItemAt(pPos, pDirection, pHangingEntityStack); + } + + @Override + public Component getName(ItemStack pStack) { + var descID = this.getDescriptionId(pStack); + var ancientId = NBTHelper.getString(pStack, TAG_OP_ID); + if (ancientId != null) { + return Component.translatable( + descID + ".of", + Component.translatable("hexcasting.action." + ResourceLocation.tryParse(ancientId))); + } else if (NBTHelper.hasCompound(pStack, TAG_PATTERN)) { + var compound = NBTHelper.getCompound(pStack, ItemScroll.TAG_PATTERN); + var patternLabel = Component.literal(""); + if (compound != null) { + var pattern = HexPattern.fromNBT(compound); + patternLabel = Component.literal(": ").append(new InlinePatternData(pattern).asText(false)); + } + return Component.translatable(descID).append(patternLabel); + } else { + return Component.translatable(descID + ".empty"); + } + } + + // purposely no hover text + + @Override + public Optional<TooltipComponent> getTooltipImage(ItemStack stack) { + var compound = NBTHelper.getCompound(stack, ItemScroll.TAG_PATTERN); + if (compound != null) { + var pattern = HexPattern.fromNBT(compound); + return Optional.of( + new PatternTooltip( + pattern, + NBTHelper.hasString(stack, ItemScroll.TAG_OP_ID) + ? PatternTooltipComponent.ANCIENT_BG + : PatternTooltipComponent.PRISTINE_BG)); + } + + return Optional.empty(); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSlate.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSlate.java index 98227d1eab..0cc82fb11c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSlate.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSlate.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.common.items.storage; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.annotations.SoftImplement; import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.casting.iota.Iota; @@ -12,6 +14,7 @@ import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import at.petrak.hexcasting.common.misc.PatternTooltip; import at.petrak.hexcasting.interop.inline.InlinePatternData; +import java.util.Optional; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; @@ -25,105 +28,102 @@ import net.minecraft.world.level.block.Block; import org.jetbrains.annotations.Nullable; -import java.util.Optional; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class ItemSlate extends BlockItem implements IotaHolderItem { - public static final ResourceLocation WRITTEN_PRED = modLoc("written"); - - public ItemSlate(Block pBlock, Properties pProperties) { - super(pBlock, pProperties); - } - - @Override - public Component getName(ItemStack pStack) { - var key = "block." + HexAPI.MOD_ID + ".slate." + (hasPattern(pStack) ? "written" : "blank"); - Component patternText = getPattern(pStack) - .map(pat -> Component.literal(": ").append(new InlinePatternData(pat).asText(false))) - .orElse(Component.literal("")); - return Component.translatable(key).append(patternText); - } - - public static Optional<HexPattern> getPattern(ItemStack stack){ - var bet = NBTHelper.getCompound(stack, "BlockEntityTag"); - - if (bet != null && bet.contains(BlockEntitySlate.TAG_PATTERN, Tag.TAG_COMPOUND)) { - var patTag = bet.getCompound(BlockEntitySlate.TAG_PATTERN); - if (!patTag.isEmpty()) { - var pattern = HexPattern.fromNBT(patTag); - return Optional.of(pattern); - } - } - return Optional.empty(); - } - - public static boolean hasPattern(ItemStack stack) { - return getPattern(stack).isPresent(); - } - - @SoftImplement("IForgeItem") - public boolean onEntityItemUpdate(ItemStack stack, ItemEntity entity) { - if (!hasPattern(stack)) { - NBTHelper.remove(stack, "BlockEntityTag"); - } - return false; - } - - @Override - public void inventoryTick(ItemStack pStack, Level pLevel, Entity pEntity, int pSlotId, boolean pIsSelected) { - if (!hasPattern(pStack)) { - NBTHelper.remove(pStack, "BlockEntityTag"); - } - } - - @Override - public @Nullable - CompoundTag readIotaTag(ItemStack stack) { - var bet = NBTHelper.getCompound(stack, "BlockEntityTag"); - - if (bet == null || !bet.contains(BlockEntitySlate.TAG_PATTERN, Tag.TAG_COMPOUND)) { - return null; - } - - var patTag = bet.getCompound(BlockEntitySlate.TAG_PATTERN); - if (patTag.isEmpty()) { - return null; - } - var out = new CompoundTag(); - out.putString(HexIotaTypes.KEY_TYPE, "hexcasting:pattern"); - out.put(HexIotaTypes.KEY_DATA, patTag); - return out; - } - - @Override - public boolean writeable(ItemStack stack) { - return true; - } - - @Override - public boolean canWrite(ItemStack stack, Iota datum) { - return datum instanceof PatternIota || datum == null; - } - - @Override - public void writeDatum(ItemStack stack, Iota datum) { - if (this.canWrite(stack, datum)) { - if (datum == null) { - var beTag = NBTHelper.getOrCreateCompound(stack, "BlockEntityTag"); - beTag.remove(BlockEntitySlate.TAG_PATTERN); - if (beTag.isEmpty()) { - NBTHelper.remove(stack, "BlockEntityTag"); - } - } else if (datum instanceof PatternIota pat) { - var beTag = NBTHelper.getOrCreateCompound(stack, "BlockEntityTag"); - beTag.put(BlockEntitySlate.TAG_PATTERN, pat.getPattern().serializeToNBT()); - } - } - } - - @Override - public Optional<TooltipComponent> getTooltipImage(ItemStack stack) { - return getPattern(stack).map(pat -> new PatternTooltip(pat, PatternTooltipComponent.SLATE_BG)); - } + public static final ResourceLocation WRITTEN_PRED = modLoc("written"); + + public ItemSlate(Block pBlock, Properties pProperties) { + super(pBlock, pProperties); + } + + @Override + public Component getName(ItemStack pStack) { + var key = "block." + HexAPI.MOD_ID + ".slate." + (hasPattern(pStack) ? "written" : "blank"); + Component patternText = + getPattern(pStack) + .map(pat -> Component.literal(": ").append(new InlinePatternData(pat).asText(false))) + .orElse(Component.literal("")); + return Component.translatable(key).append(patternText); + } + + public static Optional<HexPattern> getPattern(ItemStack stack) { + var bet = NBTHelper.getCompound(stack, "BlockEntityTag"); + + if (bet != null && bet.contains(BlockEntitySlate.TAG_PATTERN, Tag.TAG_COMPOUND)) { + var patTag = bet.getCompound(BlockEntitySlate.TAG_PATTERN); + if (!patTag.isEmpty()) { + var pattern = HexPattern.fromNBT(patTag); + return Optional.of(pattern); + } + } + return Optional.empty(); + } + + public static boolean hasPattern(ItemStack stack) { + return getPattern(stack).isPresent(); + } + + @SoftImplement("IForgeItem") + public boolean onEntityItemUpdate(ItemStack stack, ItemEntity entity) { + if (!hasPattern(stack)) { + NBTHelper.remove(stack, "BlockEntityTag"); + } + return false; + } + + @Override + public void inventoryTick( + ItemStack pStack, Level pLevel, Entity pEntity, int pSlotId, boolean pIsSelected) { + if (!hasPattern(pStack)) { + NBTHelper.remove(pStack, "BlockEntityTag"); + } + } + + @Override + public @Nullable CompoundTag readIotaTag(ItemStack stack) { + var bet = NBTHelper.getCompound(stack, "BlockEntityTag"); + + if (bet == null || !bet.contains(BlockEntitySlate.TAG_PATTERN, Tag.TAG_COMPOUND)) { + return null; + } + + var patTag = bet.getCompound(BlockEntitySlate.TAG_PATTERN); + if (patTag.isEmpty()) { + return null; + } + var out = new CompoundTag(); + out.putString(HexIotaTypes.KEY_TYPE, "hexcasting:pattern"); + out.put(HexIotaTypes.KEY_DATA, patTag); + return out; + } + + @Override + public boolean writeable(ItemStack stack) { + return true; + } + + @Override + public boolean canWrite(ItemStack stack, Iota datum) { + return datum instanceof PatternIota || datum == null; + } + + @Override + public void writeDatum(ItemStack stack, Iota datum) { + if (this.canWrite(stack, datum)) { + if (datum == null) { + var beTag = NBTHelper.getOrCreateCompound(stack, "BlockEntityTag"); + beTag.remove(BlockEntitySlate.TAG_PATTERN); + if (beTag.isEmpty()) { + NBTHelper.remove(stack, "BlockEntityTag"); + } + } else if (datum instanceof PatternIota pat) { + var beTag = NBTHelper.getOrCreateCompound(stack, "BlockEntityTag"); + beTag.put(BlockEntitySlate.TAG_PATTERN, pat.getPattern().serializeToNBT()); + } + } + } + + @Override + public Optional<TooltipComponent> getTooltipImage(ItemStack stack) { + return getPattern(stack).map(pat -> new PatternTooltip(pat, PatternTooltipComponent.SLATE_BG)); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java index b7521f7619..e5705df635 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java @@ -1,10 +1,14 @@ package at.petrak.hexcasting.common.items.storage; +import static at.petrak.hexcasting.common.items.storage.ItemFocus.NUM_VARIANTS; + import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.item.IotaHolderItem; import at.petrak.hexcasting.api.item.VariantItem; import at.petrak.hexcasting.api.utils.NBTHelper; +import java.util.List; +import java.util.stream.Stream; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; @@ -17,240 +21,247 @@ import net.minecraft.world.level.Level; import org.jetbrains.annotations.Nullable; -import java.util.List; -import java.util.stream.Stream; - -import static at.petrak.hexcasting.common.items.storage.ItemFocus.NUM_VARIANTS; - public class ItemSpellbook extends Item implements IotaHolderItem, VariantItem { - public static String TAG_SELECTED_PAGE = "page_idx"; - // this is a CompoundTag of string numerical keys to SpellData - // it is 1-indexed, so that 0/0 can be the special case of "it is empty" - public static String TAG_PAGES = "pages"; - - // this stores the names of pages, to be restored when you scroll - // it is 1-indexed, and the 0-case for TAG_PAGES will be treated as 1 - public static String TAG_PAGE_NAMES = "page_names"; - - // this stores the sealed status of each page, to be restored when you scroll - // it is 1-indexed, and the 0-case for TAG_PAGES will be treated as 1 - public static String TAG_SEALED = "sealed_pages"; - - // this stores which variant of the spellbook should be rendered - public static final String TAG_VARIANT = "variant"; - - public static final int MAX_PAGES = 64; - - public ItemSpellbook(Properties properties) { - super(properties); - } - - @Override - public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, - TooltipFlag isAdvanced) { - boolean sealed = isSealed(stack); - boolean empty = false; - if (NBTHelper.hasNumber(stack, TAG_SELECTED_PAGE)) { - var pageIdx = NBTHelper.getInt(stack, TAG_SELECTED_PAGE); - int highest = highestPage(stack); - if (highest != 0) { - if (sealed) { - tooltip.add(Component.translatable("hexcasting.tooltip.spellbook.page.sealed", - Component.literal(String.valueOf(pageIdx)).withStyle(ChatFormatting.WHITE), - Component.literal(String.valueOf(highest)).withStyle(ChatFormatting.WHITE), - Component.translatable("hexcasting.tooltip.spellbook.sealed").withStyle(ChatFormatting.GOLD)) - .withStyle(ChatFormatting.GRAY)); - } else { - tooltip.add(Component.translatable("hexcasting.tooltip.spellbook.page", - Component.literal(String.valueOf(pageIdx)).withStyle(ChatFormatting.WHITE), - Component.literal(String.valueOf(highest)).withStyle(ChatFormatting.WHITE)) - .withStyle(ChatFormatting.GRAY)); - } - } else { - empty = true; - } - } else { - empty = true; - } - - if (empty) { - boolean overridden = NBTHelper.hasString(stack, TAG_OVERRIDE_VISUALLY); - if (sealed) { - if (overridden) { - tooltip.add(Component.translatable("hexcasting.tooltip.spellbook.sealed").withStyle( - ChatFormatting.GOLD)); - } else { - tooltip.add(Component.translatable("hexcasting.tooltip.spellbook.empty.sealed", - Component.translatable("hexcasting.tooltip.spellbook.sealed").withStyle(ChatFormatting.GOLD)) - .withStyle(ChatFormatting.GRAY)); - } - } else if (!overridden) { - tooltip.add( - Component.translatable("hexcasting.tooltip.spellbook.empty").withStyle(ChatFormatting.GRAY)); - } - } - - IotaHolderItem.appendHoverText(this, stack, tooltip, isAdvanced); - - super.appendHoverText(stack, level, tooltip, isAdvanced); - } - - @Override - public void inventoryTick(ItemStack stack, Level pLevel, Entity pEntity, int pSlotId, boolean pIsSelected) { - int index = getPage(stack, 0); - NBTHelper.putInt(stack, TAG_SELECTED_PAGE, index); - - int shiftedIdx = Math.max(1, index); - String nameKey = String.valueOf(shiftedIdx); - CompoundTag names = NBTHelper.getOrCreateCompound(stack, TAG_PAGE_NAMES); - if (stack.hasCustomHoverName()) { - names.putString(nameKey, Component.Serializer.toJson(stack.getHoverName())); - } else { - names.remove(nameKey); - } - } - - public static boolean arePagesEmpty(ItemStack stack) { - CompoundTag tag = NBTHelper.getCompound(stack, TAG_PAGES); - return tag == null || tag.isEmpty(); - } - - @Override - public @Nullable - CompoundTag readIotaTag(ItemStack stack) { - int idx = getPage(stack, 1); - var key = String.valueOf(idx); - var tag = NBTHelper.getCompound(stack, TAG_PAGES); - if (tag != null && tag.contains(key, Tag.TAG_COMPOUND)) { - return tag.getCompound(key); - } else { - return null; - } - } - - @Override - public boolean writeable(ItemStack stack) { - return !isSealed(stack); - } - - @Override - public boolean canWrite(ItemStack stack, Iota datum) { - return datum == null || !isSealed(stack); - } - - @Override - public void writeDatum(ItemStack stack, Iota datum) { - if (datum != null && isSealed(stack)) { - return; - } - - int idx = getPage(stack, 1); - var key = String.valueOf(idx); - CompoundTag pages = NBTHelper.getCompound(stack, TAG_PAGES); - if (pages != null) { - if (datum == null) { - pages.remove(key); - NBTHelper.remove(NBTHelper.getCompound(stack, TAG_SEALED), key); - } else { - pages.put(key, IotaType.serialize(datum)); - } - - if (pages.isEmpty()) { - NBTHelper.remove(stack, TAG_PAGES); - } - } else if (datum != null) { - NBTHelper.getOrCreateCompound(stack, TAG_PAGES).put(key, IotaType.serialize(datum)); - } else { - NBTHelper.remove(NBTHelper.getCompound(stack, TAG_SEALED), key); - } - } - - public static int getPage(ItemStack stack, int ifEmpty) { - if (arePagesEmpty(stack)) { - return ifEmpty; - } else if (NBTHelper.hasNumber(stack, TAG_SELECTED_PAGE)) { - int index = NBTHelper.getInt(stack, TAG_SELECTED_PAGE); - if (index == 0) { - index = 1; - } - return index; - } else { - return 1; - } - } - - public static void setSealed(ItemStack stack, boolean sealed) { - int index = getPage(stack, 1); - - String nameKey = String.valueOf(index); - CompoundTag names = NBTHelper.getOrCreateCompound(stack, TAG_SEALED); - - if (!sealed) { - names.remove(nameKey); - } else { - names.putBoolean(nameKey, true); - } - - if (names.isEmpty()) { - NBTHelper.remove(stack, TAG_SEALED); - } else { - NBTHelper.putCompound(stack, TAG_SEALED, names); - } - - } - - public static boolean isSealed(ItemStack stack) { - int index = getPage(stack, 1); - - String nameKey = String.valueOf(index); - CompoundTag names = NBTHelper.getCompound(stack, TAG_SEALED); - return NBTHelper.getBoolean(names, nameKey); - } - - public static int highestPage(ItemStack stack) { - CompoundTag tag = NBTHelper.getCompound(stack, TAG_PAGES); - if (tag == null) { - return 0; - } - return tag.getAllKeys().stream().flatMap(s -> { - try { - return Stream.of(Integer.parseInt(s)); - } catch (NumberFormatException e) { - return Stream.empty(); - } - }).max(Integer::compare).orElse(0); - } - - public static int rotatePageIdx(ItemStack stack, boolean increase) { - int idx = getPage(stack, 0); - if (idx != 0) { - idx += increase ? 1 : -1; - idx = Math.max(1, idx); - } - idx = Mth.clamp(idx, 0, MAX_PAGES); - NBTHelper.putInt(stack, TAG_SELECTED_PAGE, idx); - - CompoundTag names = NBTHelper.getCompound(stack, TAG_PAGE_NAMES); - int shiftedIdx = Math.max(1, idx); - String nameKey = String.valueOf(shiftedIdx); - String name = NBTHelper.getString(names, nameKey); - if (name != null) { - stack.setHoverName(Component.Serializer.fromJson(name)); - } else { - stack.resetHoverName(); - } - - return idx; - } - - @Override - public int numVariants() { - return NUM_VARIANTS; - } - - @Override - public void setVariant(ItemStack stack, int variant) { - if (!isSealed(stack)) - NBTHelper.putInt(stack, TAG_VARIANT, clampVariant(variant)); - } + public static String TAG_SELECTED_PAGE = "page_idx"; + // this is a CompoundTag of string numerical keys to SpellData + // it is 1-indexed, so that 0/0 can be the special case of "it is empty" + public static String TAG_PAGES = "pages"; + + // this stores the names of pages, to be restored when you scroll + // it is 1-indexed, and the 0-case for TAG_PAGES will be treated as 1 + public static String TAG_PAGE_NAMES = "page_names"; + + // this stores the sealed status of each page, to be restored when you scroll + // it is 1-indexed, and the 0-case for TAG_PAGES will be treated as 1 + public static String TAG_SEALED = "sealed_pages"; + + // this stores which variant of the spellbook should be rendered + public static final String TAG_VARIANT = "variant"; + + public static final int MAX_PAGES = 64; + + public ItemSpellbook(Properties properties) { + super(properties); + } + + @Override + public void appendHoverText( + ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag isAdvanced) { + boolean sealed = isSealed(stack); + boolean empty = false; + if (NBTHelper.hasNumber(stack, TAG_SELECTED_PAGE)) { + var pageIdx = NBTHelper.getInt(stack, TAG_SELECTED_PAGE); + int highest = highestPage(stack); + if (highest != 0) { + if (sealed) { + tooltip.add( + Component.translatable( + "hexcasting.tooltip.spellbook.page.sealed", + Component.literal(String.valueOf(pageIdx)).withStyle(ChatFormatting.WHITE), + Component.literal(String.valueOf(highest)).withStyle(ChatFormatting.WHITE), + Component.translatable("hexcasting.tooltip.spellbook.sealed") + .withStyle(ChatFormatting.GOLD)) + .withStyle(ChatFormatting.GRAY)); + } else { + tooltip.add( + Component.translatable( + "hexcasting.tooltip.spellbook.page", + Component.literal(String.valueOf(pageIdx)).withStyle(ChatFormatting.WHITE), + Component.literal(String.valueOf(highest)).withStyle(ChatFormatting.WHITE)) + .withStyle(ChatFormatting.GRAY)); + } + } else { + empty = true; + } + } else { + empty = true; + } + + if (empty) { + boolean overridden = NBTHelper.hasString(stack, TAG_OVERRIDE_VISUALLY); + if (sealed) { + if (overridden) { + tooltip.add( + Component.translatable("hexcasting.tooltip.spellbook.sealed") + .withStyle(ChatFormatting.GOLD)); + } else { + tooltip.add( + Component.translatable( + "hexcasting.tooltip.spellbook.empty.sealed", + Component.translatable("hexcasting.tooltip.spellbook.sealed") + .withStyle(ChatFormatting.GOLD)) + .withStyle(ChatFormatting.GRAY)); + } + } else if (!overridden) { + tooltip.add( + Component.translatable("hexcasting.tooltip.spellbook.empty") + .withStyle(ChatFormatting.GRAY)); + } + } + + IotaHolderItem.appendHoverText(this, stack, tooltip, isAdvanced); + + super.appendHoverText(stack, level, tooltip, isAdvanced); + } + + @Override + public void inventoryTick( + ItemStack stack, Level pLevel, Entity pEntity, int pSlotId, boolean pIsSelected) { + int index = getPage(stack, 0); + NBTHelper.putInt(stack, TAG_SELECTED_PAGE, index); + + int shiftedIdx = Math.max(1, index); + String nameKey = String.valueOf(shiftedIdx); + CompoundTag names = NBTHelper.getOrCreateCompound(stack, TAG_PAGE_NAMES); + if (stack.hasCustomHoverName()) { + names.putString(nameKey, Component.Serializer.toJson(stack.getHoverName())); + } else { + names.remove(nameKey); + } + } + + public static boolean arePagesEmpty(ItemStack stack) { + CompoundTag tag = NBTHelper.getCompound(stack, TAG_PAGES); + return tag == null || tag.isEmpty(); + } + + @Override + public @Nullable CompoundTag readIotaTag(ItemStack stack) { + int idx = getPage(stack, 1); + var key = String.valueOf(idx); + var tag = NBTHelper.getCompound(stack, TAG_PAGES); + if (tag != null && tag.contains(key, Tag.TAG_COMPOUND)) { + return tag.getCompound(key); + } else { + return null; + } + } + + @Override + public boolean writeable(ItemStack stack) { + return !isSealed(stack); + } + + @Override + public boolean canWrite(ItemStack stack, Iota datum) { + return datum == null || !isSealed(stack); + } + + @Override + public void writeDatum(ItemStack stack, Iota datum) { + if (datum != null && isSealed(stack)) { + return; + } + + int idx = getPage(stack, 1); + var key = String.valueOf(idx); + CompoundTag pages = NBTHelper.getCompound(stack, TAG_PAGES); + if (pages != null) { + if (datum == null) { + pages.remove(key); + NBTHelper.remove(NBTHelper.getCompound(stack, TAG_SEALED), key); + } else { + pages.put(key, IotaType.serialize(datum)); + } + + if (pages.isEmpty()) { + NBTHelper.remove(stack, TAG_PAGES); + } + } else if (datum != null) { + NBTHelper.getOrCreateCompound(stack, TAG_PAGES).put(key, IotaType.serialize(datum)); + } else { + NBTHelper.remove(NBTHelper.getCompound(stack, TAG_SEALED), key); + } + } + + public static int getPage(ItemStack stack, int ifEmpty) { + if (arePagesEmpty(stack)) { + return ifEmpty; + } else if (NBTHelper.hasNumber(stack, TAG_SELECTED_PAGE)) { + int index = NBTHelper.getInt(stack, TAG_SELECTED_PAGE); + if (index == 0) { + index = 1; + } + return index; + } else { + return 1; + } + } + + public static void setSealed(ItemStack stack, boolean sealed) { + int index = getPage(stack, 1); + + String nameKey = String.valueOf(index); + CompoundTag names = NBTHelper.getOrCreateCompound(stack, TAG_SEALED); + + if (!sealed) { + names.remove(nameKey); + } else { + names.putBoolean(nameKey, true); + } + + if (names.isEmpty()) { + NBTHelper.remove(stack, TAG_SEALED); + } else { + NBTHelper.putCompound(stack, TAG_SEALED, names); + } + } + + public static boolean isSealed(ItemStack stack) { + int index = getPage(stack, 1); + + String nameKey = String.valueOf(index); + CompoundTag names = NBTHelper.getCompound(stack, TAG_SEALED); + return NBTHelper.getBoolean(names, nameKey); + } + + public static int highestPage(ItemStack stack) { + CompoundTag tag = NBTHelper.getCompound(stack, TAG_PAGES); + if (tag == null) { + return 0; + } + return tag.getAllKeys().stream() + .flatMap( + s -> { + try { + return Stream.of(Integer.parseInt(s)); + } catch (NumberFormatException e) { + return Stream.empty(); + } + }) + .max(Integer::compare) + .orElse(0); + } + + public static int rotatePageIdx(ItemStack stack, boolean increase) { + int idx = getPage(stack, 0); + if (idx != 0) { + idx += increase ? 1 : -1; + idx = Math.max(1, idx); + } + idx = Mth.clamp(idx, 0, MAX_PAGES); + NBTHelper.putInt(stack, TAG_SELECTED_PAGE, idx); + + CompoundTag names = NBTHelper.getCompound(stack, TAG_PAGE_NAMES); + int shiftedIdx = Math.max(1, idx); + String nameKey = String.valueOf(shiftedIdx); + String name = NBTHelper.getString(names, nameKey); + if (name != null) { + stack.setHoverName(Component.Serializer.fromJson(name)); + } else { + stack.resetHoverName(); + } + + return idx; + } + + @Override + public int numVariants() { + return NUM_VARIANTS; + } + + @Override + public void setVariant(ItemStack stack, int variant) { + if (!isSealed(stack)) NBTHelper.putInt(stack, TAG_VARIANT, clampVariant(variant)); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java index 9e867cc250..5e197606ea 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java @@ -1,9 +1,12 @@ package at.petrak.hexcasting.common.items.storage; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.item.IotaHolderItem; import at.petrak.hexcasting.api.utils.NBTHelper; +import java.util.List; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; @@ -13,45 +16,45 @@ import net.minecraft.world.level.Level; import org.jetbrains.annotations.Nullable; -import java.util.List; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - -// Would love to be able to just write to a piece of string but the api requires it to be the same item +// Would love to be able to just write to a piece of string but the api requires it to be the same +// item public class ItemThoughtKnot extends Item implements IotaHolderItem { - public static final ResourceLocation WRITTEN_PRED = modLoc("written"); - - public static final String TAG_DATA = "data"; - - public ItemThoughtKnot(Properties properties) { - super(properties); - } - - @Override - public @Nullable CompoundTag readIotaTag(ItemStack stack) { - return NBTHelper.getCompound(stack, TAG_DATA); - } - - @Override - public boolean writeable(ItemStack stack) { - return !NBTHelper.contains(stack, TAG_DATA); - } - - @Override - public boolean canWrite(ItemStack stack, @Nullable Iota iota) { - return iota != null && writeable(stack); - } - - @Override - public void writeDatum(ItemStack stack, @Nullable Iota iota) { - if (iota != null) { - NBTHelper.putCompound(stack, TAG_DATA, IotaType.serialize(iota)); - } - } - - @Override - public void appendHoverText(ItemStack pStack, @Nullable Level pLevel, - List<Component> pTooltipComponents, TooltipFlag pIsAdvanced) { - IotaHolderItem.appendHoverText(this, pStack, pTooltipComponents, pIsAdvanced); - } + public static final ResourceLocation WRITTEN_PRED = modLoc("written"); + + public static final String TAG_DATA = "data"; + + public ItemThoughtKnot(Properties properties) { + super(properties); + } + + @Override + public @Nullable CompoundTag readIotaTag(ItemStack stack) { + return NBTHelper.getCompound(stack, TAG_DATA); + } + + @Override + public boolean writeable(ItemStack stack) { + return !NBTHelper.contains(stack, TAG_DATA); + } + + @Override + public boolean canWrite(ItemStack stack, @Nullable Iota iota) { + return iota != null && writeable(stack); + } + + @Override + public void writeDatum(ItemStack stack, @Nullable Iota iota) { + if (iota != null) { + NBTHelper.putCompound(stack, TAG_DATA, IotaType.serialize(iota)); + } + } + + @Override + public void appendHoverText( + ItemStack pStack, + @Nullable Level pLevel, + List<Component> pTooltipComponents, + TooltipFlag pIsAdvanced) { + IotaHolderItem.appendHoverText(this, pStack, pTooltipComponents, pIsAdvanced); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexAttributes.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexAttributes.java index 967f61268f..53838643ed 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexAttributes.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexAttributes.java @@ -1,43 +1,41 @@ package at.petrak.hexcasting.common.lib; -import at.petrak.hexcasting.api.HexAPI; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.ai.attributes.Attribute; -import net.minecraft.world.entity.ai.attributes.RangedAttribute; +import static at.petrak.hexcasting.api.HexAPI.modLoc; +import at.petrak.hexcasting.api.HexAPI; import java.util.LinkedHashMap; import java.util.Map; import java.util.function.BiConsumer; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.RangedAttribute; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - -/** - * On forge: these are setup in ForgeHexInit - * On fabric: it's a mixin - */ +/** On forge: these are setup in ForgeHexInit On fabric: it's a mixin */ public class HexAttributes { - public static void register(BiConsumer<Attribute, ResourceLocation> r) { - for (var e : ATTRIBUTES.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } - - private static final Map<ResourceLocation, Attribute> ATTRIBUTES = new LinkedHashMap<>(); - - public static final Attribute GRID_ZOOM = make("grid_zoom", new RangedAttribute( - HexAPI.MOD_ID + ".attributes.grid_zoom", 1.0, 0.5, 4.0)).setSyncable(true); - - /** - * Whether you have the lens overlay when looking at something. 0 = no, > 0 = yes. - */ - public static final Attribute SCRY_SIGHT = make("scry_sight", new RangedAttribute( - HexAPI.MOD_ID + ".attributes.scry_sight", 0.0, 0.0, 1.0)).setSyncable(true); - - private static <T extends Attribute> T make(String id, T attr) { - var old = ATTRIBUTES.put(modLoc(id), attr); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + id); - } - return attr; - } + public static void register(BiConsumer<Attribute, ResourceLocation> r) { + for (var e : ATTRIBUTES.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } + + private static final Map<ResourceLocation, Attribute> ATTRIBUTES = new LinkedHashMap<>(); + + public static final Attribute GRID_ZOOM = + make("grid_zoom", new RangedAttribute(HexAPI.MOD_ID + ".attributes.grid_zoom", 1.0, 0.5, 4.0)) + .setSyncable(true); + + /** Whether you have the lens overlay when looking at something. 0 = no, > 0 = yes. */ + public static final Attribute SCRY_SIGHT = + make( + "scry_sight", + new RangedAttribute(HexAPI.MOD_ID + ".attributes.scry_sight", 0.0, 0.0, 1.0)) + .setSyncable(true); + + private static <T extends Attribute> T make(String id, T attr) { + var old = ATTRIBUTES.put(modLoc(id), attr); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + id); + } + return attr; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexBlockEntities.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexBlockEntities.java index 6e22920668..8bdb5879b7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexBlockEntities.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexBlockEntities.java @@ -10,6 +10,10 @@ import at.petrak.hexcasting.common.blocks.entity.BlockEntityConjured; import at.petrak.hexcasting.common.blocks.entity.BlockEntityQuenchedAllay; import at.petrak.hexcasting.xplat.IXplatAbstractions; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Block; @@ -17,74 +21,74 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; - public class HexBlockEntities { - public static void registerTiles(BiConsumer<BlockEntityType<?>, ResourceLocation> r) { - for (var e : BLOCK_ENTITIES.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } - - private static final Map<ResourceLocation, BlockEntityType<?>> BLOCK_ENTITIES = new LinkedHashMap<>(); + public static void registerTiles(BiConsumer<BlockEntityType<?>, ResourceLocation> r) { + for (var e : BLOCK_ENTITIES.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } - public static final BlockEntityType<BlockEntityConjured> CONJURED_TILE = register( - "conjured", - BlockEntityConjured::new, HexBlocks.CONJURED_LIGHT, HexBlocks.CONJURED_BLOCK); + private static final Map<ResourceLocation, BlockEntityType<?>> BLOCK_ENTITIES = + new LinkedHashMap<>(); - public static final BlockEntityType<BlockEntityAkashicBookshelf> AKASHIC_BOOKSHELF_TILE = register( - "akashic_bookshelf", - BlockEntityAkashicBookshelf::new, HexBlocks.AKASHIC_BOOKSHELF); + public static final BlockEntityType<BlockEntityConjured> CONJURED_TILE = + register( + "conjured", BlockEntityConjured::new, HexBlocks.CONJURED_LIGHT, HexBlocks.CONJURED_BLOCK); - public static final BlockEntityType<BlockEntityRedstoneImpetus> IMPETUS_REDSTONE_TILE = register( - "impetus/redstone", - BlockEntityRedstoneImpetus::new, HexBlocks.IMPETUS_REDSTONE); - public static final BlockEntityType<BlockEntityLookingImpetus> IMPETUS_LOOK_TILE = register( - "impetus/look", - BlockEntityLookingImpetus::new, HexBlocks.IMPETUS_LOOK); - public static final BlockEntityType<BlockEntityRightClickImpetus> IMPETUS_RIGHTCLICK_TILE = register( - "impetus/rightclick", - BlockEntityRightClickImpetus::new, HexBlocks.IMPETUS_RIGHTCLICK); + public static final BlockEntityType<BlockEntityAkashicBookshelf> AKASHIC_BOOKSHELF_TILE = + register("akashic_bookshelf", BlockEntityAkashicBookshelf::new, HexBlocks.AKASHIC_BOOKSHELF); - public static final BlockEntityType<BlockEntitySlate> SLATE_TILE = register( - "slate", - BlockEntitySlate::new, HexBlocks.SLATE); + public static final BlockEntityType<BlockEntityRedstoneImpetus> IMPETUS_REDSTONE_TILE = + register("impetus/redstone", BlockEntityRedstoneImpetus::new, HexBlocks.IMPETUS_REDSTONE); + public static final BlockEntityType<BlockEntityLookingImpetus> IMPETUS_LOOK_TILE = + register("impetus/look", BlockEntityLookingImpetus::new, HexBlocks.IMPETUS_LOOK); + public static final BlockEntityType<BlockEntityRightClickImpetus> IMPETUS_RIGHTCLICK_TILE = + register( + "impetus/rightclick", BlockEntityRightClickImpetus::new, HexBlocks.IMPETUS_RIGHTCLICK); - public static final BlockEntityType<BlockEntityQuenchedAllay> QUENCHED_ALLAY_TILE = register( - "quenched_allay", BlockEntityQuenchedAllay.fromKnownBlock(HexBlocks.QUENCHED_ALLAY), HexBlocks.QUENCHED_ALLAY); + public static final BlockEntityType<BlockEntitySlate> SLATE_TILE = + register("slate", BlockEntitySlate::new, HexBlocks.SLATE); - public static final BlockEntityType<BlockEntityQuenchedAllay> QUENCHED_ALLAY_TILES_TILE = register( - "quenched_allay_tiles", BlockEntityQuenchedAllay.fromKnownBlock(HexBlocks.QUENCHED_ALLAY_TILES), HexBlocks.QUENCHED_ALLAY_TILES); + public static final BlockEntityType<BlockEntityQuenchedAllay> QUENCHED_ALLAY_TILE = + register( + "quenched_allay", + BlockEntityQuenchedAllay.fromKnownBlock(HexBlocks.QUENCHED_ALLAY), + HexBlocks.QUENCHED_ALLAY); - public static final BlockEntityType<BlockEntityQuenchedAllay> QUENCHED_ALLAY_BRICKS_TILE = register( - "quenched_allay_bricks", BlockEntityQuenchedAllay.fromKnownBlock(HexBlocks.QUENCHED_ALLAY_BRICKS), HexBlocks.QUENCHED_ALLAY_BRICKS); + public static final BlockEntityType<BlockEntityQuenchedAllay> QUENCHED_ALLAY_TILES_TILE = + register( + "quenched_allay_tiles", + BlockEntityQuenchedAllay.fromKnownBlock(HexBlocks.QUENCHED_ALLAY_TILES), + HexBlocks.QUENCHED_ALLAY_TILES); - public static final BlockEntityType<BlockEntityQuenchedAllay> QUENCHED_ALLAY_BRICKS_SMALL_TILE = register( - "quenched_allay_bricks_small", BlockEntityQuenchedAllay.fromKnownBlock(HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL), HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL); + public static final BlockEntityType<BlockEntityQuenchedAllay> QUENCHED_ALLAY_BRICKS_TILE = + register( + "quenched_allay_bricks", + BlockEntityQuenchedAllay.fromKnownBlock(HexBlocks.QUENCHED_ALLAY_BRICKS), + HexBlocks.QUENCHED_ALLAY_BRICKS); - public static BlockEntityType<BlockEntityQuenchedAllay> typeForQuenchedAllay(BlockQuenchedAllay block) { - if (block == HexBlocks.QUENCHED_ALLAY) - return QUENCHED_ALLAY_TILE; - if (block == HexBlocks.QUENCHED_ALLAY_TILES) - return QUENCHED_ALLAY_TILES_TILE; - if (block == HexBlocks.QUENCHED_ALLAY_BRICKS) - return QUENCHED_ALLAY_BRICKS_TILE; - if (block == HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL) - return QUENCHED_ALLAY_BRICKS_SMALL_TILE; - return null; - } + public static final BlockEntityType<BlockEntityQuenchedAllay> QUENCHED_ALLAY_BRICKS_SMALL_TILE = + register( + "quenched_allay_bricks_small", + BlockEntityQuenchedAllay.fromKnownBlock(HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL), + HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL); - private static <T extends BlockEntity> BlockEntityType<T> register(String id, - BiFunction<BlockPos, BlockState, T> func, Block... blocks) { - var ret = IXplatAbstractions.INSTANCE.createBlockEntityType(func, blocks); - var old = BLOCK_ENTITIES.put(new ResourceLocation(HexAPI.MOD_ID, id), ret); - if (old != null) { - throw new IllegalArgumentException("Duplicate id " + id); - } - return ret; - } + public static BlockEntityType<BlockEntityQuenchedAllay> typeForQuenchedAllay( + BlockQuenchedAllay block) { + if (block == HexBlocks.QUENCHED_ALLAY) return QUENCHED_ALLAY_TILE; + if (block == HexBlocks.QUENCHED_ALLAY_TILES) return QUENCHED_ALLAY_TILES_TILE; + if (block == HexBlocks.QUENCHED_ALLAY_BRICKS) return QUENCHED_ALLAY_BRICKS_TILE; + if (block == HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL) return QUENCHED_ALLAY_BRICKS_SMALL_TILE; + return null; + } + private static <T extends BlockEntity> BlockEntityType<T> register( + String id, BiFunction<BlockPos, BlockState, T> func, Block... blocks) { + var ret = IXplatAbstractions.INSTANCE.createBlockEntityType(func, blocks); + var old = BLOCK_ENTITIES.put(new ResourceLocation(HexAPI.MOD_ID, id), ret); + if (old != null) { + throw new IllegalArgumentException("Duplicate id " + id); + } + return ret; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexBlockSetTypes.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexBlockSetTypes.java index 64a1cfb45d..4118bca0ea 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexBlockSetTypes.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexBlockSetTypes.java @@ -1,26 +1,23 @@ package at.petrak.hexcasting.common.lib; -import net.minecraft.world.level.block.state.properties.BlockSetType; - import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; +import net.minecraft.world.level.block.state.properties.BlockSetType; public class HexBlockSetTypes { - public static void registerBlocks(Consumer<BlockSetType> r) { - for (var type : TYPES) { - r.accept(type); - } - } + public static void registerBlocks(Consumer<BlockSetType> r) { + for (var type : TYPES) { + r.accept(type); + } + } - private static final List<BlockSetType> TYPES = new ArrayList<>(); + private static final List<BlockSetType> TYPES = new ArrayList<>(); - public static final BlockSetType EDIFIED_WOOD = register( - new BlockSetType("edified_wood") - ); + public static final BlockSetType EDIFIED_WOOD = register(new BlockSetType("edified_wood")); - private static BlockSetType register(BlockSetType type) { - TYPES.add(type); - return type; - } + private static BlockSetType register(BlockSetType type) { + TYPES.add(type); + return type; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexBlocks.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexBlocks.java index 97e58a75e4..68c335aa4b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexBlocks.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexBlocks.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.common.lib; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.block.circle.BlockAbstractImpetus; import at.petrak.hexcasting.common.blocks.BlockConjured; import at.petrak.hexcasting.common.blocks.BlockConjuredLight; @@ -18,6 +20,12 @@ import at.petrak.hexcasting.common.blocks.circles.impetuses.BlockRightClickImpetus; import at.petrak.hexcasting.common.blocks.decoration.*; import com.mojang.datafixers.util.Pair; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.BlockItem; @@ -30,293 +38,334 @@ import net.minecraft.world.level.material.PushReaction; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class HexBlocks { - public static void registerBlocks(BiConsumer<Block, ResourceLocation> r) { - for (var e : BLOCKS.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } - - public static void registerBlockItems(BiConsumer<Item, ResourceLocation> r) { - for (var e : BLOCK_ITEMS.entrySet()) { - r.accept(new BlockItem(e.getValue().getFirst(), e.getValue().getSecond()), e.getKey()); - } - } - - public static void registerBlockCreativeTab(Consumer<Block> r, CreativeModeTab tab) { - for (var block : BLOCK_TABS.getOrDefault(tab, List.of())) { - r.accept(block); - } - } - - private static final Map<ResourceLocation, Block> BLOCKS = new LinkedHashMap<>(); - private static final Map<ResourceLocation, Pair<Block, Item.Properties>> BLOCK_ITEMS = new LinkedHashMap<>(); - private static final Map<CreativeModeTab, List<Block>> BLOCK_TABS = new LinkedHashMap<>(); - - - private static BlockBehaviour.Properties slateish() { - return BlockBehaviour.Properties - .copy(Blocks.DEEPSLATE_TILES) - .strength(4f, 4f); - } - - private static BlockBehaviour.Properties papery(MapColor color) { - return BlockBehaviour.Properties - .of() - .mapColor(color) - .sound(SoundType.GRASS) - .instabreak() - .ignitedByLava() - .pushReaction(PushReaction.DESTROY); - } - - private static BlockBehaviour.Properties akashicWoodyHard() { - return woodyHard(MapColor.COLOR_PURPLE); - } - - private static BlockBehaviour.Properties woodyHard(MapColor color) { - return BlockBehaviour.Properties - .copy(Blocks.OAK_LOG) - .mapColor(color) - .sound(SoundType.WOOD) - .strength(3f, 4f); - } - - private static BlockBehaviour.Properties edifiedWoody() { - return woody(MapColor.COLOR_PURPLE); - } - - private static BlockBehaviour.Properties woody(MapColor color) { - return BlockBehaviour.Properties - .copy(Blocks.OAK_LOG) - .mapColor(color) - .sound(SoundType.WOOD) - .strength(2f); - } - - private static BlockBehaviour.Properties leaves(MapColor color) { - return BlockBehaviour.Properties - .copy(Blocks.OAK_LEAVES) - .strength(0.2F) - .randomTicks() - .sound(SoundType.GRASS) - .noOcclusion() - .isValidSpawn((bs, level, pos, type) -> type == EntityType.OCELOT || type == EntityType.PARROT) - .isSuffocating(HexBlocks::never) - .isViewBlocking(HexBlocks::never); - } - - // we have to make it emit light because otherwise it occludes itself and is always dark - private static BlockBehaviour.Properties quenched() { - return BlockBehaviour.Properties - .copy(Blocks.AMETHYST_BLOCK) - .lightLevel($ -> 4) - .noOcclusion(); - } - - // we give these faux items so Patchi can have an item to view with - public static final Block CONJURED_LIGHT = blockItem("conjured_light", - new BlockConjuredLight( - BlockBehaviour.Properties.of() - .mapColor(MapColor.NONE) - .sound(SoundType.AMETHYST) - .lightLevel((state) -> 15) - .noLootTable() - .isValidSpawn(HexBlocks::never) - .instabreak() - .pushReaction(PushReaction.DESTROY) - .noCollission() - .isSuffocating(HexBlocks::never) - .isViewBlocking(HexBlocks::never)), - new Item.Properties()); - public static final Block CONJURED_BLOCK = blockItem("conjured_block", - new BlockConjured( - BlockBehaviour.Properties.of() - .mapColor(MapColor.NONE) - .sound(SoundType.AMETHYST) - .lightLevel((state) -> 2) - .noLootTable() - .isValidSpawn(HexBlocks::never) - .instabreak() - .noOcclusion() - .isSuffocating(HexBlocks::never) - .isViewBlocking(HexBlocks::never)), - new Item.Properties()); - - // "no" item because we add it manually - public static final BlockSlate SLATE = blockNoItem("slate", - new BlockSlate(slateish() - .pushReaction(PushReaction.DESTROY))); - - public static final BlockEmptyImpetus IMPETUS_EMPTY = blockItem("impetus/empty", - new BlockEmptyImpetus(slateish() - .pushReaction(PushReaction.BLOCK))); - public static final BlockRightClickImpetus IMPETUS_RIGHTCLICK = blockItem("impetus/rightclick", - new BlockRightClickImpetus(slateish() - .pushReaction(PushReaction.BLOCK) - .lightLevel(bs -> bs.getValue(BlockAbstractImpetus.ENERGIZED) ? 15 : 0))); - public static final BlockLookingImpetus IMPETUS_LOOK = blockItem("impetus/look", - new BlockLookingImpetus(slateish() - .pushReaction(PushReaction.BLOCK) - .lightLevel(bs -> bs.getValue(BlockAbstractImpetus.ENERGIZED) ? 15 : 0))); - public static final BlockRedstoneImpetus IMPETUS_REDSTONE = blockItem("impetus/redstone", - new BlockRedstoneImpetus(slateish() - .pushReaction(PushReaction.BLOCK) - .lightLevel(bs -> bs.getValue(BlockAbstractImpetus.ENERGIZED) ? 15 : 0))); - - - public static final BlockEmptyDirectrix EMPTY_DIRECTRIX = blockItem("directrix/empty", - new BlockEmptyDirectrix(slateish() - .pushReaction(PushReaction.BLOCK))); - public static final BlockRedstoneDirectrix DIRECTRIX_REDSTONE = blockItem("directrix/redstone", - new BlockRedstoneDirectrix(slateish() - .pushReaction(PushReaction.BLOCK))); - public static final BlockBooleanDirectrix DIRECTRIX_BOOLEAN = blockItem("directrix/boolean", - new BlockBooleanDirectrix(slateish() - .pushReaction(PushReaction.BLOCK))); - - public static final BlockAkashicRecord AKASHIC_RECORD = blockItem("akashic_record", - new BlockAkashicRecord(akashicWoodyHard().lightLevel(bs -> 15))); - public static final BlockAkashicBookshelf AKASHIC_BOOKSHELF = blockItem("akashic_bookshelf", - new BlockAkashicBookshelf(akashicWoodyHard() - .lightLevel(bs -> (bs.getValue(BlockAkashicBookshelf.HAS_BOOKS)) ? 4 : 0))); - public static final BlockAkashicLigature AKASHIC_LIGATURE = blockItem("akashic_connector", - new BlockAkashicLigature(akashicWoodyHard().lightLevel(bs -> 4))); - - public static final BlockQuenchedAllay QUENCHED_ALLAY = blockItem("quenched_allay", new BlockQuenchedAllay(quenched())); - - // Decoration?! - public static final BlockQuenchedAllay QUENCHED_ALLAY_TILES = blockItem("quenched_allay_tiles", new BlockQuenchedAllay(quenched())); - public static final BlockQuenchedAllay QUENCHED_ALLAY_BRICKS = blockItem("quenched_allay_bricks", new BlockQuenchedAllay(quenched())); - public static final BlockQuenchedAllay QUENCHED_ALLAY_BRICKS_SMALL = blockItem("quenched_allay_bricks_small", new BlockQuenchedAllay(quenched())); - public static final Block SLATE_BLOCK = blockItem("slate_block", new Block(slateish().strength(2f, 4f))); - public static final Block SLATE_TILES = blockItem("slate_tiles", new Block(slateish().strength(2f, 4f))); - public static final Block SLATE_BRICKS = blockItem("slate_bricks", new Block(slateish().strength(2f, 4f))); - public static final Block SLATE_BRICKS_SMALL = blockItem("slate_bricks_small", new Block(slateish().strength(2f, 4f))); - public static final RotatedPillarBlock SLATE_PILLAR = blockItem("slate_pillar", new RotatedPillarBlock(slateish().strength(2f, 4f))); - public static final SandBlock AMETHYST_DUST_BLOCK = blockItem("amethyst_dust_block", - new SandBlock(0xff_b38ef3, BlockBehaviour.Properties.copy(Blocks.SAND).mapColor(MapColor.COLOR_PURPLE) - .strength(0.5f).sound(SoundType.SAND))); - public static final AmethystBlock AMETHYST_TILES = blockItem("amethyst_tiles", - new AmethystBlock(BlockBehaviour.Properties.copy(Blocks.AMETHYST_BLOCK))); - public static final AmethystBlock AMETHYST_BRICKS = blockItem("amethyst_bricks", - new AmethystBlock(BlockBehaviour.Properties.copy(Blocks.AMETHYST_BLOCK))); - public static final AmethystBlock AMETHYST_BRICKS_SMALL = blockItem("amethyst_bricks_small", - new AmethystBlock(BlockBehaviour.Properties.copy(Blocks.AMETHYST_BLOCK))); - public static final BlockAmethystDirectional AMETHYST_PILLAR = blockItem("amethyst_pillar", - new BlockAmethystDirectional(BlockBehaviour.Properties.copy(Blocks.AMETHYST_BLOCK))); - public static final Block SLATE_AMETHYST_TILES = blockItem("slate_amethyst_tiles", new Block(slateish().strength(2f, 4f))); - public static final Block SLATE_AMETHYST_BRICKS = blockItem("slate_amethyst_bricks", new Block(slateish().strength(2f, 4f))); - public static final Block SLATE_AMETHYST_BRICKS_SMALL = blockItem("slate_amethyst_bricks_small", new Block(slateish().strength(2f, 4f))); - public static final RotatedPillarBlock SLATE_AMETHYST_PILLAR = blockItem("slate_amethyst_pillar", - new RotatedPillarBlock(slateish().strength(2f, 4f))); - public static final Block SCROLL_PAPER = blockItem("scroll_paper", - new BlockFlammable(papery(MapColor.TERRACOTTA_WHITE), 100, 60)); - public static final Block ANCIENT_SCROLL_PAPER = blockItem("ancient_scroll_paper", - new BlockFlammable(papery(MapColor.TERRACOTTA_ORANGE), 100, 60)); - public static final Block SCROLL_PAPER_LANTERN = blockItem("scroll_paper_lantern", - new BlockFlammable(papery(MapColor.TERRACOTTA_WHITE).lightLevel($ -> 15), 100, 60)); - public static final Block ANCIENT_SCROLL_PAPER_LANTERN = blockItem( - "ancient_scroll_paper_lantern", - new BlockFlammable(papery(MapColor.TERRACOTTA_ORANGE).lightLevel($ -> 12), 100, 60)); - public static final BlockSconce SCONCE = blockItem("amethyst_sconce", - new BlockSconce(BlockBehaviour.Properties.of() - .mapColor(MapColor.COLOR_PURPLE) - .sound(SoundType.AMETHYST) - .strength(1f) - .lightLevel($ -> 15)), - HexItems.props().rarity(Rarity.RARE)); - - public static final BlockAkashicLog EDIFIED_LOG = blockItem("edified_log", - new BlockAkashicLog(edifiedWoody())); - public static final BlockAkashicLog EDIFIED_LOG_AMETHYST = blockItem("edified_log_amethyst", - new BlockAkashicLog(edifiedWoody())); - public static final BlockAkashicLog EDIFIED_LOG_AVENTURINE = blockItem("edified_log_aventurine", - new BlockAkashicLog(edifiedWoody())); - public static final BlockAkashicLog EDIFIED_LOG_CITRINE = blockItem("edified_log_citrine", - new BlockAkashicLog(edifiedWoody())); - public static final BlockAkashicLog EDIFIED_LOG_PURPLE = blockItem("edified_log_purple", - new BlockAkashicLog(edifiedWoody())); - public static final BlockAkashicLog STRIPPED_EDIFIED_LOG = blockItem("stripped_edified_log", - new BlockAkashicLog(edifiedWoody())); - public static final BlockAkashicLog EDIFIED_WOOD = blockItem("edified_wood", - new BlockAkashicLog(edifiedWoody())); - public static final BlockAkashicLog STRIPPED_EDIFIED_WOOD = blockItem("stripped_edified_wood", - new BlockAkashicLog(edifiedWoody())); - public static final Block EDIFIED_PLANKS = blockItem("edified_planks", - new BlockFlammable(edifiedWoody(), 20, 5)); - public static final Block EDIFIED_PANEL = blockItem("edified_panel", - new BlockFlammable(edifiedWoody(), 20, 5)); - public static final Block EDIFIED_TILE = blockItem("edified_tile", - new BlockFlammable(edifiedWoody(), 20, 5)); - public static final DoorBlock EDIFIED_DOOR = blockItem("edified_door", - new BlockHexDoor(edifiedWoody().noOcclusion())); - public static final TrapDoorBlock EDIFIED_TRAPDOOR = blockItem("edified_trapdoor", - new BlockHexTrapdoor(edifiedWoody().noOcclusion())); - public static final StairBlock EDIFIED_STAIRS = blockItem("edified_stairs", - new BlockHexStairs(EDIFIED_PLANKS.defaultBlockState(), edifiedWoody().noOcclusion())); - - public static final FenceBlock EDIFIED_FENCE = blockItem("edified_fence", - new BlockHexFence(edifiedWoody().noOcclusion())); - public static final FenceGateBlock EDIFIED_FENCE_GATE = blockItem("edified_fence_gate", - new BlockHexFenceGate(edifiedWoody().noOcclusion())); - - public static final SlabBlock EDIFIED_SLAB = blockItem("edified_slab", - new BlockHexSlab(edifiedWoody().noOcclusion())); - public static final ButtonBlock EDIFIED_BUTTON = blockItem("edified_button", - new BlockHexWoodButton(edifiedWoody().noOcclusion().noCollission())); - public static final PressurePlateBlock EDIFIED_PRESSURE_PLATE = blockItem("edified_pressure_plate", - new BlockHexPressurePlate(PressurePlateBlock.Sensitivity.EVERYTHING, - edifiedWoody().noOcclusion().noCollission())); - public static final BlockAkashicLeaves AMETHYST_EDIFIED_LEAVES = blockItem("amethyst_edified_leaves", - new BlockAkashicLeaves(leaves(MapColor.COLOR_PURPLE))); - public static final BlockAkashicLeaves AVENTURINE_EDIFIED_LEAVES = blockItem("aventurine_edified_leaves", - new BlockAkashicLeaves(leaves(MapColor.COLOR_BLUE))); - public static final BlockAkashicLeaves CITRINE_EDIFIED_LEAVES = blockItem("citrine_edified_leaves", - new BlockAkashicLeaves(leaves(MapColor.COLOR_YELLOW))); - - private static boolean never(Object... args) { - return false; - } - - private static <T extends Block> T blockNoItem(String name, T block) { - var old = BLOCKS.put(modLoc(name), block); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + name); - } - return block; - } - private static <T extends Block> T blockItem(String name, T block) { - return blockItem(name, block, HexItems.props(), HexCreativeTabs.HEX); - } - - private static <T extends Block> T blockItem(String name, T block, @Nullable CreativeModeTab tab) { - return blockItem(name, block, HexItems.props(), tab); - } - private static <T extends Block> T blockItem(String name, T block, Item.Properties props) { - return blockItem(name, block, props, HexCreativeTabs.HEX); - } - - private static <T extends Block> T blockItem(String name, T block, Item.Properties props, @Nullable CreativeModeTab tab) { - blockNoItem(name, block); - var old = BLOCK_ITEMS.put(modLoc(name), new Pair<>(block, props)); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + name); - } - if (tab != null) { - BLOCK_TABS.computeIfAbsent(tab, t -> new ArrayList<>()).add(block); - } - return block; - } + public static void registerBlocks(BiConsumer<Block, ResourceLocation> r) { + for (var e : BLOCKS.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } + + public static void registerBlockItems(BiConsumer<Item, ResourceLocation> r) { + for (var e : BLOCK_ITEMS.entrySet()) { + r.accept(new BlockItem(e.getValue().getFirst(), e.getValue().getSecond()), e.getKey()); + } + } + + public static void registerBlockCreativeTab(Consumer<Block> r, CreativeModeTab tab) { + for (var block : BLOCK_TABS.getOrDefault(tab, List.of())) { + r.accept(block); + } + } + + private static final Map<ResourceLocation, Block> BLOCKS = new LinkedHashMap<>(); + private static final Map<ResourceLocation, Pair<Block, Item.Properties>> BLOCK_ITEMS = + new LinkedHashMap<>(); + private static final Map<CreativeModeTab, List<Block>> BLOCK_TABS = new LinkedHashMap<>(); + + private static BlockBehaviour.Properties slateish() { + return BlockBehaviour.Properties.copy(Blocks.DEEPSLATE_TILES).strength(4f, 4f); + } + + private static BlockBehaviour.Properties papery(MapColor color) { + return BlockBehaviour.Properties.of() + .mapColor(color) + .sound(SoundType.GRASS) + .instabreak() + .ignitedByLava() + .pushReaction(PushReaction.DESTROY); + } + + private static BlockBehaviour.Properties akashicWoodyHard() { + return woodyHard(MapColor.COLOR_PURPLE); + } + + private static BlockBehaviour.Properties woodyHard(MapColor color) { + return BlockBehaviour.Properties.copy(Blocks.OAK_LOG) + .mapColor(color) + .sound(SoundType.WOOD) + .strength(3f, 4f); + } + + private static BlockBehaviour.Properties edifiedWoody() { + return woody(MapColor.COLOR_PURPLE); + } + + private static BlockBehaviour.Properties woody(MapColor color) { + return BlockBehaviour.Properties.copy(Blocks.OAK_LOG) + .mapColor(color) + .sound(SoundType.WOOD) + .strength(2f); + } + + private static BlockBehaviour.Properties leaves(MapColor color) { + return BlockBehaviour.Properties.copy(Blocks.OAK_LEAVES) + .strength(0.2F) + .randomTicks() + .sound(SoundType.GRASS) + .noOcclusion() + .isValidSpawn( + (bs, level, pos, type) -> type == EntityType.OCELOT || type == EntityType.PARROT) + .isSuffocating(HexBlocks::never) + .isViewBlocking(HexBlocks::never); + } + + // we have to make it emit light because otherwise it occludes itself and is always dark + private static BlockBehaviour.Properties quenched() { + return BlockBehaviour.Properties.copy(Blocks.AMETHYST_BLOCK).lightLevel($ -> 4).noOcclusion(); + } + + // we give these faux items so Patchi can have an item to view with + public static final Block CONJURED_LIGHT = + blockItem( + "conjured_light", + new BlockConjuredLight( + BlockBehaviour.Properties.of() + .mapColor(MapColor.NONE) + .sound(SoundType.AMETHYST) + .lightLevel((state) -> 15) + .noLootTable() + .isValidSpawn(HexBlocks::never) + .instabreak() + .pushReaction(PushReaction.DESTROY) + .noCollission() + .isSuffocating(HexBlocks::never) + .isViewBlocking(HexBlocks::never)), + new Item.Properties()); + public static final Block CONJURED_BLOCK = + blockItem( + "conjured_block", + new BlockConjured( + BlockBehaviour.Properties.of() + .mapColor(MapColor.NONE) + .sound(SoundType.AMETHYST) + .lightLevel((state) -> 2) + .noLootTable() + .isValidSpawn(HexBlocks::never) + .instabreak() + .noOcclusion() + .isSuffocating(HexBlocks::never) + .isViewBlocking(HexBlocks::never)), + new Item.Properties()); + + // "no" item because we add it manually + public static final BlockSlate SLATE = + blockNoItem("slate", new BlockSlate(slateish().pushReaction(PushReaction.DESTROY))); + + public static final BlockEmptyImpetus IMPETUS_EMPTY = + blockItem( + "impetus/empty", new BlockEmptyImpetus(slateish().pushReaction(PushReaction.BLOCK))); + public static final BlockRightClickImpetus IMPETUS_RIGHTCLICK = + blockItem( + "impetus/rightclick", + new BlockRightClickImpetus( + slateish() + .pushReaction(PushReaction.BLOCK) + .lightLevel(bs -> bs.getValue(BlockAbstractImpetus.ENERGIZED) ? 15 : 0))); + public static final BlockLookingImpetus IMPETUS_LOOK = + blockItem( + "impetus/look", + new BlockLookingImpetus( + slateish() + .pushReaction(PushReaction.BLOCK) + .lightLevel(bs -> bs.getValue(BlockAbstractImpetus.ENERGIZED) ? 15 : 0))); + public static final BlockRedstoneImpetus IMPETUS_REDSTONE = + blockItem( + "impetus/redstone", + new BlockRedstoneImpetus( + slateish() + .pushReaction(PushReaction.BLOCK) + .lightLevel(bs -> bs.getValue(BlockAbstractImpetus.ENERGIZED) ? 15 : 0))); + + public static final BlockEmptyDirectrix EMPTY_DIRECTRIX = + blockItem( + "directrix/empty", new BlockEmptyDirectrix(slateish().pushReaction(PushReaction.BLOCK))); + public static final BlockRedstoneDirectrix DIRECTRIX_REDSTONE = + blockItem( + "directrix/redstone", + new BlockRedstoneDirectrix(slateish().pushReaction(PushReaction.BLOCK))); + public static final BlockBooleanDirectrix DIRECTRIX_BOOLEAN = + blockItem( + "directrix/boolean", + new BlockBooleanDirectrix(slateish().pushReaction(PushReaction.BLOCK))); + + public static final BlockAkashicRecord AKASHIC_RECORD = + blockItem("akashic_record", new BlockAkashicRecord(akashicWoodyHard().lightLevel(bs -> 15))); + public static final BlockAkashicBookshelf AKASHIC_BOOKSHELF = + blockItem( + "akashic_bookshelf", + new BlockAkashicBookshelf( + akashicWoodyHard() + .lightLevel(bs -> (bs.getValue(BlockAkashicBookshelf.HAS_BOOKS)) ? 4 : 0))); + public static final BlockAkashicLigature AKASHIC_LIGATURE = + blockItem( + "akashic_connector", new BlockAkashicLigature(akashicWoodyHard().lightLevel(bs -> 4))); + + public static final BlockQuenchedAllay QUENCHED_ALLAY = + blockItem("quenched_allay", new BlockQuenchedAllay(quenched())); + + // Decoration?! + public static final BlockQuenchedAllay QUENCHED_ALLAY_TILES = + blockItem("quenched_allay_tiles", new BlockQuenchedAllay(quenched())); + public static final BlockQuenchedAllay QUENCHED_ALLAY_BRICKS = + blockItem("quenched_allay_bricks", new BlockQuenchedAllay(quenched())); + public static final BlockQuenchedAllay QUENCHED_ALLAY_BRICKS_SMALL = + blockItem("quenched_allay_bricks_small", new BlockQuenchedAllay(quenched())); + public static final Block SLATE_BLOCK = + blockItem("slate_block", new Block(slateish().strength(2f, 4f))); + public static final Block SLATE_TILES = + blockItem("slate_tiles", new Block(slateish().strength(2f, 4f))); + public static final Block SLATE_BRICKS = + blockItem("slate_bricks", new Block(slateish().strength(2f, 4f))); + public static final Block SLATE_BRICKS_SMALL = + blockItem("slate_bricks_small", new Block(slateish().strength(2f, 4f))); + public static final RotatedPillarBlock SLATE_PILLAR = + blockItem("slate_pillar", new RotatedPillarBlock(slateish().strength(2f, 4f))); + public static final SandBlock AMETHYST_DUST_BLOCK = + blockItem( + "amethyst_dust_block", + new SandBlock( + 0xff_b38ef3, + BlockBehaviour.Properties.copy(Blocks.SAND) + .mapColor(MapColor.COLOR_PURPLE) + .strength(0.5f) + .sound(SoundType.SAND))); + public static final AmethystBlock AMETHYST_TILES = + blockItem( + "amethyst_tiles", + new AmethystBlock(BlockBehaviour.Properties.copy(Blocks.AMETHYST_BLOCK))); + public static final AmethystBlock AMETHYST_BRICKS = + blockItem( + "amethyst_bricks", + new AmethystBlock(BlockBehaviour.Properties.copy(Blocks.AMETHYST_BLOCK))); + public static final AmethystBlock AMETHYST_BRICKS_SMALL = + blockItem( + "amethyst_bricks_small", + new AmethystBlock(BlockBehaviour.Properties.copy(Blocks.AMETHYST_BLOCK))); + public static final BlockAmethystDirectional AMETHYST_PILLAR = + blockItem( + "amethyst_pillar", + new BlockAmethystDirectional(BlockBehaviour.Properties.copy(Blocks.AMETHYST_BLOCK))); + public static final Block SLATE_AMETHYST_TILES = + blockItem("slate_amethyst_tiles", new Block(slateish().strength(2f, 4f))); + public static final Block SLATE_AMETHYST_BRICKS = + blockItem("slate_amethyst_bricks", new Block(slateish().strength(2f, 4f))); + public static final Block SLATE_AMETHYST_BRICKS_SMALL = + blockItem("slate_amethyst_bricks_small", new Block(slateish().strength(2f, 4f))); + public static final RotatedPillarBlock SLATE_AMETHYST_PILLAR = + blockItem("slate_amethyst_pillar", new RotatedPillarBlock(slateish().strength(2f, 4f))); + public static final Block SCROLL_PAPER = + blockItem("scroll_paper", new BlockFlammable(papery(MapColor.TERRACOTTA_WHITE), 100, 60)); + public static final Block ANCIENT_SCROLL_PAPER = + blockItem( + "ancient_scroll_paper", new BlockFlammable(papery(MapColor.TERRACOTTA_ORANGE), 100, 60)); + public static final Block SCROLL_PAPER_LANTERN = + blockItem( + "scroll_paper_lantern", + new BlockFlammable(papery(MapColor.TERRACOTTA_WHITE).lightLevel($ -> 15), 100, 60)); + public static final Block ANCIENT_SCROLL_PAPER_LANTERN = + blockItem( + "ancient_scroll_paper_lantern", + new BlockFlammable(papery(MapColor.TERRACOTTA_ORANGE).lightLevel($ -> 12), 100, 60)); + public static final BlockSconce SCONCE = + blockItem( + "amethyst_sconce", + new BlockSconce( + BlockBehaviour.Properties.of() + .mapColor(MapColor.COLOR_PURPLE) + .sound(SoundType.AMETHYST) + .strength(1f) + .lightLevel($ -> 15)), + HexItems.props().rarity(Rarity.RARE)); + + public static final BlockAkashicLog EDIFIED_LOG = + blockItem("edified_log", new BlockAkashicLog(edifiedWoody())); + public static final BlockAkashicLog EDIFIED_LOG_AMETHYST = + blockItem("edified_log_amethyst", new BlockAkashicLog(edifiedWoody())); + public static final BlockAkashicLog EDIFIED_LOG_AVENTURINE = + blockItem("edified_log_aventurine", new BlockAkashicLog(edifiedWoody())); + public static final BlockAkashicLog EDIFIED_LOG_CITRINE = + blockItem("edified_log_citrine", new BlockAkashicLog(edifiedWoody())); + public static final BlockAkashicLog EDIFIED_LOG_PURPLE = + blockItem("edified_log_purple", new BlockAkashicLog(edifiedWoody())); + public static final BlockAkashicLog STRIPPED_EDIFIED_LOG = + blockItem("stripped_edified_log", new BlockAkashicLog(edifiedWoody())); + public static final BlockAkashicLog EDIFIED_WOOD = + blockItem("edified_wood", new BlockAkashicLog(edifiedWoody())); + public static final BlockAkashicLog STRIPPED_EDIFIED_WOOD = + blockItem("stripped_edified_wood", new BlockAkashicLog(edifiedWoody())); + public static final Block EDIFIED_PLANKS = + blockItem("edified_planks", new BlockFlammable(edifiedWoody(), 20, 5)); + public static final Block EDIFIED_PANEL = + blockItem("edified_panel", new BlockFlammable(edifiedWoody(), 20, 5)); + public static final Block EDIFIED_TILE = + blockItem("edified_tile", new BlockFlammable(edifiedWoody(), 20, 5)); + public static final DoorBlock EDIFIED_DOOR = + blockItem("edified_door", new BlockHexDoor(edifiedWoody().noOcclusion())); + public static final TrapDoorBlock EDIFIED_TRAPDOOR = + blockItem("edified_trapdoor", new BlockHexTrapdoor(edifiedWoody().noOcclusion())); + public static final StairBlock EDIFIED_STAIRS = + blockItem( + "edified_stairs", + new BlockHexStairs(EDIFIED_PLANKS.defaultBlockState(), edifiedWoody().noOcclusion())); + + public static final FenceBlock EDIFIED_FENCE = + blockItem("edified_fence", new BlockHexFence(edifiedWoody().noOcclusion())); + public static final FenceGateBlock EDIFIED_FENCE_GATE = + blockItem("edified_fence_gate", new BlockHexFenceGate(edifiedWoody().noOcclusion())); + + public static final SlabBlock EDIFIED_SLAB = + blockItem("edified_slab", new BlockHexSlab(edifiedWoody().noOcclusion())); + public static final ButtonBlock EDIFIED_BUTTON = + blockItem( + "edified_button", new BlockHexWoodButton(edifiedWoody().noOcclusion().noCollission())); + public static final PressurePlateBlock EDIFIED_PRESSURE_PLATE = + blockItem( + "edified_pressure_plate", + new BlockHexPressurePlate( + PressurePlateBlock.Sensitivity.EVERYTHING, + edifiedWoody().noOcclusion().noCollission())); + public static final BlockAkashicLeaves AMETHYST_EDIFIED_LEAVES = + blockItem("amethyst_edified_leaves", new BlockAkashicLeaves(leaves(MapColor.COLOR_PURPLE))); + public static final BlockAkashicLeaves AVENTURINE_EDIFIED_LEAVES = + blockItem("aventurine_edified_leaves", new BlockAkashicLeaves(leaves(MapColor.COLOR_BLUE))); + public static final BlockAkashicLeaves CITRINE_EDIFIED_LEAVES = + blockItem("citrine_edified_leaves", new BlockAkashicLeaves(leaves(MapColor.COLOR_YELLOW))); + + private static boolean never(Object... args) { + return false; + } + + private static <T extends Block> T blockNoItem(String name, T block) { + var old = BLOCKS.put(modLoc(name), block); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + name); + } + return block; + } + + private static <T extends Block> T blockItem(String name, T block) { + return blockItem(name, block, HexItems.props(), HexCreativeTabs.HEX); + } + + private static <T extends Block> T blockItem( + String name, T block, @Nullable CreativeModeTab tab) { + return blockItem(name, block, HexItems.props(), tab); + } + + private static <T extends Block> T blockItem(String name, T block, Item.Properties props) { + return blockItem(name, block, props, HexCreativeTabs.HEX); + } + + private static <T extends Block> T blockItem( + String name, T block, Item.Properties props, @Nullable CreativeModeTab tab) { + blockNoItem(name, block); + var old = BLOCK_ITEMS.put(modLoc(name), new Pair<>(block, props)); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + name); + } + if (tab != null) { + BLOCK_TABS.computeIfAbsent(tab, t -> new ArrayList<>()).add(block); + } + return block; + } } - - diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexCommands.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexCommands.java index 0a4aca8773..a0caa02ad0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexCommands.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexCommands.java @@ -9,14 +9,14 @@ import net.minecraft.commands.Commands; public class HexCommands { - public static void register(CommandDispatcher<CommandSourceStack> dispatcher) { - var mainCmd = Commands.literal("hexcasting"); + public static void register(CommandDispatcher<CommandSourceStack> dispatcher) { + var mainCmd = Commands.literal("hexcasting"); - BrainsweepCommand.add(mainCmd); - ListPerWorldPatternsCommand.add(mainCmd); - RecalcPatternsCommand.add(mainCmd); - PatternTexturesCommand.add(mainCmd); + BrainsweepCommand.add(mainCmd); + ListPerWorldPatternsCommand.add(mainCmd); + RecalcPatternsCommand.add(mainCmd); + PatternTexturesCommand.add(mainCmd); - dispatcher.register(mainCmd); - } + dispatcher.register(mainCmd); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexConfiguredFeatures.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexConfiguredFeatures.java index 05f06de4e8..fefb894ee1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexConfiguredFeatures.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexConfiguredFeatures.java @@ -7,11 +7,15 @@ import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; public class HexConfiguredFeatures { - public static final ResourceKey<ConfiguredFeature<?, ?>> AMETHYST_EDIFIED_TREE = createKey("amethyst_edified_tree"); - public static final ResourceKey<ConfiguredFeature<?, ?>> AVENTURINE_EDIFIED_TREE = createKey("aventurine_edified_tree"); - public static final ResourceKey<ConfiguredFeature<?, ?>> CITRINE_EDIFIED_TREE = createKey("citrine_edified_tree"); + public static final ResourceKey<ConfiguredFeature<?, ?>> AMETHYST_EDIFIED_TREE = + createKey("amethyst_edified_tree"); + public static final ResourceKey<ConfiguredFeature<?, ?>> AVENTURINE_EDIFIED_TREE = + createKey("aventurine_edified_tree"); + public static final ResourceKey<ConfiguredFeature<?, ?>> CITRINE_EDIFIED_TREE = + createKey("citrine_edified_tree"); - private static ResourceKey<ConfiguredFeature<?, ?>> createKey(String name) { - return ResourceKey.create(Registries.CONFIGURED_FEATURE, new ResourceLocation(HexAPI.MOD_ID, name)); - } + private static ResourceKey<ConfiguredFeature<?, ?>> createKey(String name) { + return ResourceKey.create( + Registries.CONFIGURED_FEATURE, new ResourceLocation(HexAPI.MOD_ID, name)); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexCreativeTabs.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexCreativeTabs.java index 93cfd63011..ce29bc952c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexCreativeTabs.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexCreativeTabs.java @@ -1,34 +1,36 @@ package at.petrak.hexcasting.common.lib; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.CreativeModeTab; -import net.minecraft.world.item.ItemStack; +import static at.petrak.hexcasting.api.HexAPI.modLoc; import java.util.LinkedHashMap; import java.util.Map; import java.util.function.BiConsumer; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.ItemStack; public class HexCreativeTabs { - public static void registerCreativeTabs(BiConsumer<CreativeModeTab, ResourceLocation> r) { - for (var e : TABS.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } + public static void registerCreativeTabs(BiConsumer<CreativeModeTab, ResourceLocation> r) { + for (var e : TABS.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } - private static final Map<ResourceLocation, CreativeModeTab> TABS = new LinkedHashMap<>(); + private static final Map<ResourceLocation, CreativeModeTab> TABS = new LinkedHashMap<>(); - public static final CreativeModeTab HEX = register("hexcasting", CreativeModeTab.builder(CreativeModeTab.Row.TOP, 7) - .icon(() -> new ItemStack(HexItems.SPELLBOOK))); + public static final CreativeModeTab HEX = + register( + "hexcasting", + CreativeModeTab.builder(CreativeModeTab.Row.TOP, 7) + .icon(() -> new ItemStack(HexItems.SPELLBOOK))); - private static CreativeModeTab register(String name, CreativeModeTab.Builder tabBuilder) { - var tab = tabBuilder.title(Component.translatable("itemGroup." + name)).build(); - var old = TABS.put(modLoc(name), tab); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + name); - } - return tab; - } + private static CreativeModeTab register(String name, CreativeModeTab.Builder tabBuilder) { + var tab = tabBuilder.title(Component.translatable("itemGroup." + name)).build(); + var old = TABS.put(modLoc(name), tab); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + name); + } + return tab; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java index d0451ec184..a06f83d795 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java @@ -1,21 +1,20 @@ package at.petrak.hexcasting.common.lib; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import net.minecraft.core.registries.Registries; import net.minecraft.data.worldgen.BootstapContext; import net.minecraft.resources.ResourceKey; import net.minecraft.world.damagesource.DamageScaling; import net.minecraft.world.damagesource.DamageType; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class HexDamageTypes { - public static final ResourceKey<DamageType> OVERCAST = ResourceKey.create(Registries.DAMAGE_TYPE, modLoc("overcast")); + public static final ResourceKey<DamageType> OVERCAST = + ResourceKey.create(Registries.DAMAGE_TYPE, modLoc("overcast")); - public static void bootstrap(BootstapContext<DamageType> ctx) { - ctx.register(OVERCAST, new DamageType( - "hexcasting.overcast", - DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER, - 0f - )); - } + public static void bootstrap(BootstapContext<DamageType> ctx) { + ctx.register( + OVERCAST, + new DamageType("hexcasting.overcast", DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER, 0f)); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexFeatureConfigs.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexFeatureConfigs.java index 52be4c646e..35c73e2384 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexFeatureConfigs.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexFeatureConfigs.java @@ -2,7 +2,7 @@ import at.petrak.hexcasting.api.HexAPI; import com.mojang.serialization.JsonOps; -import net.minecraft.server.Bootstrap; +import java.util.OptionalInt; import net.minecraft.util.random.SimpleWeightedRandomList; import net.minecraft.util.valueproviders.ConstantInt; import net.minecraft.world.level.block.Block; @@ -14,36 +14,41 @@ import net.minecraft.world.level.levelgen.feature.stateproviders.WeightedStateProvider; import net.minecraft.world.level.levelgen.feature.trunkplacers.FancyTrunkPlacer; -import java.util.OptionalInt; - public class HexFeatureConfigs { - public static void dumpConfigs() { - // Used to generate the tree data json files - // Call this after the game is properly bootstrapped and copy the output logs to data/hexcasting/worldgen/configured_feature/${name}.json - // This should be done in DataGen, but I was unable to make that function. - dashkal16 - HexAPI.LOGGER.info(TreeConfiguration.CODEC.encodeStart(JsonOps.INSTANCE, AMETHYST_EDIFIED_TREE_CONFIG)); - HexAPI.LOGGER.info(TreeConfiguration.CODEC.encodeStart(JsonOps.INSTANCE, AVENTURINE_EDIFIED_TREE_CONFIG)); - HexAPI.LOGGER.info(TreeConfiguration.CODEC.encodeStart(JsonOps.INSTANCE, CITRINE_EDIFIED_TREE_CONFIG)); - } + public static void dumpConfigs() { + // Used to generate the tree data json files + // Call this after the game is properly bootstrapped and copy the output logs to + // data/hexcasting/worldgen/configured_feature/${name}.json + // This should be done in DataGen, but I was unable to make that function. - dashkal16 + HexAPI.LOGGER.info( + TreeConfiguration.CODEC.encodeStart(JsonOps.INSTANCE, AMETHYST_EDIFIED_TREE_CONFIG)); + HexAPI.LOGGER.info( + TreeConfiguration.CODEC.encodeStart(JsonOps.INSTANCE, AVENTURINE_EDIFIED_TREE_CONFIG)); + HexAPI.LOGGER.info( + TreeConfiguration.CODEC.encodeStart(JsonOps.INSTANCE, CITRINE_EDIFIED_TREE_CONFIG)); + } - public static final TreeConfiguration AMETHYST_EDIFIED_TREE_CONFIG = akashicTree(HexBlocks.AMETHYST_EDIFIED_LEAVES, HexBlocks.EDIFIED_LOG_AMETHYST); - public static final TreeConfiguration AVENTURINE_EDIFIED_TREE_CONFIG = akashicTree(HexBlocks.AVENTURINE_EDIFIED_LEAVES, HexBlocks.EDIFIED_LOG_AVENTURINE); - public static final TreeConfiguration CITRINE_EDIFIED_TREE_CONFIG = akashicTree(HexBlocks.CITRINE_EDIFIED_LEAVES, HexBlocks.EDIFIED_LOG_CITRINE); + public static final TreeConfiguration AMETHYST_EDIFIED_TREE_CONFIG = + akashicTree(HexBlocks.AMETHYST_EDIFIED_LEAVES, HexBlocks.EDIFIED_LOG_AMETHYST); + public static final TreeConfiguration AVENTURINE_EDIFIED_TREE_CONFIG = + akashicTree(HexBlocks.AVENTURINE_EDIFIED_LEAVES, HexBlocks.EDIFIED_LOG_AVENTURINE); + public static final TreeConfiguration CITRINE_EDIFIED_TREE_CONFIG = + akashicTree(HexBlocks.CITRINE_EDIFIED_LEAVES, HexBlocks.EDIFIED_LOG_CITRINE); - private static TreeConfiguration akashicTree(Block leaves, Block altLog) { - return new TreeConfiguration.TreeConfigurationBuilder( - new WeightedStateProvider( - SimpleWeightedRandomList.<BlockState>builder() - .add(HexBlocks.EDIFIED_LOG.defaultBlockState(), 8) - .add(altLog.defaultBlockState(), 1) - .build()), - // baseHeight, heightRandA, heightRandB - new FancyTrunkPlacer(5, 5, 3), - BlockStateProvider.simple(leaves), - // radius, offset, height - new FancyFoliagePlacer(ConstantInt.of(1), ConstantInt.of(5), 5), - // limit, lower size, upper size, minclippedheight - new TwoLayersFeatureSize(0, 0, 0, OptionalInt.of(6)) - ).build(); - } + private static TreeConfiguration akashicTree(Block leaves, Block altLog) { + return new TreeConfiguration.TreeConfigurationBuilder( + new WeightedStateProvider( + SimpleWeightedRandomList.<BlockState>builder() + .add(HexBlocks.EDIFIED_LOG.defaultBlockState(), 8) + .add(altLog.defaultBlockState(), 1) + .build()), + // baseHeight, heightRandA, heightRandB + new FancyTrunkPlacer(5, 5, 3), + BlockStateProvider.simple(leaves), + // radius, offset, height + new FancyFoliagePlacer(ConstantInt.of(1), ConstantInt.of(5), 5), + // limit, lower size, upper size, minclippedheight + new TwoLayersFeatureSize(0, 0, 0, OptionalInt.of(6))) + .build(); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexItems.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexItems.java index a85889e104..aa8354039c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexItems.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexItems.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.common.lib; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.misc.MediaConstants; import at.petrak.hexcasting.common.items.ItemJewelerHammer; import at.petrak.hexcasting.common.items.ItemLens; @@ -13,6 +15,9 @@ import at.petrak.hexcasting.common.items.storage.*; import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.google.common.base.Suppliers; +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Supplier; import net.minecraft.Util; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.EquipmentSlot; @@ -20,193 +25,245 @@ import net.minecraft.world.item.*; import org.jetbrains.annotations.Nullable; -import java.util.*; -import java.util.function.BiConsumer; -import java.util.function.Supplier; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - // https://github.com/VazkiiMods/Botania/blob/2c4f7fdf9ebf0c0afa1406dfe1322841133d75fa/Common/src/main/java/vazkii/botania/common/item/ModItems.java public class HexItems { - public static void registerItems(BiConsumer<Item, ResourceLocation> r) { - for (var e : ITEMS.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } - - public static void registerItemCreativeTab(CreativeModeTab.Output r, CreativeModeTab tab) { - for (var item : ITEM_TABS.getOrDefault(tab, List.of())) { - item.register(r); - } - } - - private static final Map<ResourceLocation, Item> ITEMS = new LinkedHashMap<>(); // preserve insertion order - private static final Map<CreativeModeTab, List<TabEntry>> ITEM_TABS = new LinkedHashMap<>(); - - - public static final Item AMETHYST_DUST = make("amethyst_dust", new Item(props())); - public static final Item CHARGED_AMETHYST = make("charged_amethyst", new Item(props())); - - public static final Item QUENCHED_SHARD = make("quenched_allay_shard", new Item(props())); - - public static final ItemStaff STAFF_OAK = make("staff/oak", new ItemStaff(unstackable())); - public static final ItemStaff STAFF_SPRUCE = make("staff/spruce", new ItemStaff(unstackable())); - public static final ItemStaff STAFF_BIRCH = make("staff/birch", new ItemStaff(unstackable())); - public static final ItemStaff STAFF_JUNGLE = make("staff/jungle", new ItemStaff(unstackable())); - public static final ItemStaff STAFF_ACACIA = make("staff/acacia", new ItemStaff(unstackable())); - public static final ItemStaff STAFF_DARK_OAK = make("staff/dark_oak", new ItemStaff(unstackable())); - public static final ItemStaff STAFF_CRIMSON = make("staff/crimson", new ItemStaff(unstackable())); - public static final ItemStaff STAFF_WARPED = make("staff/warped", new ItemStaff(unstackable())); - public static final ItemStaff STAFF_MANGROVE = make("staff/mangrove", new ItemStaff(unstackable())); - public static final ItemStaff STAFF_CHERRY = make("staff/cherry", new ItemStaff(unstackable())); - public static final ItemStaff STAFF_BAMBOO = make("staff/bamboo", new ItemStaff(unstackable())); - public static final ItemStaff STAFF_EDIFIED = make("staff/edified", new ItemStaff(unstackable())); - public static final ItemStaff STAFF_QUENCHED = make("staff/quenched", new ItemStaff(unstackable())); - // mindsplice staffaratus - public static final ItemStaff STAFF_MINDSPLICE = make("staff/mindsplice", new ItemStaff(unstackable())); - - public static final ItemLens SCRYING_LENS = make("lens", new ItemLens( - IXplatAbstractions.INSTANCE.addEquipSlotFabric(EquipmentSlot.HEAD) - .stacksTo(1))); - - public static final ItemAbacus ABACUS = make("abacus", new ItemAbacus(unstackable())); - public static final ItemThoughtKnot THOUGHT_KNOT = make("thought_knot", new ItemThoughtKnot(unstackable())); - public static final ItemFocus FOCUS = make("focus", new ItemFocus(unstackable())); - public static final ItemSpellbook SPELLBOOK = make("spellbook", new ItemSpellbook(unstackable())); - - public static final ItemCypher CYPHER = make("cypher", new ItemCypher(unstackable())); - public static final ItemTrinket TRINKET = make("trinket", new ItemTrinket(unstackable().rarity(Rarity.UNCOMMON))); - public static final ItemArtifact ARTIFACT = make("artifact", new ItemArtifact(unstackable().rarity(Rarity.RARE))); - - public static final ItemJewelerHammer JEWELER_HAMMER = make("jeweler_hammer", - new ItemJewelerHammer(Tiers.IRON, 0, -2.8F, props().stacksTo(1).defaultDurability(Tiers.DIAMOND.getUses()))); - - public static final ItemScroll SCROLL_SMOL = make("scroll_small", new ItemScroll(props(), 1)); - public static final ItemScroll SCROLL_MEDIUM = make("scroll_medium", new ItemScroll(props(), 2)); - public static final ItemScroll SCROLL_LARGE = make("scroll", new ItemScroll(props(), 3)); - - public static final ItemSlate SLATE = make("slate", new ItemSlate(HexBlocks.SLATE, props())); - - public static final ItemMediaBattery BATTERY = make("battery", - new ItemMediaBattery(unstackable()), null); - - public static final Supplier<ItemStack> BATTERY_DUST_STACK = addToTab(() -> ItemMediaBattery.withMedia( - new ItemStack(HexItems.BATTERY), - MediaConstants.DUST_UNIT * 64, - MediaConstants.DUST_UNIT * 64), HexCreativeTabs.HEX); - public static final Supplier<ItemStack> BATTERY_SHARD_STACK = addToTab(() -> ItemMediaBattery.withMedia( - new ItemStack(HexItems.BATTERY), - MediaConstants.SHARD_UNIT * 64, - MediaConstants.SHARD_UNIT * 64), HexCreativeTabs.HEX); - public static final Supplier<ItemStack> BATTERY_CRYSTAL_STACK = addToTab(() -> ItemMediaBattery.withMedia( - new ItemStack(HexItems.BATTERY), - MediaConstants.CRYSTAL_UNIT * 64, - MediaConstants.CRYSTAL_UNIT * 64), HexCreativeTabs.HEX); - public static final Supplier<ItemStack> BATTERY_QUENCHED_SHARD_STACK = addToTab(() -> ItemMediaBattery.withMedia( - new ItemStack(HexItems.BATTERY), - MediaConstants.QUENCHED_SHARD_UNIT * 64, - MediaConstants.QUENCHED_SHARD_UNIT * 64), HexCreativeTabs.HEX); - - public static final Supplier<ItemStack> BATTERY_QUENCHED_BLOCK_STACK = addToTab(() -> ItemMediaBattery.withMedia( - new ItemStack(HexItems.BATTERY), - MediaConstants.QUENCHED_BLOCK_UNIT * 64, - MediaConstants.QUENCHED_BLOCK_UNIT * 64), HexCreativeTabs.HEX); - - public static final EnumMap<DyeColor, ItemDyePigment> DYE_PIGMENTS = Util.make(() -> { - var out = new EnumMap<DyeColor, ItemDyePigment>(DyeColor.class); - for (var dye : DyeColor.values()) { - out.put(dye, make("dye_colorizer_" + dye.getName(), new ItemDyePigment(dye, unstackable()))); - } - return out; - }); - public static final EnumMap<ItemPridePigment.Type, ItemPridePigment> PRIDE_PIGMENTS = Util.make(() -> { - var out = new EnumMap<ItemPridePigment.Type, ItemPridePigment>(ItemPridePigment.Type.class); - for (var politicsInMyVidya : ItemPridePigment.Type.values()) { - out.put(politicsInMyVidya, make("pride_colorizer_" + politicsInMyVidya.getName(), - new ItemPridePigment(politicsInMyVidya, unstackable()))); - } - return out; - }); - - public static final Item UUID_PIGMENT = make("uuid_colorizer", new ItemUUIDPigment(unstackable())); - public static final Item DEFAULT_PIGMENT = make("default_colorizer", - new ItemAmethystAndCopperPigment(unstackable())); - - // BUFF SANDVICH - public static final Item SUBMARINE_SANDWICH = make("sub_sandwich", - new Item(props().food(new FoodProperties.Builder().nutrition(14).saturationMod(1.2f).build()))); - - public static final ItemLoreFragment LORE_FRAGMENT = make("lore_fragment", - new ItemLoreFragment(unstackable() - .rarity(Rarity.RARE))); - - public static final ItemCreativeUnlocker CREATIVE_UNLOCKER = make("creative_unlocker", - new ItemCreativeUnlocker(unstackable() - .rarity(Rarity.EPIC) - .food(new FoodProperties.Builder().nutrition(20).saturationMod(1f).alwaysEat().build()))); - - // - - public static Item.Properties props() { - return new Item.Properties(); - } - - public static Item.Properties unstackable() { - return props().stacksTo(1); - } - - private static <T extends Item> T make(ResourceLocation id, T item, @Nullable CreativeModeTab tab) { - var old = ITEMS.put(id, item); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + id); - } - if (tab != null) { - ITEM_TABS.computeIfAbsent(tab, t -> new ArrayList<>()).add(new TabEntry.ItemEntry(item)); - } - return item; - } - - private static <T extends Item> T make(String id, T item, @Nullable CreativeModeTab tab) { - return make(modLoc(id), item, tab); - } - - private static <T extends Item> T make(String id, T item) { - return make(modLoc(id), item, HexCreativeTabs.HEX); - } - - private static Supplier<ItemStack> addToTab(Supplier<ItemStack> stack, CreativeModeTab tab) { - var memoised = Suppliers.memoize(stack::get); - ITEM_TABS.computeIfAbsent(tab, t -> new ArrayList<>()).add(new TabEntry.StackEntry(memoised)); - return memoised; - } - - private static abstract class TabEntry { - abstract void register(CreativeModeTab.Output r); - - static class ItemEntry extends TabEntry { - private final Item item; - - ItemEntry(Item item) { - this.item = item; - } - - @Override - void register(CreativeModeTab.Output r) { - r.accept(item); - } - } - - static class StackEntry extends TabEntry { - private final Supplier<ItemStack> stack; - - StackEntry(Supplier<ItemStack> stack) { - this.stack = stack; - } - - @Override - void register(CreativeModeTab.Output r) { - r.accept(stack.get()); - } - } - } + public static void registerItems(BiConsumer<Item, ResourceLocation> r) { + for (var e : ITEMS.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } + + public static void registerItemCreativeTab(CreativeModeTab.Output r, CreativeModeTab tab) { + for (var item : ITEM_TABS.getOrDefault(tab, List.of())) { + item.register(r); + } + } + + private static final Map<ResourceLocation, Item> ITEMS = + new LinkedHashMap<>(); // preserve insertion order + private static final Map<CreativeModeTab, List<TabEntry>> ITEM_TABS = new LinkedHashMap<>(); + + public static final Item AMETHYST_DUST = make("amethyst_dust", new Item(props())); + public static final Item CHARGED_AMETHYST = make("charged_amethyst", new Item(props())); + + public static final Item QUENCHED_SHARD = make("quenched_allay_shard", new Item(props())); + + public static final ItemStaff STAFF_OAK = make("staff/oak", new ItemStaff(unstackable())); + public static final ItemStaff STAFF_SPRUCE = make("staff/spruce", new ItemStaff(unstackable())); + public static final ItemStaff STAFF_BIRCH = make("staff/birch", new ItemStaff(unstackable())); + public static final ItemStaff STAFF_JUNGLE = make("staff/jungle", new ItemStaff(unstackable())); + public static final ItemStaff STAFF_ACACIA = make("staff/acacia", new ItemStaff(unstackable())); + public static final ItemStaff STAFF_DARK_OAK = + make("staff/dark_oak", new ItemStaff(unstackable())); + public static final ItemStaff STAFF_CRIMSON = make("staff/crimson", new ItemStaff(unstackable())); + public static final ItemStaff STAFF_WARPED = make("staff/warped", new ItemStaff(unstackable())); + public static final ItemStaff STAFF_MANGROVE = + make("staff/mangrove", new ItemStaff(unstackable())); + public static final ItemStaff STAFF_CHERRY = make("staff/cherry", new ItemStaff(unstackable())); + public static final ItemStaff STAFF_BAMBOO = make("staff/bamboo", new ItemStaff(unstackable())); + public static final ItemStaff STAFF_EDIFIED = make("staff/edified", new ItemStaff(unstackable())); + public static final ItemStaff STAFF_QUENCHED = + make("staff/quenched", new ItemStaff(unstackable())); + // mindsplice staffaratus + public static final ItemStaff STAFF_MINDSPLICE = + make("staff/mindsplice", new ItemStaff(unstackable())); + + public static final ItemLens SCRYING_LENS = + make( + "lens", + new ItemLens( + IXplatAbstractions.INSTANCE.addEquipSlotFabric(EquipmentSlot.HEAD).stacksTo(1))); + + public static final ItemAbacus ABACUS = make("abacus", new ItemAbacus(unstackable())); + public static final ItemThoughtKnot THOUGHT_KNOT = + make("thought_knot", new ItemThoughtKnot(unstackable())); + public static final ItemFocus FOCUS = make("focus", new ItemFocus(unstackable())); + public static final ItemSpellbook SPELLBOOK = make("spellbook", new ItemSpellbook(unstackable())); + + public static final ItemCypher CYPHER = make("cypher", new ItemCypher(unstackable())); + public static final ItemTrinket TRINKET = + make("trinket", new ItemTrinket(unstackable().rarity(Rarity.UNCOMMON))); + public static final ItemArtifact ARTIFACT = + make("artifact", new ItemArtifact(unstackable().rarity(Rarity.RARE))); + + public static final ItemJewelerHammer JEWELER_HAMMER = + make( + "jeweler_hammer", + new ItemJewelerHammer( + Tiers.IRON, + 0, + -2.8F, + props().stacksTo(1).defaultDurability(Tiers.DIAMOND.getUses()))); + + public static final ItemScroll SCROLL_SMOL = make("scroll_small", new ItemScroll(props(), 1)); + public static final ItemScroll SCROLL_MEDIUM = make("scroll_medium", new ItemScroll(props(), 2)); + public static final ItemScroll SCROLL_LARGE = make("scroll", new ItemScroll(props(), 3)); + + public static final ItemSlate SLATE = make("slate", new ItemSlate(HexBlocks.SLATE, props())); + + public static final ItemMediaBattery BATTERY = + make("battery", new ItemMediaBattery(unstackable()), null); + + public static final Supplier<ItemStack> BATTERY_DUST_STACK = + addToTab( + () -> + ItemMediaBattery.withMedia( + new ItemStack(HexItems.BATTERY), + MediaConstants.DUST_UNIT * 64, + MediaConstants.DUST_UNIT * 64), + HexCreativeTabs.HEX); + public static final Supplier<ItemStack> BATTERY_SHARD_STACK = + addToTab( + () -> + ItemMediaBattery.withMedia( + new ItemStack(HexItems.BATTERY), + MediaConstants.SHARD_UNIT * 64, + MediaConstants.SHARD_UNIT * 64), + HexCreativeTabs.HEX); + public static final Supplier<ItemStack> BATTERY_CRYSTAL_STACK = + addToTab( + () -> + ItemMediaBattery.withMedia( + new ItemStack(HexItems.BATTERY), + MediaConstants.CRYSTAL_UNIT * 64, + MediaConstants.CRYSTAL_UNIT * 64), + HexCreativeTabs.HEX); + public static final Supplier<ItemStack> BATTERY_QUENCHED_SHARD_STACK = + addToTab( + () -> + ItemMediaBattery.withMedia( + new ItemStack(HexItems.BATTERY), + MediaConstants.QUENCHED_SHARD_UNIT * 64, + MediaConstants.QUENCHED_SHARD_UNIT * 64), + HexCreativeTabs.HEX); + + public static final Supplier<ItemStack> BATTERY_QUENCHED_BLOCK_STACK = + addToTab( + () -> + ItemMediaBattery.withMedia( + new ItemStack(HexItems.BATTERY), + MediaConstants.QUENCHED_BLOCK_UNIT * 64, + MediaConstants.QUENCHED_BLOCK_UNIT * 64), + HexCreativeTabs.HEX); + + public static final EnumMap<DyeColor, ItemDyePigment> DYE_PIGMENTS = + Util.make( + () -> { + var out = new EnumMap<DyeColor, ItemDyePigment>(DyeColor.class); + for (var dye : DyeColor.values()) { + out.put( + dye, + make("dye_colorizer_" + dye.getName(), new ItemDyePigment(dye, unstackable()))); + } + return out; + }); + public static final EnumMap<ItemPridePigment.Type, ItemPridePigment> PRIDE_PIGMENTS = + Util.make( + () -> { + var out = + new EnumMap<ItemPridePigment.Type, ItemPridePigment>(ItemPridePigment.Type.class); + for (var politicsInMyVidya : ItemPridePigment.Type.values()) { + out.put( + politicsInMyVidya, + make( + "pride_colorizer_" + politicsInMyVidya.getName(), + new ItemPridePigment(politicsInMyVidya, unstackable()))); + } + return out; + }); + + public static final Item UUID_PIGMENT = + make("uuid_colorizer", new ItemUUIDPigment(unstackable())); + public static final Item DEFAULT_PIGMENT = + make("default_colorizer", new ItemAmethystAndCopperPigment(unstackable())); + + // BUFF SANDVICH + public static final Item SUBMARINE_SANDWICH = + make( + "sub_sandwich", + new Item( + props() + .food(new FoodProperties.Builder().nutrition(14).saturationMod(1.2f).build()))); + + public static final ItemLoreFragment LORE_FRAGMENT = + make("lore_fragment", new ItemLoreFragment(unstackable().rarity(Rarity.RARE))); + + public static final ItemCreativeUnlocker CREATIVE_UNLOCKER = + make( + "creative_unlocker", + new ItemCreativeUnlocker( + unstackable() + .rarity(Rarity.EPIC) + .food( + new FoodProperties.Builder() + .nutrition(20) + .saturationMod(1f) + .alwaysEat() + .build()))); + + // + + public static Item.Properties props() { + return new Item.Properties(); + } + + public static Item.Properties unstackable() { + return props().stacksTo(1); + } + + private static <T extends Item> T make( + ResourceLocation id, T item, @Nullable CreativeModeTab tab) { + var old = ITEMS.put(id, item); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + id); + } + if (tab != null) { + ITEM_TABS.computeIfAbsent(tab, t -> new ArrayList<>()).add(new TabEntry.ItemEntry(item)); + } + return item; + } + + private static <T extends Item> T make(String id, T item, @Nullable CreativeModeTab tab) { + return make(modLoc(id), item, tab); + } + + private static <T extends Item> T make(String id, T item) { + return make(modLoc(id), item, HexCreativeTabs.HEX); + } + + private static Supplier<ItemStack> addToTab(Supplier<ItemStack> stack, CreativeModeTab tab) { + var memoised = Suppliers.memoize(stack::get); + ITEM_TABS.computeIfAbsent(tab, t -> new ArrayList<>()).add(new TabEntry.StackEntry(memoised)); + return memoised; + } + + private abstract static class TabEntry { + abstract void register(CreativeModeTab.Output r); + + static class ItemEntry extends TabEntry { + private final Item item; + + ItemEntry(Item item) { + this.item = item; + } + + @Override + void register(CreativeModeTab.Output r) { + r.accept(item); + } + } + + static class StackEntry extends TabEntry { + private final Supplier<ItemStack> stack; + + StackEntry(Supplier<ItemStack> stack) { + this.stack = stack; + } + + @Override + void register(CreativeModeTab.Output r) { + r.accept(stack.get()); + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexLootFunctions.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexLootFunctions.java index bebc94ad42..7402e9b729 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexLootFunctions.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexLootFunctions.java @@ -1,35 +1,38 @@ package at.petrak.hexcasting.common.lib; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.common.loot.AddPerWorldPatternToScrollFunc; import at.petrak.hexcasting.common.loot.AmethystReducerFunc; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType; - import java.util.LinkedHashMap; import java.util.Map; import java.util.function.BiConsumer; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType; public class HexLootFunctions { - public static void registerSerializers(BiConsumer<LootItemFunctionType, ResourceLocation> r) { - for (var e : LOOT_FUNCS.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } + public static void registerSerializers(BiConsumer<LootItemFunctionType, ResourceLocation> r) { + for (var e : LOOT_FUNCS.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } - private static final Map<ResourceLocation, LootItemFunctionType> LOOT_FUNCS = new LinkedHashMap<>(); + private static final Map<ResourceLocation, LootItemFunctionType> LOOT_FUNCS = + new LinkedHashMap<>(); - public static final LootItemFunctionType PATTERN_SCROLL = register("pattern_scroll", - new LootItemFunctionType(new AddPerWorldPatternToScrollFunc.Serializer())); - public static final LootItemFunctionType AMETHYST_SHARD_REDUCER = register("amethyst_shard_reducer", - new LootItemFunctionType(new AmethystReducerFunc.Serializer())); + public static final LootItemFunctionType PATTERN_SCROLL = + register( + "pattern_scroll", + new LootItemFunctionType(new AddPerWorldPatternToScrollFunc.Serializer())); + public static final LootItemFunctionType AMETHYST_SHARD_REDUCER = + register( + "amethyst_shard_reducer", new LootItemFunctionType(new AmethystReducerFunc.Serializer())); - private static LootItemFunctionType register(String id, LootItemFunctionType lift) { - var old = LOOT_FUNCS.put(modLoc(id), lift); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + id); - } - return lift; - } + private static LootItemFunctionType register(String id, LootItemFunctionType lift) { + var old = LOOT_FUNCS.put(modLoc(id), lift); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + id); + } + return lift; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexMobEffects.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexMobEffects.java index fe1e0499c4..1f0a1bd138 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexMobEffects.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexMobEffects.java @@ -1,41 +1,45 @@ package at.petrak.hexcasting.common.lib; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.common.misc.HexMobEffect; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.BiConsumer; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectCategory; import net.minecraft.world.entity.ai.attributes.AttributeModifier; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.function.BiConsumer; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class HexMobEffects { - public static void register(BiConsumer<MobEffect, ResourceLocation> r) { - for (var e : EFFECTS.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } - - private static final Map<ResourceLocation, MobEffect> EFFECTS = new LinkedHashMap<>(); - - public static final MobEffect ENLARGE_GRID = make("enlarge_grid", - new HexMobEffect(MobEffectCategory.BENEFICIAL, 0xc875ff)) - .addAttributeModifier(HexAttributes.GRID_ZOOM, "d4afaf0f-df37-4253-9fa7-029e8e4415d9", - 0.25, AttributeModifier.Operation.MULTIPLY_TOTAL); - public static final MobEffect SHRINK_GRID = make("shrink_grid", - new HexMobEffect(MobEffectCategory.HARMFUL, 0xebad1c)) - .addAttributeModifier(HexAttributes.GRID_ZOOM, "1ce492a9-8bf5-4091-a482-c6d9399e448a", - -0.2, AttributeModifier.Operation.MULTIPLY_TOTAL); - - - private static <T extends MobEffect> T make(String id, T effect) { - var old = EFFECTS.put(modLoc(id), effect); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + id); - } - return effect; - } + public static void register(BiConsumer<MobEffect, ResourceLocation> r) { + for (var e : EFFECTS.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } + + private static final Map<ResourceLocation, MobEffect> EFFECTS = new LinkedHashMap<>(); + + public static final MobEffect ENLARGE_GRID = + make("enlarge_grid", new HexMobEffect(MobEffectCategory.BENEFICIAL, 0xc875ff)) + .addAttributeModifier( + HexAttributes.GRID_ZOOM, + "d4afaf0f-df37-4253-9fa7-029e8e4415d9", + 0.25, + AttributeModifier.Operation.MULTIPLY_TOTAL); + public static final MobEffect SHRINK_GRID = + make("shrink_grid", new HexMobEffect(MobEffectCategory.HARMFUL, 0xebad1c)) + .addAttributeModifier( + HexAttributes.GRID_ZOOM, + "1ce492a9-8bf5-4091-a482-c6d9399e448a", + -0.2, + AttributeModifier.Operation.MULTIPLY_TOTAL); + + private static <T extends MobEffect> T make(String id, T effect) { + var old = EFFECTS.put(modLoc(id), effect); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + id); + } + return effect; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexParticles.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexParticles.java index 52c538b6f2..f7e2d8b492 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexParticles.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexParticles.java @@ -1,48 +1,48 @@ package at.petrak.hexcasting.common.lib; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.client.particles.ConjureParticle; import at.petrak.hexcasting.common.particles.ConjureParticleOptions; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Function; import net.minecraft.client.particle.ParticleProvider; import net.minecraft.client.particle.SpriteSet; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleType; import net.minecraft.resources.ResourceLocation; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.Function; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class HexParticles { - public static void registerParticles(BiConsumer<ParticleType<?>, ResourceLocation> r) { - for (var e : PARTICLES.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } - - private static final Map<ResourceLocation, ParticleType<?>> PARTICLES = new LinkedHashMap<>(); - - public static final ConjureParticleOptions.Type CONJURE_PARTICLE = register( - "conjure_particle", new ConjureParticleOptions.Type(false)); - - private static <O extends ParticleOptions, T extends ParticleType<O>> T register(String id, T particle) { - var old = PARTICLES.put(modLoc(id), particle); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + id); - } - return particle; - } - - public static class FactoryHandler { - public interface Consumer { - <T extends ParticleOptions> void register(ParticleType<T> type, - Function<SpriteSet, ParticleProvider<T>> constructor); - } - - public static void registerFactories(Consumer consumer) { - consumer.register(CONJURE_PARTICLE, ConjureParticle.Provider::new); - } - } + public static void registerParticles(BiConsumer<ParticleType<?>, ResourceLocation> r) { + for (var e : PARTICLES.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } + + private static final Map<ResourceLocation, ParticleType<?>> PARTICLES = new LinkedHashMap<>(); + + public static final ConjureParticleOptions.Type CONJURE_PARTICLE = + register("conjure_particle", new ConjureParticleOptions.Type(false)); + + private static <O extends ParticleOptions, T extends ParticleType<O>> T register( + String id, T particle) { + var old = PARTICLES.put(modLoc(id), particle); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + id); + } + return particle; + } + + public static class FactoryHandler { + public interface Consumer { + <T extends ParticleOptions> void register( + ParticleType<T> type, Function<SpriteSet, ParticleProvider<T>> constructor); + } + + public static void registerFactories(Consumer consumer) { + consumer.register(CONJURE_PARTICLE, ConjureParticle.Provider::new); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexPotions.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexPotions.java index f970235b5d..ca1eac3bb4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexPotions.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexPotions.java @@ -1,44 +1,50 @@ package at.petrak.hexcasting.common.lib; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.item.alchemy.Potion; +import static at.petrak.hexcasting.api.HexAPI.modLoc; import java.util.LinkedHashMap; import java.util.Map; import java.util.function.BiConsumer; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.item.alchemy.Potion; public class HexPotions { - public static void register(BiConsumer<Potion, ResourceLocation> r) { - for (var e : POTIONS.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } - - private static final Map<ResourceLocation, Potion> POTIONS = new LinkedHashMap<>(); - - public static final Potion ENLARGE_GRID = make("enlarge_grid", - new Potion("enlarge_grid", new MobEffectInstance(HexMobEffects.ENLARGE_GRID, 3600))); - public static final Potion ENLARGE_GRID_LONG = make("enlarge_grid_long", - new Potion("enlarge_grid_long", new MobEffectInstance(HexMobEffects.ENLARGE_GRID, 9600))); - public static final Potion ENLARGE_GRID_STRONG = make("enlarge_grid_strong", - new Potion("enlarge_grid_strong", new MobEffectInstance(HexMobEffects.ENLARGE_GRID, 1800, 1))); - - public static void addRecipes() { - /* - AccessorPotionBrewing.addMix(Potions.AWKWARD, HexItems.AMETHYST_DUST, ENLARGE_GRID); - AccessorPotionBrewing.addMix(ENLARGE_GRID, Items.REDSTONE, ENLARGE_GRID_LONG); - AccessorPotionBrewing.addMix(ENLARGE_GRID, Items.GLOWSTONE_DUST, ENLARGE_GRID_STRONG); - */ - } - - private static <T extends Potion> T make(String id, T potion) { - var old = POTIONS.put(modLoc(id), potion); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + id); - } - return potion; - } + public static void register(BiConsumer<Potion, ResourceLocation> r) { + for (var e : POTIONS.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } + + private static final Map<ResourceLocation, Potion> POTIONS = new LinkedHashMap<>(); + + public static final Potion ENLARGE_GRID = + make( + "enlarge_grid", + new Potion("enlarge_grid", new MobEffectInstance(HexMobEffects.ENLARGE_GRID, 3600))); + public static final Potion ENLARGE_GRID_LONG = + make( + "enlarge_grid_long", + new Potion("enlarge_grid_long", new MobEffectInstance(HexMobEffects.ENLARGE_GRID, 9600))); + public static final Potion ENLARGE_GRID_STRONG = + make( + "enlarge_grid_strong", + new Potion( + "enlarge_grid_strong", new MobEffectInstance(HexMobEffects.ENLARGE_GRID, 1800, 1))); + + public static void addRecipes() { + /* + AccessorPotionBrewing.addMix(Potions.AWKWARD, HexItems.AMETHYST_DUST, ENLARGE_GRID); + AccessorPotionBrewing.addMix(ENLARGE_GRID, Items.REDSTONE, ENLARGE_GRID_LONG); + AccessorPotionBrewing.addMix(ENLARGE_GRID, Items.GLOWSTONE_DUST, ENLARGE_GRID_STRONG); + */ + } + + private static <T extends Potion> T make(String id, T potion) { + var old = POTIONS.put(modLoc(id), potion); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + id); + } + return potion; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexRegistries.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexRegistries.java index e529e9b889..9016335dce 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexRegistries.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexRegistries.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.common.lib; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.ActionRegistryEntry; import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic; import at.petrak.hexcasting.api.casting.castables.SpecialHandler; @@ -9,13 +11,17 @@ import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class HexRegistries { - public static final ResourceKey<Registry<ActionRegistryEntry>> ACTION = ResourceKey.createRegistryKey(modLoc("action")); - public static final ResourceKey<Registry<SpecialHandler.Factory<?>>> SPECIAL_HANDLER = ResourceKey.createRegistryKey(modLoc("special_handler")); - public static final ResourceKey<Registry<IotaType<?>>> IOTA_TYPE = ResourceKey.createRegistryKey(modLoc("iota_type")); - public static final ResourceKey<Registry<Arithmetic>> ARITHMETIC = ResourceKey.createRegistryKey(modLoc("arithmetic")); - public static final ResourceKey<Registry<ContinuationFrame.Type<?>>> CONTINUATION_TYPE = ResourceKey.createRegistryKey(modLoc("continuation_type")); - public static final ResourceKey<Registry<EvalSound>> EVAL_SOUND = ResourceKey.createRegistryKey(modLoc("eval_sound")); + public static final ResourceKey<Registry<ActionRegistryEntry>> ACTION = + ResourceKey.createRegistryKey(modLoc("action")); + public static final ResourceKey<Registry<SpecialHandler.Factory<?>>> SPECIAL_HANDLER = + ResourceKey.createRegistryKey(modLoc("special_handler")); + public static final ResourceKey<Registry<IotaType<?>>> IOTA_TYPE = + ResourceKey.createRegistryKey(modLoc("iota_type")); + public static final ResourceKey<Registry<Arithmetic>> ARITHMETIC = + ResourceKey.createRegistryKey(modLoc("arithmetic")); + public static final ResourceKey<Registry<ContinuationFrame.Type<?>>> CONTINUATION_TYPE = + ResourceKey.createRegistryKey(modLoc("continuation_type")); + public static final ResourceKey<Registry<EvalSound>> EVAL_SOUND = + ResourceKey.createRegistryKey(modLoc("eval_sound")); } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexSounds.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexSounds.java index b70f239a12..a5538be60f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexSounds.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexSounds.java @@ -1,60 +1,59 @@ package at.petrak.hexcasting.common.lib; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.sounds.SoundEvent; +import static at.petrak.hexcasting.api.HexAPI.modLoc; import java.util.LinkedHashMap; import java.util.Map; import java.util.function.BiConsumer; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvent; public class HexSounds { - public static void registerSounds(BiConsumer<SoundEvent, ResourceLocation> r) { - for (var e : SOUNDS.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } + public static void registerSounds(BiConsumer<SoundEvent, ResourceLocation> r) { + for (var e : SOUNDS.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } - private static final Map<ResourceLocation, SoundEvent> SOUNDS = new LinkedHashMap<>(); + private static final Map<ResourceLocation, SoundEvent> SOUNDS = new LinkedHashMap<>(); - public static final SoundEvent START_PATTERN = sound("casting.pattern.start"); - public static final SoundEvent ADD_TO_PATTERN = sound("casting.pattern.add_segment"); + public static final SoundEvent START_PATTERN = sound("casting.pattern.start"); + public static final SoundEvent ADD_TO_PATTERN = sound("casting.pattern.add_segment"); - public static final SoundEvent CASTING_AMBIANCE = sound("casting.ambiance"); + public static final SoundEvent CASTING_AMBIANCE = sound("casting.ambiance"); - public static final SoundEvent CAST_NORMAL = sound("casting.cast.normal"); - public static final SoundEvent CAST_SPELL = sound("casting.cast.spell"); - public static final SoundEvent CAST_HERMES = sound("casting.cast.hermes"); - public static final SoundEvent CAST_THOTH = sound("casting.cast.thoth"); - public static final SoundEvent CAST_FAILURE = sound("casting.cast.fail"); + public static final SoundEvent CAST_NORMAL = sound("casting.cast.normal"); + public static final SoundEvent CAST_SPELL = sound("casting.cast.spell"); + public static final SoundEvent CAST_HERMES = sound("casting.cast.hermes"); + public static final SoundEvent CAST_THOTH = sound("casting.cast.thoth"); + public static final SoundEvent CAST_FAILURE = sound("casting.cast.fail"); - public static final SoundEvent ABACUS = sound("abacus"); - public static final SoundEvent ABACUS_SHAKE = sound("abacus.shake"); + public static final SoundEvent ABACUS = sound("abacus"); + public static final SoundEvent ABACUS_SHAKE = sound("abacus.shake"); - public static final SoundEvent STAFF_RESET = sound("staff.reset"); + public static final SoundEvent STAFF_RESET = sound("staff.reset"); - public static final SoundEvent SPELL_CIRCLE_FIND_BLOCK = sound("spellcircle.find_block"); - public static final SoundEvent SPELL_CIRCLE_FAIL = sound("spellcircle.fail"); + public static final SoundEvent SPELL_CIRCLE_FIND_BLOCK = sound("spellcircle.find_block"); + public static final SoundEvent SPELL_CIRCLE_FAIL = sound("spellcircle.fail"); - public static final SoundEvent SCROLL_DUST = sound("scroll.dust"); - public static final SoundEvent SCROLL_SCRIBBLE = sound("scroll.scribble"); + public static final SoundEvent SCROLL_DUST = sound("scroll.dust"); + public static final SoundEvent SCROLL_SCRIBBLE = sound("scroll.scribble"); - public static final SoundEvent IMPETUS_LOOK_TICK = sound("impetus.fletcher.tick"); - public static final SoundEvent IMPETUS_REDSTONE_DING = sound("impetus.redstone.register"); + public static final SoundEvent IMPETUS_LOOK_TICK = sound("impetus.fletcher.tick"); + public static final SoundEvent IMPETUS_REDSTONE_DING = sound("impetus.redstone.register"); - public static final SoundEvent READ_LORE_FRAGMENT = sound("lore_fragment.read"); + public static final SoundEvent READ_LORE_FRAGMENT = sound("lore_fragment.read"); - public static final SoundEvent FLIGHT_AMBIENCE = sound("flight.ambience"); - public static final SoundEvent FLIGHT_FINISH = sound("flight.finish"); + public static final SoundEvent FLIGHT_AMBIENCE = sound("flight.ambience"); + public static final SoundEvent FLIGHT_FINISH = sound("flight.finish"); - private static SoundEvent sound(String name) { - var id = modLoc(name); - var sound = SoundEvent.createVariableRangeEvent(id); - var old = SOUNDS.put(id, sound); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + name); - } - return sound; - } + private static SoundEvent sound(String name) { + var id = modLoc(name); + var sound = SoundEvent.createVariableRangeEvent(id); + var old = SOUNDS.put(id, sound); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + name); + } + return sound; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexActions.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexActions.java index 27398b8787..b1c92f0004 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexActions.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexActions.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.common.lib.hex; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.ActionRegistryEntry; import at.petrak.hexcasting.api.casting.castables.Action; import at.petrak.hexcasting.api.casting.castables.OperationAction; @@ -15,6 +17,7 @@ import at.petrak.hexcasting.common.casting.actions.akashic.*; import at.petrak.hexcasting.common.casting.actions.circles.*; import at.petrak.hexcasting.common.casting.actions.eval.*; +import at.petrak.hexcasting.common.casting.actions.eval.OpEvalBreakable; import at.petrak.hexcasting.common.casting.actions.lists.*; import at.petrak.hexcasting.common.casting.actions.local.*; import at.petrak.hexcasting.common.casting.actions.math.*; @@ -26,10 +29,12 @@ import at.petrak.hexcasting.common.casting.actions.spells.great.*; import at.petrak.hexcasting.common.casting.actions.spells.sentinel.*; import at.petrak.hexcasting.common.casting.actions.stack.*; -import at.petrak.hexcasting.common.casting.actions.eval.OpEvalBreakable; import at.petrak.hexcasting.common.lib.HexItems; import at.petrak.hexcasting.interop.pehkui.*; import at.petrak.hexcasting.xplat.IXplatAbstractions; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.BiConsumer; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.effect.MobEffects; @@ -39,539 +44,914 @@ import net.minecraft.world.level.material.Fluids; import net.minecraft.world.phys.Vec3; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.function.BiConsumer; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - @SuppressWarnings("unused") public class HexActions { - public static final Registry<ActionRegistryEntry> REGISTRY = IXplatAbstractions.INSTANCE.getActionRegistry(); - - private static final Map<ResourceLocation, ActionRegistryEntry> ACTIONS = new LinkedHashMap<>(); - - // In general: - // - CCW is the normal or construction version - // - CW is the special or destruction version - - public static final ActionRegistryEntry GET_CASTER = make("get_caster", - new ActionRegistryEntry(HexPattern.fromAngles("qaq", HexDir.NORTH_EAST), OpGetCaster.INSTANCE)); - public static final ActionRegistryEntry ENTITY_POS$EYE = make("entity_pos/eye", - new ActionRegistryEntry(HexPattern.fromAngles("aa", HexDir.EAST), new OpEntityPos(false))); - public static final ActionRegistryEntry ENTITY_POS$FOOT = make("entity_pos/foot", - new ActionRegistryEntry(HexPattern.fromAngles("dd", HexDir.NORTH_EAST), new OpEntityPos(true))); - public static final ActionRegistryEntry ENTITY_LOOK = make("get_entity_look", - new ActionRegistryEntry(HexPattern.fromAngles("wa", HexDir.EAST), OpEntityLook.INSTANCE)); - public static final ActionRegistryEntry ENTITY_HEIGHT = make("get_entity_height", - new ActionRegistryEntry(HexPattern.fromAngles("awq", HexDir.NORTH_EAST), OpEntityHeight.INSTANCE)); - public static final ActionRegistryEntry ENTITY_VELOCITY = make("get_entity_velocity", - new ActionRegistryEntry(HexPattern.fromAngles("wq", HexDir.EAST), OpEntityVelocity.INSTANCE)); - - // == Getters == - - public static final ActionRegistryEntry RAYCAST = make("raycast", - new ActionRegistryEntry(HexPattern.fromAngles("wqaawdd", HexDir.EAST), OpBlockRaycast.INSTANCE)); - public static final ActionRegistryEntry RAYCAST_AXIS = make("raycast/axis", - new ActionRegistryEntry(HexPattern.fromAngles("weddwaa", HexDir.EAST), OpBlockAxisRaycast.INSTANCE)); - public static final ActionRegistryEntry RAYCAST_ENTITY = make("raycast/entity", - new ActionRegistryEntry(HexPattern.fromAngles("weaqa", HexDir.EAST), OpEntityRaycast.INSTANCE)); - - // == spell circle getters == - - public static final ActionRegistryEntry CIRCLE$IMPETUS_POST = make("circle/impetus_pos", - new ActionRegistryEntry(HexPattern.fromAngles("eaqwqae", HexDir.SOUTH_WEST), OpImpetusPos.INSTANCE)); - public static final ActionRegistryEntry CIRCLE$IMPETUS_DIR = make("circle/impetus_dir", - new ActionRegistryEntry(HexPattern.fromAngles("eaqwqaewede", HexDir.SOUTH_WEST), OpImpetusDir.INSTANCE)); - public static final ActionRegistryEntry CIRCLE$BOUNDS$MIN = make("circle/bounds/min", - new ActionRegistryEntry(HexPattern.fromAngles("eaqwqaewdd", HexDir.SOUTH_WEST), new OpCircleBounds(false))); - public static final ActionRegistryEntry CIRCLE$BOUNDS$MAX = make("circle/bounds/max", - new ActionRegistryEntry(HexPattern.fromAngles("aqwqawaaqa", HexDir.WEST), new OpCircleBounds(true))); - - // == Modify Stack == - - public static final ActionRegistryEntry SWAP = make("swap", - new ActionRegistryEntry(HexPattern.fromAngles("aawdd", HexDir.EAST), new OpTwiddling(2, new int[]{1, 0}))); - public static final ActionRegistryEntry ROTATE = make("rotate", - new ActionRegistryEntry(HexPattern.fromAngles("aaeaa", HexDir.EAST), new OpTwiddling(3, new int[]{1, 2, 0}))); - public static final ActionRegistryEntry ROTATE_REVERSE = make("rotate_reverse", - new ActionRegistryEntry(HexPattern.fromAngles("ddqdd", - HexDir.NORTH_EAST), new OpTwiddling(3, new int[]{2, 0, 1}))); - public static final ActionRegistryEntry DUPLICATE = make("duplicate", - new ActionRegistryEntry(HexPattern.fromAngles("aadaa", HexDir.EAST), new OpTwiddling(1, new int[]{0, 0}))); - public static final ActionRegistryEntry OVER = make("over", - new ActionRegistryEntry(HexPattern.fromAngles("aaedd", HexDir.EAST), new OpTwiddling(2, new int[]{0, 1, 0}))); - public static final ActionRegistryEntry TUCK = make("tuck", - new ActionRegistryEntry(HexPattern.fromAngles("ddqaa", HexDir.EAST), new OpTwiddling(2, new int[]{1, 0, 1}))); - public static final ActionRegistryEntry TWO_DUP = make("2dup", - new ActionRegistryEntry(HexPattern.fromAngles("aadadaaw", - HexDir.EAST), new OpTwiddling(2, new int[]{0, 1, 0, 1}))); - - public static final ActionRegistryEntry STACK_LEN = make("stack_len", - new ActionRegistryEntry(HexPattern.fromAngles("qwaeawqaeaqa", HexDir.NORTH_WEST), OpStackSize.INSTANCE)); - public static final ActionRegistryEntry DUPLICATE_N = make("duplicate_n", - new ActionRegistryEntry(HexPattern.fromAngles("aadaadaa", HexDir.EAST), OpDuplicateN.INSTANCE)); - public static final ActionRegistryEntry FISHERMAN = make("fisherman", - new ActionRegistryEntry(HexPattern.fromAngles("ddad", HexDir.WEST), OpFisherman.INSTANCE)); - public static final ActionRegistryEntry FISHERMAN$COPY = make("fisherman/copy", - new ActionRegistryEntry(HexPattern.fromAngles("aada", HexDir.EAST), OpFishermanButItCopies.INSTANCE)); - public static final ActionRegistryEntry SWIZZLE = make("swizzle", - new ActionRegistryEntry(HexPattern.fromAngles("qaawdde", - HexDir.SOUTH_EAST), OpAlwinfyHasAscendedToABeingOfPureMath.INSTANCE)); - - // == Math == - - public static final ActionRegistryEntry ADD = make("add", - new OperationAction(HexPattern.fromAngles("waaw", HexDir.NORTH_EAST))); - public static final ActionRegistryEntry SUB = make("sub", - new OperationAction(HexPattern.fromAngles("wddw", HexDir.NORTH_WEST))); - public static final ActionRegistryEntry MUL_DOT = make("mul", - new OperationAction(HexPattern.fromAngles("waqaw", HexDir.SOUTH_EAST))); - public static final ActionRegistryEntry DIV_CROSS = make("div", - new OperationAction(HexPattern.fromAngles("wdedw", HexDir.NORTH_EAST))); - public static final ActionRegistryEntry ABS = make("abs", - new OperationAction(HexPattern.fromAngles("wqaqw", HexDir.NORTH_EAST))); - public static final ActionRegistryEntry POW_PROJ = make("pow", - new OperationAction(HexPattern.fromAngles("wedew", HexDir.NORTH_WEST))); - public static final ActionRegistryEntry FLOOR = make("floor", - new OperationAction(HexPattern.fromAngles("ewq", HexDir.EAST))); - public static final ActionRegistryEntry CEIL = make("ceil", - new OperationAction(HexPattern.fromAngles("qwe", HexDir.EAST))); - - public static final ActionRegistryEntry CONSTRUCT_VEC = make("construct_vec", - new OperationAction(HexPattern.fromAngles("eqqqqq", HexDir.EAST))); - public static final ActionRegistryEntry DECONSTRUCT_VEC = make("deconstruct_vec", - new OperationAction(HexPattern.fromAngles("qeeeee", HexDir.EAST))); - public static final ActionRegistryEntry COERCE_AXIAL = make("coerce_axial", - new ActionRegistryEntry(HexPattern.fromAngles("qqqqqaww", HexDir.NORTH_WEST), OpCoerceToAxial.INSTANCE)); - - // == Logic == - - public static final ActionRegistryEntry AND = make("and", - new OperationAction(HexPattern.fromAngles("wdw", HexDir.NORTH_EAST))); - public static final ActionRegistryEntry OR = make("or", - new OperationAction(HexPattern.fromAngles("waw", HexDir.SOUTH_EAST))); - public static final ActionRegistryEntry XOR = make("xor", - new OperationAction(HexPattern.fromAngles("dwa", HexDir.NORTH_WEST))); - public static final ActionRegistryEntry GREATER = make("greater", new OperationAction( - HexPattern.fromAngles("e", HexDir.SOUTH_EAST)) - ); - public static final ActionRegistryEntry LESS = make("less", new OperationAction( - HexPattern.fromAngles("q", HexDir.SOUTH_WEST)) - ); - public static final ActionRegistryEntry GREATER_EQ = make("greater_eq", new OperationAction( - HexPattern.fromAngles("ee", HexDir.SOUTH_EAST)) - ); - public static final ActionRegistryEntry LESS_EQ = make("less_eq", new OperationAction( - HexPattern.fromAngles("qq", HexDir.SOUTH_WEST)) - ); - public static final ActionRegistryEntry EQUALS = make("equals", - new ActionRegistryEntry(HexPattern.fromAngles("ad", HexDir.EAST), new OpEquality(false))); - public static final ActionRegistryEntry NOT_EQUALS = make("not_equals", - new ActionRegistryEntry(HexPattern.fromAngles("da", HexDir.EAST), new OpEquality(true))); - public static final ActionRegistryEntry NOT = make("not", - new ActionRegistryEntry(HexPattern.fromAngles("dw", HexDir.NORTH_WEST), OpBoolNot.INSTANCE)); - public static final ActionRegistryEntry BOOL_COERCE = make("bool_coerce", - new ActionRegistryEntry(HexPattern.fromAngles("aw", HexDir.NORTH_EAST), OpCoerceToBool.INSTANCE)); - public static final ActionRegistryEntry IF = make("if", - new ActionRegistryEntry(HexPattern.fromAngles("awdd", HexDir.SOUTH_EAST), OpBoolIf.INSTANCE)); - - public static final ActionRegistryEntry RANDOM = make("random", - new ActionRegistryEntry(HexPattern.fromAngles("eqqq", HexDir.NORTH_WEST), OpRandom.INSTANCE)); - - // == Advanced Math == - - public static final ActionRegistryEntry SIN = make("sin", - new OperationAction(HexPattern.fromAngles("qqqqqaa", HexDir.SOUTH_EAST))); - public static final ActionRegistryEntry COS = make("cos", - new OperationAction(HexPattern.fromAngles("qqqqqad", HexDir.SOUTH_EAST))); - public static final ActionRegistryEntry TAN = make("tan", - new OperationAction(HexPattern.fromAngles("wqqqqqadq", HexDir.SOUTH_WEST))); - public static final ActionRegistryEntry ARCSIN = make("arcsin", - new OperationAction(HexPattern.fromAngles("ddeeeee", HexDir.SOUTH_EAST))); - public static final ActionRegistryEntry ARCCOS = make("arccos", - new OperationAction(HexPattern.fromAngles("adeeeee", HexDir.NORTH_EAST))); - public static final ActionRegistryEntry ARCTAN = make("arctan", - new OperationAction(HexPattern.fromAngles("eadeeeeew", HexDir.NORTH_EAST))); - public static final ActionRegistryEntry ARCTAN2 = make("arctan2", - new OperationAction(HexPattern.fromAngles("deadeeeeewd", HexDir.WEST))); - public static final ActionRegistryEntry LOGARITHM = make("logarithm", - new OperationAction(HexPattern.fromAngles("eqaqe", HexDir.NORTH_WEST))); - public static final ActionRegistryEntry MODULO = make("modulo", - new OperationAction(HexPattern.fromAngles("addwaad", HexDir.NORTH_EAST))); - - // == Sets == - - public static final ActionRegistryEntry UNIQUE = make("unique", - new OperationAction(HexPattern.fromAngles("aweaqa", HexDir.NORTH_EAST))); - - // == Spells == - - public static final ActionRegistryEntry PRINT = make("print", - new ActionRegistryEntry(HexPattern.fromAngles("de", HexDir.NORTH_EAST), OpPrint.INSTANCE)); - public static final ActionRegistryEntry EXPLODE = make("explode", - new ActionRegistryEntry(HexPattern.fromAngles("aawaawaa", HexDir.EAST), new OpExplode(false))); - public static final ActionRegistryEntry EXPLODE$FIRE = make("explode/fire", - new ActionRegistryEntry(HexPattern.fromAngles("ddwddwdd", HexDir.EAST), new OpExplode(true))); - public static final ActionRegistryEntry ADD_MOTION = make("add_motion", - new ActionRegistryEntry(HexPattern.fromAngles("awqqqwaqw", HexDir.SOUTH_WEST), OpAddMotion.INSTANCE)); - public static final ActionRegistryEntry BLINK = make("blink", - new ActionRegistryEntry(HexPattern.fromAngles("awqqqwaq", HexDir.SOUTH_WEST), OpBlink.INSTANCE)); - public static final ActionRegistryEntry BREAK_BLOCK = make("break_block", - new ActionRegistryEntry(HexPattern.fromAngles("qaqqqqq", HexDir.EAST), OpBreakBlock.INSTANCE)); - public static final ActionRegistryEntry PLACE_BLOCK = make("place_block", - new ActionRegistryEntry(HexPattern.fromAngles("eeeeede", HexDir.SOUTH_WEST), OpPlaceBlock.INSTANCE)); - public static final ActionRegistryEntry COLORIZE = make("colorize", - new ActionRegistryEntry(HexPattern.fromAngles("awddwqawqwawq", HexDir.EAST), OpColorize.INSTANCE)); - public static final ActionRegistryEntry CYCLE_VARIANT = make("cycle_variant", - new ActionRegistryEntry(HexPattern.fromAngles("dwaawedwewdwe", HexDir.WEST), OpCycleVariant.INSTANCE)); - public static final ActionRegistryEntry CREATE_WATER = make("create_water", - new ActionRegistryEntry(HexPattern.fromAngles("aqawqadaq", HexDir.SOUTH_EAST), new OpCreateFluid( - MediaConstants.DUST_UNIT, - Items.WATER_BUCKET, - Blocks.WATER_CAULDRON.defaultBlockState() - .setValue(LayeredCauldronBlock.LEVEL, LayeredCauldronBlock.MAX_FILL_LEVEL), - Fluids.WATER))); - public static final ActionRegistryEntry DESTROY_WATER = make("destroy_water", - new ActionRegistryEntry(HexPattern.fromAngles("dedwedade", HexDir.SOUTH_WEST), OpDestroyFluid.INSTANCE)); - public static final ActionRegistryEntry IGNITE = make("ignite", - new ActionRegistryEntry(HexPattern.fromAngles("aaqawawa", HexDir.SOUTH_EAST), OpIgnite.INSTANCE)); - public static final ActionRegistryEntry EXTINGUISH = make("extinguish", - new ActionRegistryEntry(HexPattern.fromAngles("ddedwdwd", HexDir.SOUTH_WEST), OpExtinguish.INSTANCE)); - public static final ActionRegistryEntry CONJURE_BLOCK = make("conjure_block", - new ActionRegistryEntry(HexPattern.fromAngles("qqa", HexDir.NORTH_EAST), new OpConjureBlock(false))); - public static final ActionRegistryEntry CONJURE_LIGHT = make("conjure_light", - new ActionRegistryEntry(HexPattern.fromAngles("qqd", HexDir.NORTH_EAST), new OpConjureBlock(true))); - public static final ActionRegistryEntry BONEMEAL = make("bonemeal", - new ActionRegistryEntry(HexPattern.fromAngles("wqaqwawqaqw", - HexDir.NORTH_EAST), OpTheOnlyReasonAnyoneDownloadedPsi.INSTANCE)); - public static final ActionRegistryEntry RECHARGE = make("recharge", - new ActionRegistryEntry(HexPattern.fromAngles("qqqqqwaeaeaeaeaea", HexDir.NORTH_WEST), OpRecharge.INSTANCE)); - public static final ActionRegistryEntry ERASE = make("erase", - new ActionRegistryEntry(HexPattern.fromAngles("qdqawwaww", HexDir.EAST), OpErase.INSTANCE)); - public static final ActionRegistryEntry EDIFY = make("edify", - new ActionRegistryEntry(HexPattern.fromAngles("wqaqwd", HexDir.NORTH_EAST), OpEdifySapling.INSTANCE)); - - public static final ActionRegistryEntry BEEP = make("beep", - new ActionRegistryEntry(HexPattern.fromAngles("adaa", HexDir.WEST), OpBeep.INSTANCE)); - - public static final ActionRegistryEntry CRAFT$CYPHER = make("craft/cypher", new ActionRegistryEntry( - HexPattern.fromAngles("waqqqqq", HexDir.EAST), new OpMakePackagedSpell<>(HexItems.CYPHER, - MediaConstants.CRYSTAL_UNIT) - )); - public static final ActionRegistryEntry CRAFT$TRINKET = make("craft/trinket", new ActionRegistryEntry( - HexPattern.fromAngles( - "wwaqqqqqeaqeaeqqqeaeq", HexDir.EAST), new OpMakePackagedSpell<>(HexItems.TRINKET, - 5 * MediaConstants.CRYSTAL_UNIT))); - public static final ActionRegistryEntry CRAFT$ARTIFACT = make("craft/artifact", new ActionRegistryEntry( - HexPattern.fromAngles("wwaqqqqqeawqwqwqwqwqwwqqeadaeqqeqqeadaeqq", HexDir.EAST), - new OpMakePackagedSpell<>(HexItems.ARTIFACT, 10 * MediaConstants.CRYSTAL_UNIT) - )); - public static final ActionRegistryEntry CRAFT$BATTERY = make("craft/battery", new ActionRegistryEntry( - HexPattern.fromAngles("aqqqaqwwaqqqqqeqaqqqawwqwqwqwqwqw", HexDir.SOUTH_WEST), OpMakeBattery.INSTANCE)); - - public static final ActionRegistryEntry POTION$WEAKNESS = make("potion/weakness", new ActionRegistryEntry( - HexPattern.fromAngles("qqqqqaqwawaw", HexDir.NORTH_WEST), new OpPotionEffect(MobEffects.WEAKNESS, - MediaConstants.DUST_UNIT / 10, true, false) - )); - public static final ActionRegistryEntry POTION$LEVITATION = make("potion/levitation", new ActionRegistryEntry( - HexPattern.fromAngles("qqqqqawwawawd", HexDir.WEST), new OpPotionEffect(MobEffects.LEVITATION, - MediaConstants.DUST_UNIT / 5, false, false) - )); - public static final ActionRegistryEntry POTION$WITHER = make("potion/wither", new ActionRegistryEntry( - HexPattern.fromAngles("qqqqqaewawawe", HexDir.SOUTH_WEST), new OpPotionEffect(MobEffects.WITHER, - MediaConstants.DUST_UNIT, true, false) - )); - public static final ActionRegistryEntry POTION$POISON = make("potion/poison", new ActionRegistryEntry( - HexPattern.fromAngles("qqqqqadwawaww", HexDir.SOUTH_EAST), new OpPotionEffect(MobEffects.POISON, - MediaConstants.DUST_UNIT / 3, true, false) - )); - public static final ActionRegistryEntry POTION$SLOWNESS = make("potion/slowness", new ActionRegistryEntry( - HexPattern.fromAngles("qqqqqadwawaw", HexDir.SOUTH_EAST), new OpPotionEffect(MobEffects.MOVEMENT_SLOWDOWN, - MediaConstants.DUST_UNIT / 3, true, false) - )); - - public static final ActionRegistryEntry POTION$REGENERATION = make("potion/regeneration", new ActionRegistryEntry( - HexPattern.fromAngles("qqqqaawawaedd", HexDir.NORTH_WEST), new OpPotionEffect(MobEffects.REGENERATION, - MediaConstants.DUST_UNIT, true, true) - )); - public static final ActionRegistryEntry POTION$NIGHT_VISION = make("potion/night_vision", new ActionRegistryEntry( - HexPattern.fromAngles("qqqaawawaeqdd", HexDir.WEST), new OpPotionEffect(MobEffects.NIGHT_VISION, - MediaConstants.DUST_UNIT / 5, false, true) - )); - public static final ActionRegistryEntry POTION$ABSORPTION = make("potion/absorption", new ActionRegistryEntry( - HexPattern.fromAngles("qqaawawaeqqdd", HexDir.SOUTH_WEST), new OpPotionEffect(MobEffects.ABSORPTION, - MediaConstants.DUST_UNIT, true, true) - )); - public static final ActionRegistryEntry POTION$HASTE = make("potion/haste", new ActionRegistryEntry( - HexPattern.fromAngles("qaawawaeqqqdd", HexDir.SOUTH_EAST), new OpPotionEffect(MobEffects.DIG_SPEED, - MediaConstants.DUST_UNIT / 3, true, true) - )); - public static final ActionRegistryEntry POTION$STRENGTH = make("potion/strength", new ActionRegistryEntry( - HexPattern.fromAngles("aawawaeqqqqdd", HexDir.EAST), new OpPotionEffect(MobEffects.DAMAGE_BOOST, - MediaConstants.DUST_UNIT / 3, true, true) - )); - - public static final ActionRegistryEntry FLIGHT$RANGE = make("flight/range", - new ActionRegistryEntry(HexPattern.fromAngles("awawaawq", HexDir.SOUTH_WEST), - new OpFlight(OpFlight.Type.LimitRange))); - public static final ActionRegistryEntry FLIGHT$TIME = make("flight/time", - new ActionRegistryEntry(HexPattern.fromAngles("dwdwdewq", HexDir.NORTH_EAST), - new OpFlight(OpFlight.Type.LimitTime))); - - public static final ActionRegistryEntry SENTINEL$CREATE = make("sentinel/create", - new ActionRegistryEntry(HexPattern.fromAngles("waeawae", HexDir.EAST), new OpCreateSentinel(false))); - public static final ActionRegistryEntry SENTINEL$DESTROY = make("sentinel/destroy", - new ActionRegistryEntry(HexPattern.fromAngles("qdwdqdw", HexDir.NORTH_EAST), OpDestroySentinel.INSTANCE)); - public static final ActionRegistryEntry SENTINEL$GET_POS = make("sentinel/get_pos", - new ActionRegistryEntry(HexPattern.fromAngles("waeawaede", HexDir.EAST), OpGetSentinelPos.INSTANCE)); - public static final ActionRegistryEntry SENTINEL$WAYFIND = make("sentinel/wayfind", - new ActionRegistryEntry(HexPattern.fromAngles("waeawaedwa", HexDir.EAST), OpGetSentinelWayfind.INSTANCE)); - - public static final ActionRegistryEntry LIGHTNING = make("lightning", - new ActionRegistryEntry(HexPattern.fromAngles("waadwawdaaweewq", HexDir.EAST), OpLightning.INSTANCE)); - - public static final ActionRegistryEntry ALTIORA = make("flight", - new ActionRegistryEntry(HexPattern.fromAngles("eawwaeawawaa", HexDir.NORTH_WEST), OpAltiora.INSTANCE)); - - - public static final ActionRegistryEntry CREATE_LAVA = make("create_lava", - new ActionRegistryEntry(HexPattern.fromAngles("eaqawqadaqd", HexDir.EAST), new OpCreateFluid( - MediaConstants.CRYSTAL_UNIT, - Items.LAVA_BUCKET, - Blocks.LAVA_CAULDRON.defaultBlockState(), - Fluids.LAVA))); - public static final ActionRegistryEntry TELEPORT = make("teleport/great", - new ActionRegistryEntry(HexPattern.fromAngles("wwwqqqwwwqqeqqwwwqqwqqdqqqqqdqq", - HexDir.EAST), OpTeleport.INSTANCE)); - public static final ActionRegistryEntry SENTINEL$GREAT = make("sentinel/create/great", - new ActionRegistryEntry(HexPattern.fromAngles("waeawaeqqqwqwqqwq", HexDir.EAST), new OpCreateSentinel(true))); - public static final ActionRegistryEntry DISPEL_RAIN = make("dispel_rain", - new ActionRegistryEntry(HexPattern.fromAngles("eeewwweeewwaqqddqdqd", HexDir.EAST), new OpWeather(false))); - public static final ActionRegistryEntry SUMMON_RAIN = make("summon_rain", - new ActionRegistryEntry(HexPattern.fromAngles("wwweeewwweewdawdwad", HexDir.WEST), new OpWeather(true))); - public static final ActionRegistryEntry BRAINSWEEP = make("brainsweep", - new ActionRegistryEntry(HexPattern.fromAngles("qeqwqwqwqwqeqaeqeaqeqaeqaqded", - HexDir.NORTH_EAST), OpBrainsweep.INSTANCE)); - - public static final ActionRegistryEntry AKASHIC$READ = make("akashic/read", - new ActionRegistryEntry(HexPattern.fromAngles("qqqwqqqqqaq", HexDir.WEST), OpAkashicRead.INSTANCE)); - public static final ActionRegistryEntry AKASHIC$WRITE = make("akashic/write", - new ActionRegistryEntry(HexPattern.fromAngles("eeeweeeeede", HexDir.EAST), OpAkashicWrite.INSTANCE)); - - // == Meta stuff == - - // Intro/Retro/Consideration are now special-form-likes and aren't even ops. - // TODO should there be a registry for these too - - // http://www.toroidalsnark.net/mkss3-pix/CalderheadJMM2014.pdf - // eval being a space filling curve feels apt doesn't it - public static final ActionRegistryEntry EVAL = make("eval", - new ActionRegistryEntry(HexPattern.fromAngles("deaqq", HexDir.SOUTH_EAST), OpEval.INSTANCE)); - public static final ActionRegistryEntry EVAL$CC = make("eval/cc", - new ActionRegistryEntry(HexPattern.fromAngles("qwaqde", HexDir.NORTH_WEST), OpEvalBreakable.INSTANCE)); - public static final ActionRegistryEntry HALT = make("halt", - new ActionRegistryEntry(HexPattern.fromAngles("aqdee", HexDir.SOUTH_WEST), OpHalt.INSTANCE)); - - public static final ActionRegistryEntry READ = make("read", - new ActionRegistryEntry(HexPattern.fromAngles("aqqqqq", HexDir.EAST), OpRead.INSTANCE)); - public static final ActionRegistryEntry READ$ENTITY = make("read/entity", - new ActionRegistryEntry(HexPattern.fromAngles("wawqwqwqwqwqw", HexDir.EAST), OpTheCoolerRead.INSTANCE)); - public static final ActionRegistryEntry WRITE = make("write", - new ActionRegistryEntry(HexPattern.fromAngles("deeeee", HexDir.EAST), OpWrite.INSTANCE)); - public static final ActionRegistryEntry WRITE$ENTITY = make("write/entity", - new ActionRegistryEntry(HexPattern.fromAngles("wdwewewewewew", HexDir.EAST), OpTheCoolerWrite.INSTANCE)); - public static final ActionRegistryEntry READABLE = make("readable", - new ActionRegistryEntry(HexPattern.fromAngles("aqqqqqe", HexDir.EAST), OpReadable.INSTANCE)); - public static final ActionRegistryEntry READABLE$ENTITY = make("readable/entity", - new ActionRegistryEntry(HexPattern.fromAngles("wawqwqwqwqwqwew", HexDir.EAST), OpTheCoolerReadable.INSTANCE)); - public static final ActionRegistryEntry WRITABLE = make("writable", - new ActionRegistryEntry(HexPattern.fromAngles("deeeeeq", HexDir.EAST), OpWritable.INSTANCE)); - public static final ActionRegistryEntry WRITABLE$ENTITY = make("writable/entity", - new ActionRegistryEntry(HexPattern.fromAngles("wdwewewewewewqw", HexDir.EAST), OpTheCoolerWritable.INSTANCE)); - - public static final ActionRegistryEntry READ$LOCAL = make("read/local", - new ActionRegistryEntry(HexPattern.fromAngles("qeewdweddw", HexDir.NORTH_EAST), OpPeekLocal.INSTANCE)); - public static final ActionRegistryEntry WRITE$LOCAL = make("write/local", - new ActionRegistryEntry(HexPattern.fromAngles("eqqwawqaaw", HexDir.NORTH_WEST), OpPushLocal.INSTANCE)); - - public static final ActionRegistryEntry THANATOS = make("thanatos", - new ActionRegistryEntry(HexPattern.fromAngles("qqaed", HexDir.SOUTH_EAST), OpThanos.INSTANCE)); - - // == Consts == - - public static final ActionRegistryEntry CONST$NULL = make("const/null", - new ActionRegistryEntry(HexPattern.fromAngles("d", HexDir.EAST), Action.makeConstantOp(new NullIota()))); - - public static final ActionRegistryEntry CONST$TRUE = make("const/true", - new ActionRegistryEntry(HexPattern.fromAngles("aqae", - HexDir.SOUTH_EAST), Action.makeConstantOp(new BooleanIota(true)))); - public static final ActionRegistryEntry CONST$FALSE = make("const/false", - new ActionRegistryEntry(HexPattern.fromAngles("dedq", - HexDir.NORTH_EAST), Action.makeConstantOp(new BooleanIota(false)))); - - public static final ActionRegistryEntry CONST$VEC$PX = make("const/vec/px", - new ActionRegistryEntry(HexPattern.fromAngles( - "qqqqqea", HexDir.NORTH_WEST), Action.makeConstantOp(new Vec3Iota(new Vec3(1.0, 0.0, 0.0))))); - public static final ActionRegistryEntry CONST$VEC$PY = make("const/vec/py", - new ActionRegistryEntry(HexPattern.fromAngles( - "qqqqqew", HexDir.NORTH_WEST), Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 1.0, 0.0))))); - public static final ActionRegistryEntry CONST$VEC$PZ = make("const/vec/pz", - new ActionRegistryEntry(HexPattern.fromAngles( - "qqqqqed", HexDir.NORTH_WEST), Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 0.0, 1.0))))); - public static final ActionRegistryEntry CONST$VEC$NX = make("const/vec/nx", - new ActionRegistryEntry(HexPattern.fromAngles( - "eeeeeqa", HexDir.SOUTH_WEST), Action.makeConstantOp(new Vec3Iota(new Vec3(-1.0, 0.0, 0.0))))); - public static final ActionRegistryEntry CONST$VEC$NY = make("const/vec/ny", - new ActionRegistryEntry(HexPattern.fromAngles( - "eeeeeqw", HexDir.SOUTH_WEST), Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, -1.0, 0.0))))); - public static final ActionRegistryEntry CONST$VEC$NZ = make("const/vec/nz", - new ActionRegistryEntry(HexPattern.fromAngles( - "eeeeeqd", HexDir.SOUTH_WEST), Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 0.0, -1.0))))); - // Yep, this is what I spend the "plain hexagon" pattern on. - public static final ActionRegistryEntry CONST$VEC$0 = make("const/vec/0", - new ActionRegistryEntry(HexPattern.fromAngles( - "qqqqq", HexDir.NORTH_WEST), Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 0.0, 0.0))))); - - public static final ActionRegistryEntry CONST$DOUBLE$PI = make("const/double/pi", - new ActionRegistryEntry(HexPattern.fromAngles("qdwdq", - HexDir.NORTH_EAST), Action.makeConstantOp(new DoubleIota(Math.PI)))); - public static final ActionRegistryEntry CONST$DOUBLE$TAU = make("const/double/tau", - new ActionRegistryEntry(HexPattern.fromAngles("eawae", - HexDir.NORTH_WEST), Action.makeConstantOp(new DoubleIota(HexUtils.TAU)))); - public static final ActionRegistryEntry CONST$E = make("const/double/e", - new ActionRegistryEntry(HexPattern.fromAngles("aaq", - HexDir.EAST), Action.makeConstantOp(new DoubleIota(Math.E)))); - - // == Entities == - - public static final ActionRegistryEntry GET_ENTITY = make("get_entity", - new ActionRegistryEntry(HexPattern.fromAngles("qqqqqdaqa", HexDir.SOUTH_EAST), new OpGetEntityAt(e -> true))); - public static final ActionRegistryEntry GET_ENTITY$ANIMAL = make("get_entity/animal", - new ActionRegistryEntry(HexPattern.fromAngles("qqqqqdaqaawa", - HexDir.SOUTH_EAST), new OpGetEntityAt(OpGetEntitiesBy::isAnimal))); - public static final ActionRegistryEntry GET_ENTITY$MONSTER = make("get_entity/monster", - new ActionRegistryEntry(HexPattern.fromAngles("qqqqqdaqaawq", - HexDir.SOUTH_EAST), new OpGetEntityAt(OpGetEntitiesBy::isMonster))); - public static final ActionRegistryEntry GET_ENTITY$ITEM = make("get_entity/item", - new ActionRegistryEntry(HexPattern.fromAngles("qqqqqdaqaaww", - HexDir.SOUTH_EAST), new OpGetEntityAt(OpGetEntitiesBy::isItem))); - public static final ActionRegistryEntry GET_ENTITY$PLAYER = make("get_entity/player", - new ActionRegistryEntry(HexPattern.fromAngles("qqqqqdaqaawe", - HexDir.SOUTH_EAST), new OpGetEntityAt(OpGetEntitiesBy::isPlayer))); - public static final ActionRegistryEntry GET_ENTITY$LIVING = make("get_entity/living", - new ActionRegistryEntry(HexPattern.fromAngles("qqqqqdaqaawd", - HexDir.SOUTH_EAST), new OpGetEntityAt(OpGetEntitiesBy::isLiving))); - - public static final ActionRegistryEntry ZONE_ENTITY = make("zone_entity", new ActionRegistryEntry( - HexPattern.fromAngles("qqqqqwded", HexDir.SOUTH_EAST), new OpGetEntitiesBy(e -> true, false) - )); - public static final ActionRegistryEntry ZONE_ENTITY$ANIMAL = make("zone_entity/animal", new ActionRegistryEntry( - HexPattern.fromAngles("qqqqqwdeddwa", HexDir.SOUTH_EAST), new OpGetEntitiesBy(OpGetEntitiesBy::isAnimal, false) - )); - public static final ActionRegistryEntry ZONE_ENTITY$NOT_ANIMAL = make("zone_entity/not_animal", - new ActionRegistryEntry( - HexPattern.fromAngles("eeeeewaqaawa", HexDir.NORTH_EAST), new OpGetEntitiesBy(OpGetEntitiesBy::isAnimal, - true) - )); - public static final ActionRegistryEntry ZONE_ENTITY$MONSTER = make("zone_entity/monster", new ActionRegistryEntry( - HexPattern.fromAngles("qqqqqwdeddwq", HexDir.SOUTH_EAST), new OpGetEntitiesBy(OpGetEntitiesBy::isMonster, false) - )); - public static final ActionRegistryEntry ZONE_ENTITY$NOT_MONSTER = make("zone_entity/not_monster", - new ActionRegistryEntry( - HexPattern.fromAngles("eeeeewaqaawq", HexDir.NORTH_EAST), new OpGetEntitiesBy(OpGetEntitiesBy::isMonster, - true) - )); - public static final ActionRegistryEntry ZONE_ENTITY$ITEM = make("zone_entity/item", new ActionRegistryEntry( - HexPattern.fromAngles("qqqqqwdeddww", HexDir.SOUTH_EAST), new OpGetEntitiesBy(OpGetEntitiesBy::isItem, false) - )); - public static final ActionRegistryEntry ZONE_ENTITY$NOT_ITEM = make("zone_entity/not_item", new ActionRegistryEntry( - HexPattern.fromAngles("eeeeewaqaaww", HexDir.NORTH_EAST), new OpGetEntitiesBy(OpGetEntitiesBy::isItem, true) - )); - public static final ActionRegistryEntry ZONE_ENTITY$PLAYER = make("zone_entity/player", new ActionRegistryEntry( - HexPattern.fromAngles("qqqqqwdeddwe", HexDir.SOUTH_EAST), new OpGetEntitiesBy(OpGetEntitiesBy::isPlayer, false) - )); - public static final ActionRegistryEntry ZONE_ENTITY$NOT_PLAYER = make("zone_entity/not_player", - new ActionRegistryEntry( - HexPattern.fromAngles("eeeeewaqaawe", HexDir.NORTH_EAST), new OpGetEntitiesBy(OpGetEntitiesBy::isPlayer, - true) - )); - public static final ActionRegistryEntry ZONE_ENTITY$LIVING = make("zone_entity/living", new ActionRegistryEntry( - HexPattern.fromAngles("qqqqqwdeddwd", HexDir.SOUTH_EAST), new OpGetEntitiesBy(OpGetEntitiesBy::isLiving, false) - )); - public static final ActionRegistryEntry ZONE_ENTITY$NOT_LIVING = make("zone_entity/not_living", - new ActionRegistryEntry( - HexPattern.fromAngles("eeeeewaqaawd", HexDir.NORTH_EAST), new OpGetEntitiesBy(OpGetEntitiesBy::isLiving, - true) - )); - - // == Lists == - - public static final ActionRegistryEntry APPEND = make("append", - new OperationAction(HexPattern.fromAngles("edqde", HexDir.SOUTH_WEST))); - public static final ActionRegistryEntry UNAPPEND = make("unappend", - new OperationAction(HexPattern.fromAngles("qaeaq", HexDir.NORTH_WEST))); -// public static final ActionRegistryEntry CONCAT = make("concat", -// new ActionRegistryEntry(HexPattern.fromAngles("qaeaq", HexDir.NORTH_WEST), OpConcat.INSTANCE)); - public static final ActionRegistryEntry INDEX = make("index", - new OperationAction(HexPattern.fromAngles("deeed", HexDir.NORTH_WEST))); - public static final ActionRegistryEntry FOR_EACH = make("for_each", - new ActionRegistryEntry(HexPattern.fromAngles("dadad", HexDir.NORTH_EAST), OpForEach.INSTANCE)); -// public static final ActionRegistryEntry LIST_SIZE = make("list_size", -// new ActionRegistryEntry(HexPattern.fromAngles("aqaeaq", HexDir.EAST), OpListSize.INSTANCE)); - public static final ActionRegistryEntry SINGLETON = make("singleton", - new ActionRegistryEntry(HexPattern.fromAngles("adeeed", HexDir.EAST), OpSingleton.INSTANCE)); - public static final ActionRegistryEntry EMPTY_LIST = make("empty_list", - new ActionRegistryEntry(HexPattern.fromAngles("qqaeaae", HexDir.NORTH_EAST), OpEmptyList.INSTANCE)); - public static final ActionRegistryEntry REVERSE = make("reverse", - new OperationAction(HexPattern.fromAngles("qqqaede", HexDir.EAST))); - public static final ActionRegistryEntry LAST_N_LIST = make("last_n_list", - new ActionRegistryEntry(HexPattern.fromAngles("ewdqdwe", HexDir.SOUTH_WEST), OpLastNToList.INSTANCE)); - public static final ActionRegistryEntry SPLAT = make("splat", - new ActionRegistryEntry(HexPattern.fromAngles("qwaeawq", HexDir.NORTH_WEST), OpSplat.INSTANCE)); - public static final ActionRegistryEntry INDEX_OF = make("index_of", - new OperationAction(HexPattern.fromAngles("dedqde", HexDir.EAST))); - public static final ActionRegistryEntry REMOVE_FROM = make("remove_from", - new OperationAction(HexPattern.fromAngles("edqdewaqa", HexDir.SOUTH_WEST))); - public static final ActionRegistryEntry SLICE = make("slice", - new OperationAction(HexPattern.fromAngles("qaeaqwded", HexDir.NORTH_WEST))); - public static final ActionRegistryEntry REPLACE = make("replace", - new OperationAction(HexPattern.fromAngles("wqaeaqw", HexDir.NORTH_WEST))); - public static final ActionRegistryEntry CONSTRUCT = make("construct", - new OperationAction(HexPattern.fromAngles("ddewedd", HexDir.SOUTH_EAST))); - public static final ActionRegistryEntry DECONSTRUCT = make("deconstruct", - new OperationAction(HexPattern.fromAngles("aaqwqaa", HexDir.SOUTH_WEST))); - - // Xplat interops - static { - if (PehkuiInterop.isActive()) { - make("interop/pehkui/get", - new ActionRegistryEntry(HexPattern.fromAngles("aawawwawwa", HexDir.NORTH_WEST), OpGetScale.INSTANCE)); - make("interop/pehkui/set", - new ActionRegistryEntry(HexPattern.fromAngles("ddwdwwdwwd", HexDir.NORTH_EAST), OpSetScale.INSTANCE)); - } - } - - public static ActionRegistryEntry make(String name, ActionRegistryEntry are) { - var old = ACTIONS.put(modLoc(name), are); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + name); - } - return are; - } - - public static ActionRegistryEntry make(String name, OperationAction oa) { - var are = new ActionRegistryEntry(oa.getPattern(), oa); - var old = ACTIONS.put(modLoc(name), are); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + name); - } - return are; - } - - public static void register(BiConsumer<ActionRegistryEntry, ResourceLocation> r) { - for (var e : ACTIONS.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } + public static final Registry<ActionRegistryEntry> REGISTRY = + IXplatAbstractions.INSTANCE.getActionRegistry(); + + private static final Map<ResourceLocation, ActionRegistryEntry> ACTIONS = new LinkedHashMap<>(); + + // In general: + // - CCW is the normal or construction version + // - CW is the special or destruction version + + public static final ActionRegistryEntry GET_CASTER = + make( + "get_caster", + new ActionRegistryEntry( + HexPattern.fromAngles("qaq", HexDir.NORTH_EAST), OpGetCaster.INSTANCE)); + public static final ActionRegistryEntry ENTITY_POS$EYE = + make( + "entity_pos/eye", + new ActionRegistryEntry( + HexPattern.fromAngles("aa", HexDir.EAST), new OpEntityPos(false))); + public static final ActionRegistryEntry ENTITY_POS$FOOT = + make( + "entity_pos/foot", + new ActionRegistryEntry( + HexPattern.fromAngles("dd", HexDir.NORTH_EAST), new OpEntityPos(true))); + public static final ActionRegistryEntry ENTITY_LOOK = + make( + "get_entity_look", + new ActionRegistryEntry(HexPattern.fromAngles("wa", HexDir.EAST), OpEntityLook.INSTANCE)); + public static final ActionRegistryEntry ENTITY_HEIGHT = + make( + "get_entity_height", + new ActionRegistryEntry( + HexPattern.fromAngles("awq", HexDir.NORTH_EAST), OpEntityHeight.INSTANCE)); + public static final ActionRegistryEntry ENTITY_VELOCITY = + make( + "get_entity_velocity", + new ActionRegistryEntry( + HexPattern.fromAngles("wq", HexDir.EAST), OpEntityVelocity.INSTANCE)); + + // == Getters == + + public static final ActionRegistryEntry RAYCAST = + make( + "raycast", + new ActionRegistryEntry( + HexPattern.fromAngles("wqaawdd", HexDir.EAST), OpBlockRaycast.INSTANCE)); + public static final ActionRegistryEntry RAYCAST_AXIS = + make( + "raycast/axis", + new ActionRegistryEntry( + HexPattern.fromAngles("weddwaa", HexDir.EAST), OpBlockAxisRaycast.INSTANCE)); + public static final ActionRegistryEntry RAYCAST_ENTITY = + make( + "raycast/entity", + new ActionRegistryEntry( + HexPattern.fromAngles("weaqa", HexDir.EAST), OpEntityRaycast.INSTANCE)); + + // == spell circle getters == + + public static final ActionRegistryEntry CIRCLE$IMPETUS_POST = + make( + "circle/impetus_pos", + new ActionRegistryEntry( + HexPattern.fromAngles("eaqwqae", HexDir.SOUTH_WEST), OpImpetusPos.INSTANCE)); + public static final ActionRegistryEntry CIRCLE$IMPETUS_DIR = + make( + "circle/impetus_dir", + new ActionRegistryEntry( + HexPattern.fromAngles("eaqwqaewede", HexDir.SOUTH_WEST), OpImpetusDir.INSTANCE)); + public static final ActionRegistryEntry CIRCLE$BOUNDS$MIN = + make( + "circle/bounds/min", + new ActionRegistryEntry( + HexPattern.fromAngles("eaqwqaewdd", HexDir.SOUTH_WEST), new OpCircleBounds(false))); + public static final ActionRegistryEntry CIRCLE$BOUNDS$MAX = + make( + "circle/bounds/max", + new ActionRegistryEntry( + HexPattern.fromAngles("aqwqawaaqa", HexDir.WEST), new OpCircleBounds(true))); + + // == Modify Stack == + + public static final ActionRegistryEntry SWAP = + make( + "swap", + new ActionRegistryEntry( + HexPattern.fromAngles("aawdd", HexDir.EAST), new OpTwiddling(2, new int[] {1, 0}))); + public static final ActionRegistryEntry ROTATE = + make( + "rotate", + new ActionRegistryEntry( + HexPattern.fromAngles("aaeaa", HexDir.EAST), + new OpTwiddling(3, new int[] {1, 2, 0}))); + public static final ActionRegistryEntry ROTATE_REVERSE = + make( + "rotate_reverse", + new ActionRegistryEntry( + HexPattern.fromAngles("ddqdd", HexDir.NORTH_EAST), + new OpTwiddling(3, new int[] {2, 0, 1}))); + public static final ActionRegistryEntry DUPLICATE = + make( + "duplicate", + new ActionRegistryEntry( + HexPattern.fromAngles("aadaa", HexDir.EAST), new OpTwiddling(1, new int[] {0, 0}))); + public static final ActionRegistryEntry OVER = + make( + "over", + new ActionRegistryEntry( + HexPattern.fromAngles("aaedd", HexDir.EAST), + new OpTwiddling(2, new int[] {0, 1, 0}))); + public static final ActionRegistryEntry TUCK = + make( + "tuck", + new ActionRegistryEntry( + HexPattern.fromAngles("ddqaa", HexDir.EAST), + new OpTwiddling(2, new int[] {1, 0, 1}))); + public static final ActionRegistryEntry TWO_DUP = + make( + "2dup", + new ActionRegistryEntry( + HexPattern.fromAngles("aadadaaw", HexDir.EAST), + new OpTwiddling(2, new int[] {0, 1, 0, 1}))); + + public static final ActionRegistryEntry STACK_LEN = + make( + "stack_len", + new ActionRegistryEntry( + HexPattern.fromAngles("qwaeawqaeaqa", HexDir.NORTH_WEST), OpStackSize.INSTANCE)); + public static final ActionRegistryEntry DUPLICATE_N = + make( + "duplicate_n", + new ActionRegistryEntry( + HexPattern.fromAngles("aadaadaa", HexDir.EAST), OpDuplicateN.INSTANCE)); + public static final ActionRegistryEntry FISHERMAN = + make( + "fisherman", + new ActionRegistryEntry( + HexPattern.fromAngles("ddad", HexDir.WEST), OpFisherman.INSTANCE)); + public static final ActionRegistryEntry FISHERMAN$COPY = + make( + "fisherman/copy", + new ActionRegistryEntry( + HexPattern.fromAngles("aada", HexDir.EAST), OpFishermanButItCopies.INSTANCE)); + public static final ActionRegistryEntry SWIZZLE = + make( + "swizzle", + new ActionRegistryEntry( + HexPattern.fromAngles("qaawdde", HexDir.SOUTH_EAST), + OpAlwinfyHasAscendedToABeingOfPureMath.INSTANCE)); + + // == Math == + + public static final ActionRegistryEntry ADD = + make("add", new OperationAction(HexPattern.fromAngles("waaw", HexDir.NORTH_EAST))); + public static final ActionRegistryEntry SUB = + make("sub", new OperationAction(HexPattern.fromAngles("wddw", HexDir.NORTH_WEST))); + public static final ActionRegistryEntry MUL_DOT = + make("mul", new OperationAction(HexPattern.fromAngles("waqaw", HexDir.SOUTH_EAST))); + public static final ActionRegistryEntry DIV_CROSS = + make("div", new OperationAction(HexPattern.fromAngles("wdedw", HexDir.NORTH_EAST))); + public static final ActionRegistryEntry ABS = + make("abs", new OperationAction(HexPattern.fromAngles("wqaqw", HexDir.NORTH_EAST))); + public static final ActionRegistryEntry POW_PROJ = + make("pow", new OperationAction(HexPattern.fromAngles("wedew", HexDir.NORTH_WEST))); + public static final ActionRegistryEntry FLOOR = + make("floor", new OperationAction(HexPattern.fromAngles("ewq", HexDir.EAST))); + public static final ActionRegistryEntry CEIL = + make("ceil", new OperationAction(HexPattern.fromAngles("qwe", HexDir.EAST))); + + public static final ActionRegistryEntry CONSTRUCT_VEC = + make("construct_vec", new OperationAction(HexPattern.fromAngles("eqqqqq", HexDir.EAST))); + public static final ActionRegistryEntry DECONSTRUCT_VEC = + make("deconstruct_vec", new OperationAction(HexPattern.fromAngles("qeeeee", HexDir.EAST))); + public static final ActionRegistryEntry COERCE_AXIAL = + make( + "coerce_axial", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqaww", HexDir.NORTH_WEST), OpCoerceToAxial.INSTANCE)); + + // == Logic == + + public static final ActionRegistryEntry AND = + make("and", new OperationAction(HexPattern.fromAngles("wdw", HexDir.NORTH_EAST))); + public static final ActionRegistryEntry OR = + make("or", new OperationAction(HexPattern.fromAngles("waw", HexDir.SOUTH_EAST))); + public static final ActionRegistryEntry XOR = + make("xor", new OperationAction(HexPattern.fromAngles("dwa", HexDir.NORTH_WEST))); + public static final ActionRegistryEntry GREATER = + make("greater", new OperationAction(HexPattern.fromAngles("e", HexDir.SOUTH_EAST))); + public static final ActionRegistryEntry LESS = + make("less", new OperationAction(HexPattern.fromAngles("q", HexDir.SOUTH_WEST))); + public static final ActionRegistryEntry GREATER_EQ = + make("greater_eq", new OperationAction(HexPattern.fromAngles("ee", HexDir.SOUTH_EAST))); + public static final ActionRegistryEntry LESS_EQ = + make("less_eq", new OperationAction(HexPattern.fromAngles("qq", HexDir.SOUTH_WEST))); + public static final ActionRegistryEntry EQUALS = + make( + "equals", + new ActionRegistryEntry(HexPattern.fromAngles("ad", HexDir.EAST), new OpEquality(false))); + public static final ActionRegistryEntry NOT_EQUALS = + make( + "not_equals", + new ActionRegistryEntry(HexPattern.fromAngles("da", HexDir.EAST), new OpEquality(true))); + public static final ActionRegistryEntry NOT = + make( + "not", + new ActionRegistryEntry( + HexPattern.fromAngles("dw", HexDir.NORTH_WEST), OpBoolNot.INSTANCE)); + public static final ActionRegistryEntry BOOL_COERCE = + make( + "bool_coerce", + new ActionRegistryEntry( + HexPattern.fromAngles("aw", HexDir.NORTH_EAST), OpCoerceToBool.INSTANCE)); + public static final ActionRegistryEntry IF = + make( + "if", + new ActionRegistryEntry( + HexPattern.fromAngles("awdd", HexDir.SOUTH_EAST), OpBoolIf.INSTANCE)); + + public static final ActionRegistryEntry RANDOM = + make( + "random", + new ActionRegistryEntry( + HexPattern.fromAngles("eqqq", HexDir.NORTH_WEST), OpRandom.INSTANCE)); + + // == Advanced Math == + + public static final ActionRegistryEntry SIN = + make("sin", new OperationAction(HexPattern.fromAngles("qqqqqaa", HexDir.SOUTH_EAST))); + public static final ActionRegistryEntry COS = + make("cos", new OperationAction(HexPattern.fromAngles("qqqqqad", HexDir.SOUTH_EAST))); + public static final ActionRegistryEntry TAN = + make("tan", new OperationAction(HexPattern.fromAngles("wqqqqqadq", HexDir.SOUTH_WEST))); + public static final ActionRegistryEntry ARCSIN = + make("arcsin", new OperationAction(HexPattern.fromAngles("ddeeeee", HexDir.SOUTH_EAST))); + public static final ActionRegistryEntry ARCCOS = + make("arccos", new OperationAction(HexPattern.fromAngles("adeeeee", HexDir.NORTH_EAST))); + public static final ActionRegistryEntry ARCTAN = + make("arctan", new OperationAction(HexPattern.fromAngles("eadeeeeew", HexDir.NORTH_EAST))); + public static final ActionRegistryEntry ARCTAN2 = + make("arctan2", new OperationAction(HexPattern.fromAngles("deadeeeeewd", HexDir.WEST))); + public static final ActionRegistryEntry LOGARITHM = + make("logarithm", new OperationAction(HexPattern.fromAngles("eqaqe", HexDir.NORTH_WEST))); + public static final ActionRegistryEntry MODULO = + make("modulo", new OperationAction(HexPattern.fromAngles("addwaad", HexDir.NORTH_EAST))); + + // == Sets == + + public static final ActionRegistryEntry UNIQUE = + make("unique", new OperationAction(HexPattern.fromAngles("aweaqa", HexDir.NORTH_EAST))); + + // == Spells == + + public static final ActionRegistryEntry PRINT = + make( + "print", + new ActionRegistryEntry( + HexPattern.fromAngles("de", HexDir.NORTH_EAST), OpPrint.INSTANCE)); + public static final ActionRegistryEntry EXPLODE = + make( + "explode", + new ActionRegistryEntry( + HexPattern.fromAngles("aawaawaa", HexDir.EAST), new OpExplode(false))); + public static final ActionRegistryEntry EXPLODE$FIRE = + make( + "explode/fire", + new ActionRegistryEntry( + HexPattern.fromAngles("ddwddwdd", HexDir.EAST), new OpExplode(true))); + public static final ActionRegistryEntry ADD_MOTION = + make( + "add_motion", + new ActionRegistryEntry( + HexPattern.fromAngles("awqqqwaqw", HexDir.SOUTH_WEST), OpAddMotion.INSTANCE)); + public static final ActionRegistryEntry BLINK = + make( + "blink", + new ActionRegistryEntry( + HexPattern.fromAngles("awqqqwaq", HexDir.SOUTH_WEST), OpBlink.INSTANCE)); + public static final ActionRegistryEntry BREAK_BLOCK = + make( + "break_block", + new ActionRegistryEntry( + HexPattern.fromAngles("qaqqqqq", HexDir.EAST), OpBreakBlock.INSTANCE)); + public static final ActionRegistryEntry PLACE_BLOCK = + make( + "place_block", + new ActionRegistryEntry( + HexPattern.fromAngles("eeeeede", HexDir.SOUTH_WEST), OpPlaceBlock.INSTANCE)); + public static final ActionRegistryEntry COLORIZE = + make( + "colorize", + new ActionRegistryEntry( + HexPattern.fromAngles("awddwqawqwawq", HexDir.EAST), OpColorize.INSTANCE)); + public static final ActionRegistryEntry CYCLE_VARIANT = + make( + "cycle_variant", + new ActionRegistryEntry( + HexPattern.fromAngles("dwaawedwewdwe", HexDir.WEST), OpCycleVariant.INSTANCE)); + public static final ActionRegistryEntry CREATE_WATER = + make( + "create_water", + new ActionRegistryEntry( + HexPattern.fromAngles("aqawqadaq", HexDir.SOUTH_EAST), + new OpCreateFluid( + MediaConstants.DUST_UNIT, + Items.WATER_BUCKET, + Blocks.WATER_CAULDRON + .defaultBlockState() + .setValue(LayeredCauldronBlock.LEVEL, LayeredCauldronBlock.MAX_FILL_LEVEL), + Fluids.WATER))); + public static final ActionRegistryEntry DESTROY_WATER = + make( + "destroy_water", + new ActionRegistryEntry( + HexPattern.fromAngles("dedwedade", HexDir.SOUTH_WEST), OpDestroyFluid.INSTANCE)); + public static final ActionRegistryEntry IGNITE = + make( + "ignite", + new ActionRegistryEntry( + HexPattern.fromAngles("aaqawawa", HexDir.SOUTH_EAST), OpIgnite.INSTANCE)); + public static final ActionRegistryEntry EXTINGUISH = + make( + "extinguish", + new ActionRegistryEntry( + HexPattern.fromAngles("ddedwdwd", HexDir.SOUTH_WEST), OpExtinguish.INSTANCE)); + public static final ActionRegistryEntry CONJURE_BLOCK = + make( + "conjure_block", + new ActionRegistryEntry( + HexPattern.fromAngles("qqa", HexDir.NORTH_EAST), new OpConjureBlock(false))); + public static final ActionRegistryEntry CONJURE_LIGHT = + make( + "conjure_light", + new ActionRegistryEntry( + HexPattern.fromAngles("qqd", HexDir.NORTH_EAST), new OpConjureBlock(true))); + public static final ActionRegistryEntry BONEMEAL = + make( + "bonemeal", + new ActionRegistryEntry( + HexPattern.fromAngles("wqaqwawqaqw", HexDir.NORTH_EAST), + OpTheOnlyReasonAnyoneDownloadedPsi.INSTANCE)); + public static final ActionRegistryEntry RECHARGE = + make( + "recharge", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqwaeaeaeaeaea", HexDir.NORTH_WEST), OpRecharge.INSTANCE)); + public static final ActionRegistryEntry ERASE = + make( + "erase", + new ActionRegistryEntry( + HexPattern.fromAngles("qdqawwaww", HexDir.EAST), OpErase.INSTANCE)); + public static final ActionRegistryEntry EDIFY = + make( + "edify", + new ActionRegistryEntry( + HexPattern.fromAngles("wqaqwd", HexDir.NORTH_EAST), OpEdifySapling.INSTANCE)); + + public static final ActionRegistryEntry BEEP = + make( + "beep", + new ActionRegistryEntry(HexPattern.fromAngles("adaa", HexDir.WEST), OpBeep.INSTANCE)); + + public static final ActionRegistryEntry CRAFT$CYPHER = + make( + "craft/cypher", + new ActionRegistryEntry( + HexPattern.fromAngles("waqqqqq", HexDir.EAST), + new OpMakePackagedSpell<>(HexItems.CYPHER, MediaConstants.CRYSTAL_UNIT))); + public static final ActionRegistryEntry CRAFT$TRINKET = + make( + "craft/trinket", + new ActionRegistryEntry( + HexPattern.fromAngles("wwaqqqqqeaqeaeqqqeaeq", HexDir.EAST), + new OpMakePackagedSpell<>(HexItems.TRINKET, 5 * MediaConstants.CRYSTAL_UNIT))); + public static final ActionRegistryEntry CRAFT$ARTIFACT = + make( + "craft/artifact", + new ActionRegistryEntry( + HexPattern.fromAngles("wwaqqqqqeawqwqwqwqwqwwqqeadaeqqeqqeadaeqq", HexDir.EAST), + new OpMakePackagedSpell<>(HexItems.ARTIFACT, 10 * MediaConstants.CRYSTAL_UNIT))); + public static final ActionRegistryEntry CRAFT$BATTERY = + make( + "craft/battery", + new ActionRegistryEntry( + HexPattern.fromAngles("aqqqaqwwaqqqqqeqaqqqawwqwqwqwqwqw", HexDir.SOUTH_WEST), + OpMakeBattery.INSTANCE)); + + public static final ActionRegistryEntry POTION$WEAKNESS = + make( + "potion/weakness", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqaqwawaw", HexDir.NORTH_WEST), + new OpPotionEffect(MobEffects.WEAKNESS, MediaConstants.DUST_UNIT / 10, true, false))); + public static final ActionRegistryEntry POTION$LEVITATION = + make( + "potion/levitation", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqawwawawd", HexDir.WEST), + new OpPotionEffect( + MobEffects.LEVITATION, MediaConstants.DUST_UNIT / 5, false, false))); + public static final ActionRegistryEntry POTION$WITHER = + make( + "potion/wither", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqaewawawe", HexDir.SOUTH_WEST), + new OpPotionEffect(MobEffects.WITHER, MediaConstants.DUST_UNIT, true, false))); + public static final ActionRegistryEntry POTION$POISON = + make( + "potion/poison", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqadwawaww", HexDir.SOUTH_EAST), + new OpPotionEffect(MobEffects.POISON, MediaConstants.DUST_UNIT / 3, true, false))); + public static final ActionRegistryEntry POTION$SLOWNESS = + make( + "potion/slowness", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqadwawaw", HexDir.SOUTH_EAST), + new OpPotionEffect( + MobEffects.MOVEMENT_SLOWDOWN, MediaConstants.DUST_UNIT / 3, true, false))); + + public static final ActionRegistryEntry POTION$REGENERATION = + make( + "potion/regeneration", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqaawawaedd", HexDir.NORTH_WEST), + new OpPotionEffect(MobEffects.REGENERATION, MediaConstants.DUST_UNIT, true, true))); + public static final ActionRegistryEntry POTION$NIGHT_VISION = + make( + "potion/night_vision", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqaawawaeqdd", HexDir.WEST), + new OpPotionEffect( + MobEffects.NIGHT_VISION, MediaConstants.DUST_UNIT / 5, false, true))); + public static final ActionRegistryEntry POTION$ABSORPTION = + make( + "potion/absorption", + new ActionRegistryEntry( + HexPattern.fromAngles("qqaawawaeqqdd", HexDir.SOUTH_WEST), + new OpPotionEffect(MobEffects.ABSORPTION, MediaConstants.DUST_UNIT, true, true))); + public static final ActionRegistryEntry POTION$HASTE = + make( + "potion/haste", + new ActionRegistryEntry( + HexPattern.fromAngles("qaawawaeqqqdd", HexDir.SOUTH_EAST), + new OpPotionEffect(MobEffects.DIG_SPEED, MediaConstants.DUST_UNIT / 3, true, true))); + public static final ActionRegistryEntry POTION$STRENGTH = + make( + "potion/strength", + new ActionRegistryEntry( + HexPattern.fromAngles("aawawaeqqqqdd", HexDir.EAST), + new OpPotionEffect( + MobEffects.DAMAGE_BOOST, MediaConstants.DUST_UNIT / 3, true, true))); + + public static final ActionRegistryEntry FLIGHT$RANGE = + make( + "flight/range", + new ActionRegistryEntry( + HexPattern.fromAngles("awawaawq", HexDir.SOUTH_WEST), + new OpFlight(OpFlight.Type.LimitRange))); + public static final ActionRegistryEntry FLIGHT$TIME = + make( + "flight/time", + new ActionRegistryEntry( + HexPattern.fromAngles("dwdwdewq", HexDir.NORTH_EAST), + new OpFlight(OpFlight.Type.LimitTime))); + + public static final ActionRegistryEntry SENTINEL$CREATE = + make( + "sentinel/create", + new ActionRegistryEntry( + HexPattern.fromAngles("waeawae", HexDir.EAST), new OpCreateSentinel(false))); + public static final ActionRegistryEntry SENTINEL$DESTROY = + make( + "sentinel/destroy", + new ActionRegistryEntry( + HexPattern.fromAngles("qdwdqdw", HexDir.NORTH_EAST), OpDestroySentinel.INSTANCE)); + public static final ActionRegistryEntry SENTINEL$GET_POS = + make( + "sentinel/get_pos", + new ActionRegistryEntry( + HexPattern.fromAngles("waeawaede", HexDir.EAST), OpGetSentinelPos.INSTANCE)); + public static final ActionRegistryEntry SENTINEL$WAYFIND = + make( + "sentinel/wayfind", + new ActionRegistryEntry( + HexPattern.fromAngles("waeawaedwa", HexDir.EAST), OpGetSentinelWayfind.INSTANCE)); + + public static final ActionRegistryEntry LIGHTNING = + make( + "lightning", + new ActionRegistryEntry( + HexPattern.fromAngles("waadwawdaaweewq", HexDir.EAST), OpLightning.INSTANCE)); + + public static final ActionRegistryEntry ALTIORA = + make( + "flight", + new ActionRegistryEntry( + HexPattern.fromAngles("eawwaeawawaa", HexDir.NORTH_WEST), OpAltiora.INSTANCE)); + + public static final ActionRegistryEntry CREATE_LAVA = + make( + "create_lava", + new ActionRegistryEntry( + HexPattern.fromAngles("eaqawqadaqd", HexDir.EAST), + new OpCreateFluid( + MediaConstants.CRYSTAL_UNIT, + Items.LAVA_BUCKET, + Blocks.LAVA_CAULDRON.defaultBlockState(), + Fluids.LAVA))); + public static final ActionRegistryEntry TELEPORT = + make( + "teleport/great", + new ActionRegistryEntry( + HexPattern.fromAngles("wwwqqqwwwqqeqqwwwqqwqqdqqqqqdqq", HexDir.EAST), + OpTeleport.INSTANCE)); + public static final ActionRegistryEntry SENTINEL$GREAT = + make( + "sentinel/create/great", + new ActionRegistryEntry( + HexPattern.fromAngles("waeawaeqqqwqwqqwq", HexDir.EAST), new OpCreateSentinel(true))); + public static final ActionRegistryEntry DISPEL_RAIN = + make( + "dispel_rain", + new ActionRegistryEntry( + HexPattern.fromAngles("eeewwweeewwaqqddqdqd", HexDir.EAST), new OpWeather(false))); + public static final ActionRegistryEntry SUMMON_RAIN = + make( + "summon_rain", + new ActionRegistryEntry( + HexPattern.fromAngles("wwweeewwweewdawdwad", HexDir.WEST), new OpWeather(true))); + public static final ActionRegistryEntry BRAINSWEEP = + make( + "brainsweep", + new ActionRegistryEntry( + HexPattern.fromAngles("qeqwqwqwqwqeqaeqeaqeqaeqaqded", HexDir.NORTH_EAST), + OpBrainsweep.INSTANCE)); + + public static final ActionRegistryEntry AKASHIC$READ = + make( + "akashic/read", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqwqqqqqaq", HexDir.WEST), OpAkashicRead.INSTANCE)); + public static final ActionRegistryEntry AKASHIC$WRITE = + make( + "akashic/write", + new ActionRegistryEntry( + HexPattern.fromAngles("eeeweeeeede", HexDir.EAST), OpAkashicWrite.INSTANCE)); + + // == Meta stuff == + + // Intro/Retro/Consideration are now special-form-likes and aren't even ops. + // TODO should there be a registry for these too + + // http://www.toroidalsnark.net/mkss3-pix/CalderheadJMM2014.pdf + // eval being a space filling curve feels apt doesn't it + public static final ActionRegistryEntry EVAL = + make( + "eval", + new ActionRegistryEntry( + HexPattern.fromAngles("deaqq", HexDir.SOUTH_EAST), OpEval.INSTANCE)); + public static final ActionRegistryEntry EVAL$CC = + make( + "eval/cc", + new ActionRegistryEntry( + HexPattern.fromAngles("qwaqde", HexDir.NORTH_WEST), OpEvalBreakable.INSTANCE)); + public static final ActionRegistryEntry HALT = + make( + "halt", + new ActionRegistryEntry( + HexPattern.fromAngles("aqdee", HexDir.SOUTH_WEST), OpHalt.INSTANCE)); + + public static final ActionRegistryEntry READ = + make( + "read", + new ActionRegistryEntry(HexPattern.fromAngles("aqqqqq", HexDir.EAST), OpRead.INSTANCE)); + public static final ActionRegistryEntry READ$ENTITY = + make( + "read/entity", + new ActionRegistryEntry( + HexPattern.fromAngles("wawqwqwqwqwqw", HexDir.EAST), OpTheCoolerRead.INSTANCE)); + public static final ActionRegistryEntry WRITE = + make( + "write", + new ActionRegistryEntry(HexPattern.fromAngles("deeeee", HexDir.EAST), OpWrite.INSTANCE)); + public static final ActionRegistryEntry WRITE$ENTITY = + make( + "write/entity", + new ActionRegistryEntry( + HexPattern.fromAngles("wdwewewewewew", HexDir.EAST), OpTheCoolerWrite.INSTANCE)); + public static final ActionRegistryEntry READABLE = + make( + "readable", + new ActionRegistryEntry( + HexPattern.fromAngles("aqqqqqe", HexDir.EAST), OpReadable.INSTANCE)); + public static final ActionRegistryEntry READABLE$ENTITY = + make( + "readable/entity", + new ActionRegistryEntry( + HexPattern.fromAngles("wawqwqwqwqwqwew", HexDir.EAST), OpTheCoolerReadable.INSTANCE)); + public static final ActionRegistryEntry WRITABLE = + make( + "writable", + new ActionRegistryEntry( + HexPattern.fromAngles("deeeeeq", HexDir.EAST), OpWritable.INSTANCE)); + public static final ActionRegistryEntry WRITABLE$ENTITY = + make( + "writable/entity", + new ActionRegistryEntry( + HexPattern.fromAngles("wdwewewewewewqw", HexDir.EAST), OpTheCoolerWritable.INSTANCE)); + + public static final ActionRegistryEntry READ$LOCAL = + make( + "read/local", + new ActionRegistryEntry( + HexPattern.fromAngles("qeewdweddw", HexDir.NORTH_EAST), OpPeekLocal.INSTANCE)); + public static final ActionRegistryEntry WRITE$LOCAL = + make( + "write/local", + new ActionRegistryEntry( + HexPattern.fromAngles("eqqwawqaaw", HexDir.NORTH_WEST), OpPushLocal.INSTANCE)); + + public static final ActionRegistryEntry THANATOS = + make( + "thanatos", + new ActionRegistryEntry( + HexPattern.fromAngles("qqaed", HexDir.SOUTH_EAST), OpThanos.INSTANCE)); + + // == Consts == + + public static final ActionRegistryEntry CONST$NULL = + make( + "const/null", + new ActionRegistryEntry( + HexPattern.fromAngles("d", HexDir.EAST), Action.makeConstantOp(new NullIota()))); + + public static final ActionRegistryEntry CONST$TRUE = + make( + "const/true", + new ActionRegistryEntry( + HexPattern.fromAngles("aqae", HexDir.SOUTH_EAST), + Action.makeConstantOp(new BooleanIota(true)))); + public static final ActionRegistryEntry CONST$FALSE = + make( + "const/false", + new ActionRegistryEntry( + HexPattern.fromAngles("dedq", HexDir.NORTH_EAST), + Action.makeConstantOp(new BooleanIota(false)))); + + public static final ActionRegistryEntry CONST$VEC$PX = + make( + "const/vec/px", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqea", HexDir.NORTH_WEST), + Action.makeConstantOp(new Vec3Iota(new Vec3(1.0, 0.0, 0.0))))); + public static final ActionRegistryEntry CONST$VEC$PY = + make( + "const/vec/py", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqew", HexDir.NORTH_WEST), + Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 1.0, 0.0))))); + public static final ActionRegistryEntry CONST$VEC$PZ = + make( + "const/vec/pz", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqed", HexDir.NORTH_WEST), + Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 0.0, 1.0))))); + public static final ActionRegistryEntry CONST$VEC$NX = + make( + "const/vec/nx", + new ActionRegistryEntry( + HexPattern.fromAngles("eeeeeqa", HexDir.SOUTH_WEST), + Action.makeConstantOp(new Vec3Iota(new Vec3(-1.0, 0.0, 0.0))))); + public static final ActionRegistryEntry CONST$VEC$NY = + make( + "const/vec/ny", + new ActionRegistryEntry( + HexPattern.fromAngles("eeeeeqw", HexDir.SOUTH_WEST), + Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, -1.0, 0.0))))); + public static final ActionRegistryEntry CONST$VEC$NZ = + make( + "const/vec/nz", + new ActionRegistryEntry( + HexPattern.fromAngles("eeeeeqd", HexDir.SOUTH_WEST), + Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 0.0, -1.0))))); + // Yep, this is what I spend the "plain hexagon" pattern on. + public static final ActionRegistryEntry CONST$VEC$0 = + make( + "const/vec/0", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqq", HexDir.NORTH_WEST), + Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 0.0, 0.0))))); + + public static final ActionRegistryEntry CONST$DOUBLE$PI = + make( + "const/double/pi", + new ActionRegistryEntry( + HexPattern.fromAngles("qdwdq", HexDir.NORTH_EAST), + Action.makeConstantOp(new DoubleIota(Math.PI)))); + public static final ActionRegistryEntry CONST$DOUBLE$TAU = + make( + "const/double/tau", + new ActionRegistryEntry( + HexPattern.fromAngles("eawae", HexDir.NORTH_WEST), + Action.makeConstantOp(new DoubleIota(HexUtils.TAU)))); + public static final ActionRegistryEntry CONST$E = + make( + "const/double/e", + new ActionRegistryEntry( + HexPattern.fromAngles("aaq", HexDir.EAST), + Action.makeConstantOp(new DoubleIota(Math.E)))); + + // == Entities == + + public static final ActionRegistryEntry GET_ENTITY = + make( + "get_entity", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqdaqa", HexDir.SOUTH_EAST), new OpGetEntityAt(e -> true))); + public static final ActionRegistryEntry GET_ENTITY$ANIMAL = + make( + "get_entity/animal", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqdaqaawa", HexDir.SOUTH_EAST), + new OpGetEntityAt(OpGetEntitiesBy::isAnimal))); + public static final ActionRegistryEntry GET_ENTITY$MONSTER = + make( + "get_entity/monster", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqdaqaawq", HexDir.SOUTH_EAST), + new OpGetEntityAt(OpGetEntitiesBy::isMonster))); + public static final ActionRegistryEntry GET_ENTITY$ITEM = + make( + "get_entity/item", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqdaqaaww", HexDir.SOUTH_EAST), + new OpGetEntityAt(OpGetEntitiesBy::isItem))); + public static final ActionRegistryEntry GET_ENTITY$PLAYER = + make( + "get_entity/player", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqdaqaawe", HexDir.SOUTH_EAST), + new OpGetEntityAt(OpGetEntitiesBy::isPlayer))); + public static final ActionRegistryEntry GET_ENTITY$LIVING = + make( + "get_entity/living", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqdaqaawd", HexDir.SOUTH_EAST), + new OpGetEntityAt(OpGetEntitiesBy::isLiving))); + + public static final ActionRegistryEntry ZONE_ENTITY = + make( + "zone_entity", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqwded", HexDir.SOUTH_EAST), + new OpGetEntitiesBy(e -> true, false))); + public static final ActionRegistryEntry ZONE_ENTITY$ANIMAL = + make( + "zone_entity/animal", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqwdeddwa", HexDir.SOUTH_EAST), + new OpGetEntitiesBy(OpGetEntitiesBy::isAnimal, false))); + public static final ActionRegistryEntry ZONE_ENTITY$NOT_ANIMAL = + make( + "zone_entity/not_animal", + new ActionRegistryEntry( + HexPattern.fromAngles("eeeeewaqaawa", HexDir.NORTH_EAST), + new OpGetEntitiesBy(OpGetEntitiesBy::isAnimal, true))); + public static final ActionRegistryEntry ZONE_ENTITY$MONSTER = + make( + "zone_entity/monster", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqwdeddwq", HexDir.SOUTH_EAST), + new OpGetEntitiesBy(OpGetEntitiesBy::isMonster, false))); + public static final ActionRegistryEntry ZONE_ENTITY$NOT_MONSTER = + make( + "zone_entity/not_monster", + new ActionRegistryEntry( + HexPattern.fromAngles("eeeeewaqaawq", HexDir.NORTH_EAST), + new OpGetEntitiesBy(OpGetEntitiesBy::isMonster, true))); + public static final ActionRegistryEntry ZONE_ENTITY$ITEM = + make( + "zone_entity/item", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqwdeddww", HexDir.SOUTH_EAST), + new OpGetEntitiesBy(OpGetEntitiesBy::isItem, false))); + public static final ActionRegistryEntry ZONE_ENTITY$NOT_ITEM = + make( + "zone_entity/not_item", + new ActionRegistryEntry( + HexPattern.fromAngles("eeeeewaqaaww", HexDir.NORTH_EAST), + new OpGetEntitiesBy(OpGetEntitiesBy::isItem, true))); + public static final ActionRegistryEntry ZONE_ENTITY$PLAYER = + make( + "zone_entity/player", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqwdeddwe", HexDir.SOUTH_EAST), + new OpGetEntitiesBy(OpGetEntitiesBy::isPlayer, false))); + public static final ActionRegistryEntry ZONE_ENTITY$NOT_PLAYER = + make( + "zone_entity/not_player", + new ActionRegistryEntry( + HexPattern.fromAngles("eeeeewaqaawe", HexDir.NORTH_EAST), + new OpGetEntitiesBy(OpGetEntitiesBy::isPlayer, true))); + public static final ActionRegistryEntry ZONE_ENTITY$LIVING = + make( + "zone_entity/living", + new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqwdeddwd", HexDir.SOUTH_EAST), + new OpGetEntitiesBy(OpGetEntitiesBy::isLiving, false))); + public static final ActionRegistryEntry ZONE_ENTITY$NOT_LIVING = + make( + "zone_entity/not_living", + new ActionRegistryEntry( + HexPattern.fromAngles("eeeeewaqaawd", HexDir.NORTH_EAST), + new OpGetEntitiesBy(OpGetEntitiesBy::isLiving, true))); + + // == Lists == + + public static final ActionRegistryEntry APPEND = + make("append", new OperationAction(HexPattern.fromAngles("edqde", HexDir.SOUTH_WEST))); + public static final ActionRegistryEntry UNAPPEND = + make("unappend", new OperationAction(HexPattern.fromAngles("qaeaq", HexDir.NORTH_WEST))); + // public static final ActionRegistryEntry CONCAT = make("concat", + // new ActionRegistryEntry(HexPattern.fromAngles("qaeaq", HexDir.NORTH_WEST), + // OpConcat.INSTANCE)); + public static final ActionRegistryEntry INDEX = + make("index", new OperationAction(HexPattern.fromAngles("deeed", HexDir.NORTH_WEST))); + public static final ActionRegistryEntry FOR_EACH = + make( + "for_each", + new ActionRegistryEntry( + HexPattern.fromAngles("dadad", HexDir.NORTH_EAST), OpForEach.INSTANCE)); + // public static final ActionRegistryEntry LIST_SIZE = make("list_size", + // new ActionRegistryEntry(HexPattern.fromAngles("aqaeaq", HexDir.EAST), + // OpListSize.INSTANCE)); + public static final ActionRegistryEntry SINGLETON = + make( + "singleton", + new ActionRegistryEntry( + HexPattern.fromAngles("adeeed", HexDir.EAST), OpSingleton.INSTANCE)); + public static final ActionRegistryEntry EMPTY_LIST = + make( + "empty_list", + new ActionRegistryEntry( + HexPattern.fromAngles("qqaeaae", HexDir.NORTH_EAST), OpEmptyList.INSTANCE)); + public static final ActionRegistryEntry REVERSE = + make("reverse", new OperationAction(HexPattern.fromAngles("qqqaede", HexDir.EAST))); + public static final ActionRegistryEntry LAST_N_LIST = + make( + "last_n_list", + new ActionRegistryEntry( + HexPattern.fromAngles("ewdqdwe", HexDir.SOUTH_WEST), OpLastNToList.INSTANCE)); + public static final ActionRegistryEntry SPLAT = + make( + "splat", + new ActionRegistryEntry( + HexPattern.fromAngles("qwaeawq", HexDir.NORTH_WEST), OpSplat.INSTANCE)); + public static final ActionRegistryEntry INDEX_OF = + make("index_of", new OperationAction(HexPattern.fromAngles("dedqde", HexDir.EAST))); + public static final ActionRegistryEntry REMOVE_FROM = + make( + "remove_from", + new OperationAction(HexPattern.fromAngles("edqdewaqa", HexDir.SOUTH_WEST))); + public static final ActionRegistryEntry SLICE = + make("slice", new OperationAction(HexPattern.fromAngles("qaeaqwded", HexDir.NORTH_WEST))); + public static final ActionRegistryEntry REPLACE = + make("replace", new OperationAction(HexPattern.fromAngles("wqaeaqw", HexDir.NORTH_WEST))); + public static final ActionRegistryEntry CONSTRUCT = + make("construct", new OperationAction(HexPattern.fromAngles("ddewedd", HexDir.SOUTH_EAST))); + public static final ActionRegistryEntry DECONSTRUCT = + make("deconstruct", new OperationAction(HexPattern.fromAngles("aaqwqaa", HexDir.SOUTH_WEST))); + + // Xplat interops + static { + if (PehkuiInterop.isActive()) { + make( + "interop/pehkui/get", + new ActionRegistryEntry( + HexPattern.fromAngles("aawawwawwa", HexDir.NORTH_WEST), OpGetScale.INSTANCE)); + make( + "interop/pehkui/set", + new ActionRegistryEntry( + HexPattern.fromAngles("ddwdwwdwwd", HexDir.NORTH_EAST), OpSetScale.INSTANCE)); + } + } + + public static ActionRegistryEntry make(String name, ActionRegistryEntry are) { + var old = ACTIONS.put(modLoc(name), are); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + name); + } + return are; + } + + public static ActionRegistryEntry make(String name, OperationAction oa) { + var are = new ActionRegistryEntry(oa.getPattern(), oa); + var old = ACTIONS.put(modLoc(name), are); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + name); + } + return are; + } + + public static void register(BiConsumer<ActionRegistryEntry, ResourceLocation> r) { + for (var e : ACTIONS.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexArithmetics.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexArithmetics.java index f3feb0dad7..70d717c9be 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexArithmetics.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexArithmetics.java @@ -1,52 +1,55 @@ package at.petrak.hexcasting.common.lib.hex; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic; import at.petrak.hexcasting.api.casting.arithmetic.engine.ArithmeticEngine; import at.petrak.hexcasting.common.casting.arithmetic.*; import at.petrak.hexcasting.xplat.IXplatAbstractions; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; - import java.util.LinkedHashMap; import java.util.Map; import java.util.function.BiConsumer; import java.util.stream.Collectors; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; public class HexArithmetics { - private static ArithmeticEngine ENGINE; - - public static ArithmeticEngine getEngine() { - if (ENGINE == null) { - ENGINE = new ArithmeticEngine(REGISTRY.holders().map(Holder.Reference::value).collect(Collectors.toList())); - } - return ENGINE; - } - - public static final Registry<Arithmetic> REGISTRY = IXplatAbstractions.INSTANCE.getArithmeticRegistry(); - - public static void register(BiConsumer<Arithmetic, ResourceLocation> r) { - for (var e : ARITHMETICS.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } - - private static final Map<ResourceLocation, Arithmetic> ARITHMETICS = new LinkedHashMap<>(); - - public static DoubleArithmetic DOUBLE = make("double", DoubleArithmetic.INSTANCE); - public static Vec3Arithmetic VEC3 = make("vec3", Vec3Arithmetic.INSTANCE); - public static ListArithmetic LIST = make("list", ListArithmetic.INSTANCE); - public static BoolArithmetic BOOL = make("bool", BoolArithmetic.INSTANCE); - public static ListSetArithmetic LIST_SET = make("list_set", ListSetArithmetic.INSTANCE); - public static BitwiseSetArithmetic BITWISE_SET = make("bitwise_set", BitwiseSetArithmetic.INSTANCE); - - private static <T extends Arithmetic> T make(String name, T arithmetic) { - var old = ARITHMETICS.put(modLoc(name), arithmetic); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + name); - } - return arithmetic; - } + private static ArithmeticEngine ENGINE; + + public static ArithmeticEngine getEngine() { + if (ENGINE == null) { + ENGINE = + new ArithmeticEngine( + REGISTRY.holders().map(Holder.Reference::value).collect(Collectors.toList())); + } + return ENGINE; + } + + public static final Registry<Arithmetic> REGISTRY = + IXplatAbstractions.INSTANCE.getArithmeticRegistry(); + + public static void register(BiConsumer<Arithmetic, ResourceLocation> r) { + for (var e : ARITHMETICS.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } + + private static final Map<ResourceLocation, Arithmetic> ARITHMETICS = new LinkedHashMap<>(); + + public static DoubleArithmetic DOUBLE = make("double", DoubleArithmetic.INSTANCE); + public static Vec3Arithmetic VEC3 = make("vec3", Vec3Arithmetic.INSTANCE); + public static ListArithmetic LIST = make("list", ListArithmetic.INSTANCE); + public static BoolArithmetic BOOL = make("bool", BoolArithmetic.INSTANCE); + public static ListSetArithmetic LIST_SET = make("list_set", ListSetArithmetic.INSTANCE); + public static BitwiseSetArithmetic BITWISE_SET = + make("bitwise_set", BitwiseSetArithmetic.INSTANCE); + + private static <T extends Arithmetic> T make(String name, T arithmetic) { + var old = ARITHMETICS.put(modLoc(name), arithmetic); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + name); + } + return arithmetic; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexContinuationTypes.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexContinuationTypes.java index 5ec1d82125..884b8bd938 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexContinuationTypes.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexContinuationTypes.java @@ -1,49 +1,54 @@ package at.petrak.hexcasting.common.lib.hex; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.casting.eval.vm.ContinuationFrame; import at.petrak.hexcasting.api.casting.eval.vm.FrameEvaluate; import at.petrak.hexcasting.api.casting.eval.vm.FrameFinishEval; import at.petrak.hexcasting.api.casting.eval.vm.FrameForEach; import at.petrak.hexcasting.xplat.IXplatAbstractions; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; - -import javax.annotation.ParametersAreNonnullByDefault; import java.util.LinkedHashMap; import java.util.Map; import java.util.function.BiConsumer; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; +import javax.annotation.ParametersAreNonnullByDefault; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; /** - * Stores the registry for continuation frame types, some utility methods, and all the types Hexcasting itself defines. + * Stores the registry for continuation frame types, some utility methods, and all the types + * Hexcasting itself defines. */ @ParametersAreNonnullByDefault public class HexContinuationTypes { - public static final Registry<ContinuationFrame.Type<?>> REGISTRY = IXplatAbstractions.INSTANCE.getContinuationTypeRegistry(); - - public static final String - KEY_TYPE = HexAPI.MOD_ID + ":type", - KEY_DATA = HexAPI.MOD_ID + ":data"; - - public static void registerContinuations(BiConsumer<ContinuationFrame.Type<?>, ResourceLocation> r) { - for (var e : CONTINUATIONS.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } - - private static final Map<ResourceLocation, ContinuationFrame.Type<?>> CONTINUATIONS = new LinkedHashMap<>(); - - public static final ContinuationFrame.Type<FrameEvaluate> EVALUATE = continuation("evaluate", FrameEvaluate.TYPE); - public static final ContinuationFrame.Type<FrameForEach> FOREACH = continuation("foreach", FrameForEach.TYPE); - public static final ContinuationFrame.Type<FrameFinishEval> END = continuation("end", FrameFinishEval.TYPE); - - private static <U extends ContinuationFrame, T extends ContinuationFrame.Type<U>> T continuation(String name, T continuation) { - var old = CONTINUATIONS.put(modLoc(name), continuation); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + name); - } - return continuation; - } + public static final Registry<ContinuationFrame.Type<?>> REGISTRY = + IXplatAbstractions.INSTANCE.getContinuationTypeRegistry(); + + public static final String KEY_TYPE = HexAPI.MOD_ID + ":type", KEY_DATA = HexAPI.MOD_ID + ":data"; + + public static void registerContinuations( + BiConsumer<ContinuationFrame.Type<?>, ResourceLocation> r) { + for (var e : CONTINUATIONS.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } + + private static final Map<ResourceLocation, ContinuationFrame.Type<?>> CONTINUATIONS = + new LinkedHashMap<>(); + + public static final ContinuationFrame.Type<FrameEvaluate> EVALUATE = + continuation("evaluate", FrameEvaluate.TYPE); + public static final ContinuationFrame.Type<FrameForEach> FOREACH = + continuation("foreach", FrameForEach.TYPE); + public static final ContinuationFrame.Type<FrameFinishEval> END = + continuation("end", FrameFinishEval.TYPE); + + private static <U extends ContinuationFrame, T extends ContinuationFrame.Type<U>> T continuation( + String name, T continuation) { + var old = CONTINUATIONS.put(modLoc(name), continuation); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + name); + } + return continuation; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexEvalSounds.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexEvalSounds.java index fe322da59c..7213b3a9c1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexEvalSounds.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexEvalSounds.java @@ -1,47 +1,41 @@ package at.petrak.hexcasting.common.lib.hex; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.eval.sideeffects.EvalSound; import at.petrak.hexcasting.common.lib.HexSounds; -import net.minecraft.resources.ResourceLocation; - import java.util.LinkedHashMap; import java.util.Map; import java.util.function.BiConsumer; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; +import net.minecraft.resources.ResourceLocation; // TODO: we REALLY need a cleanup of how sounds work. again. public class HexEvalSounds { - private static final Map<ResourceLocation, EvalSound> SOUNDS = new LinkedHashMap<>(); - - public static final EvalSound NOTHING = make("nothing", - new EvalSound(null, Integer.MIN_VALUE)); - public static final EvalSound NORMAL_EXECUTE = make("operator", - new EvalSound(HexSounds.CAST_NORMAL, 0)); - public static final EvalSound SPELL = make("spell", - new EvalSound(HexSounds.CAST_SPELL, 1000)); - public static final EvalSound HERMES = make("hermes", - new EvalSound(HexSounds.CAST_HERMES, 2000)); - public static final EvalSound THOTH = make("thoth", - new EvalSound(HexSounds.CAST_THOTH, 2500)); - - public static final EvalSound MUTE = make("mute", - new EvalSound(null, 3000)); - - public static final EvalSound MISHAP = make("mishap", - new EvalSound(HexSounds.CAST_FAILURE, 4000)); - - private static EvalSound make(String name, EvalSound sound) { - var old = SOUNDS.put(modLoc(name), sound); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + name); - } - return sound; - } - - public static void register(BiConsumer<EvalSound, ResourceLocation> r) { - for (var e : SOUNDS.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } + private static final Map<ResourceLocation, EvalSound> SOUNDS = new LinkedHashMap<>(); + + public static final EvalSound NOTHING = make("nothing", new EvalSound(null, Integer.MIN_VALUE)); + public static final EvalSound NORMAL_EXECUTE = + make("operator", new EvalSound(HexSounds.CAST_NORMAL, 0)); + public static final EvalSound SPELL = make("spell", new EvalSound(HexSounds.CAST_SPELL, 1000)); + public static final EvalSound HERMES = make("hermes", new EvalSound(HexSounds.CAST_HERMES, 2000)); + public static final EvalSound THOTH = make("thoth", new EvalSound(HexSounds.CAST_THOTH, 2500)); + + public static final EvalSound MUTE = make("mute", new EvalSound(null, 3000)); + + public static final EvalSound MISHAP = + make("mishap", new EvalSound(HexSounds.CAST_FAILURE, 4000)); + + private static EvalSound make(String name, EvalSound sound) { + var old = SOUNDS.put(modLoc(name), sound); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + name); + } + return sound; + } + + public static void register(BiConsumer<EvalSound, ResourceLocation> r) { + for (var e : SOUNDS.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexIotaTypes.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexIotaTypes.java index 0526e9ac56..37887abd06 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexIotaTypes.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexIotaTypes.java @@ -1,54 +1,53 @@ package at.petrak.hexcasting.common.lib.hex; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.casting.iota.*; import at.petrak.hexcasting.xplat.IXplatAbstractions; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; - -import javax.annotation.ParametersAreNonnullByDefault; import java.util.LinkedHashMap; import java.util.Map; import java.util.function.BiConsumer; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; +import javax.annotation.ParametersAreNonnullByDefault; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; /** - * Stores the registry for iota types, some utility methods, and all the types Hexcasting itself defines. + * Stores the registry for iota types, some utility methods, and all the types Hexcasting itself + * defines. */ @ParametersAreNonnullByDefault public class HexIotaTypes { - public static final Registry<IotaType<?>> REGISTRY = IXplatAbstractions.INSTANCE.getIotaTypeRegistry(); - public static final String - KEY_TYPE = HexAPI.MOD_ID + ":type", - KEY_DATA = HexAPI.MOD_ID + ":data"; - public static final int MAX_SERIALIZATION_DEPTH = 256; - public static final int MAX_SERIALIZATION_TOTAL = 1024; - - public static void registerTypes(BiConsumer<IotaType<?>, ResourceLocation> r) { - for (var e : TYPES.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } - - private static final Map<ResourceLocation, IotaType<?>> TYPES = new LinkedHashMap<>(); - - public static final IotaType<NullIota> NULL = type("null", NullIota.TYPE); - public static final IotaType<DoubleIota> DOUBLE = type("double", DoubleIota.TYPE); - public static final IotaType<BooleanIota> BOOLEAN = type("boolean", BooleanIota.TYPE); - public static final IotaType<EntityIota> ENTITY = type("entity", EntityIota.TYPE); - public static final IotaType<ListIota> LIST = type("list", ListIota.TYPE); - public static final IotaType<PatternIota> PATTERN = type("pattern", PatternIota.TYPE); - public static final IotaType<GarbageIota> GARBAGE = type("garbage", GarbageIota.TYPE); - public static final IotaType<Vec3Iota> VEC3 = type("vec3", Vec3Iota.TYPE); - public static final IotaType<ContinuationIota> CONTINUATION = type("continuation", ContinuationIota.TYPE); - - - private static <U extends Iota, T extends IotaType<U>> T type(String name, T type) { - var old = TYPES.put(modLoc(name), type); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + name); - } - return type; - } + public static final Registry<IotaType<?>> REGISTRY = + IXplatAbstractions.INSTANCE.getIotaTypeRegistry(); + public static final String KEY_TYPE = HexAPI.MOD_ID + ":type", KEY_DATA = HexAPI.MOD_ID + ":data"; + public static final int MAX_SERIALIZATION_DEPTH = 256; + public static final int MAX_SERIALIZATION_TOTAL = 1024; + + public static void registerTypes(BiConsumer<IotaType<?>, ResourceLocation> r) { + for (var e : TYPES.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } + + private static final Map<ResourceLocation, IotaType<?>> TYPES = new LinkedHashMap<>(); + + public static final IotaType<NullIota> NULL = type("null", NullIota.TYPE); + public static final IotaType<DoubleIota> DOUBLE = type("double", DoubleIota.TYPE); + public static final IotaType<BooleanIota> BOOLEAN = type("boolean", BooleanIota.TYPE); + public static final IotaType<EntityIota> ENTITY = type("entity", EntityIota.TYPE); + public static final IotaType<ListIota> LIST = type("list", ListIota.TYPE); + public static final IotaType<PatternIota> PATTERN = type("pattern", PatternIota.TYPE); + public static final IotaType<GarbageIota> GARBAGE = type("garbage", GarbageIota.TYPE); + public static final IotaType<Vec3Iota> VEC3 = type("vec3", Vec3Iota.TYPE); + public static final IotaType<ContinuationIota> CONTINUATION = + type("continuation", ContinuationIota.TYPE); + + private static <U extends Iota, T extends IotaType<U>> T type(String name, T type) { + var old = TYPES.put(modLoc(name), type); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + name); + } + return type; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexSpecialHandlers.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexSpecialHandlers.java index c69fb9363c..801da985f6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexSpecialHandlers.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexSpecialHandlers.java @@ -1,36 +1,36 @@ package at.petrak.hexcasting.common.lib.hex; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.castables.SpecialHandler; import at.petrak.hexcasting.common.casting.actions.math.SpecialHandlerNumberLiteral; import at.petrak.hexcasting.common.casting.actions.stack.SpecialHandlerMask; -import net.minecraft.resources.ResourceLocation; - import java.util.LinkedHashMap; import java.util.Map; import java.util.function.BiConsumer; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; +import net.minecraft.resources.ResourceLocation; public class HexSpecialHandlers { - private static final Map<ResourceLocation, SpecialHandler.Factory<?>> SPECIAL_HANDLERS = new LinkedHashMap<>(); + private static final Map<ResourceLocation, SpecialHandler.Factory<?>> SPECIAL_HANDLERS = + new LinkedHashMap<>(); - public static final SpecialHandler.Factory<SpecialHandlerNumberLiteral> NUMBER = make("number", - new SpecialHandlerNumberLiteral.Factory()); - public static final SpecialHandler.Factory<SpecialHandlerMask> MASK = make("mask", - new SpecialHandlerMask.Factory()); + public static final SpecialHandler.Factory<SpecialHandlerNumberLiteral> NUMBER = + make("number", new SpecialHandlerNumberLiteral.Factory()); + public static final SpecialHandler.Factory<SpecialHandlerMask> MASK = + make("mask", new SpecialHandlerMask.Factory()); - private static <T extends SpecialHandler> SpecialHandler.Factory<T> make(String name, - SpecialHandler.Factory<T> handler) { - var old = SPECIAL_HANDLERS.put(modLoc(name), handler); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + name); - } - return handler; - } + private static <T extends SpecialHandler> SpecialHandler.Factory<T> make( + String name, SpecialHandler.Factory<T> handler) { + var old = SPECIAL_HANDLERS.put(modLoc(name), handler); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + name); + } + return handler; + } - public static void register(BiConsumer<SpecialHandler.Factory<?>, ResourceLocation> r) { - for (var e : SPECIAL_HANDLERS.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } + public static void register(BiConsumer<SpecialHandler.Factory<?>, ResourceLocation> r) { + for (var e : SPECIAL_HANDLERS.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/package-info.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/package-info.java index ef050db775..3aa372bf53 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/package-info.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/package-info.java @@ -1,4 +1,2 @@ -/** - * Registries and such of types Hexcasting itself defines - */ -package at.petrak.hexcasting.common.lib.hex; \ No newline at end of file +/** Registries and such of types Hexcasting itself defines */ +package at.petrak.hexcasting.common.lib.hex; diff --git a/Common/src/main/java/at/petrak/hexcasting/common/loot/AddPerWorldPatternToScrollFunc.java b/Common/src/main/java/at/petrak/hexcasting/common/loot/AddPerWorldPatternToScrollFunc.java index 30c9f97370..d2db4fa23f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/loot/AddPerWorldPatternToScrollFunc.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/loot/AddPerWorldPatternToScrollFunc.java @@ -10,6 +10,7 @@ import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; +import java.util.ArrayList; import net.minecraft.core.Registry; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceKey; @@ -19,63 +20,63 @@ import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; -import java.util.ArrayList; - /** * Slap a random per-world pattern on the scroll. - * <p> - * The function itself is only used on Fabric but the behavior {@link AddPerWorldPatternToScrollFunc#doStatic} - * is used on both sides + * + * <p>The function itself is only used on Fabric but the behavior {@link + * AddPerWorldPatternToScrollFunc#doStatic} is used on both sides */ public class AddPerWorldPatternToScrollFunc extends LootItemConditionalFunction { - public AddPerWorldPatternToScrollFunc(LootItemCondition[] lootItemConditions) { - super(lootItemConditions); - } + public AddPerWorldPatternToScrollFunc(LootItemCondition[] lootItemConditions) { + super(lootItemConditions); + } - /** - * This doesn't actually have any params so extract behaviour out for the benefit of forge - */ - public static ItemStack doStatic(ItemStack stack, LootContext ctx) { - var rand = ctx.getRandom(); - var perWorldKeys = new ArrayList<ResourceKey<ActionRegistryEntry>>(); - Registry<ActionRegistryEntry> regi = IXplatAbstractions.INSTANCE.getActionRegistry(); - for (var key : regi.registryKeySet()) { - if (HexUtils.isOfTag(regi, key, HexTags.Actions.PER_WORLD_PATTERN)) { - perWorldKeys.add(key); - } - } - var key = perWorldKeys.get(rand.nextInt(perWorldKeys.size())); + /** This doesn't actually have any params so extract behaviour out for the benefit of forge */ + public static ItemStack doStatic(ItemStack stack, LootContext ctx) { + var rand = ctx.getRandom(); + var perWorldKeys = new ArrayList<ResourceKey<ActionRegistryEntry>>(); + Registry<ActionRegistryEntry> regi = IXplatAbstractions.INSTANCE.getActionRegistry(); + for (var key : regi.registryKeySet()) { + if (HexUtils.isOfTag(regi, key, HexTags.Actions.PER_WORLD_PATTERN)) { + perWorldKeys.add(key); + } + } + var key = perWorldKeys.get(rand.nextInt(perWorldKeys.size())); - var pat = PatternRegistryManifest.getCanonicalStrokesPerWorld(key, ctx.getLevel().getServer().overworld()); - var tag = new CompoundTag(); - tag.putString(ItemScroll.TAG_OP_ID, key.location().toString()); - tag.put(ItemScroll.TAG_PATTERN, pat.serializeToNBT()); + var pat = + PatternRegistryManifest.getCanonicalStrokesPerWorld( + key, ctx.getLevel().getServer().overworld()); + var tag = new CompoundTag(); + tag.putString(ItemScroll.TAG_OP_ID, key.location().toString()); + tag.put(ItemScroll.TAG_PATTERN, pat.serializeToNBT()); - stack.getOrCreateTag().merge(tag); + stack.getOrCreateTag().merge(tag); - return stack; - } + return stack; + } - @Override - protected ItemStack run(ItemStack stack, LootContext ctx) { - return doStatic(stack, ctx); - } + @Override + protected ItemStack run(ItemStack stack, LootContext ctx) { + return doStatic(stack, ctx); + } - @Override - public LootItemFunctionType getType() { - return HexLootFunctions.PATTERN_SCROLL; - } + @Override + public LootItemFunctionType getType() { + return HexLootFunctions.PATTERN_SCROLL; + } - public static class Serializer extends LootItemConditionalFunction.Serializer<AddPerWorldPatternToScrollFunc> { - @Override - public void serialize(JsonObject json, AddPerWorldPatternToScrollFunc value, JsonSerializationContext ctx) { - super.serialize(json, value, ctx); - } + public static class Serializer + extends LootItemConditionalFunction.Serializer<AddPerWorldPatternToScrollFunc> { + @Override + public void serialize( + JsonObject json, AddPerWorldPatternToScrollFunc value, JsonSerializationContext ctx) { + super.serialize(json, value, ctx); + } - @Override - public AddPerWorldPatternToScrollFunc deserialize(JsonObject object, JsonDeserializationContext ctx, - LootItemCondition[] conditions) { - return new AddPerWorldPatternToScrollFunc(conditions); - } - } + @Override + public AddPerWorldPatternToScrollFunc deserialize( + JsonObject object, JsonDeserializationContext ctx, LootItemCondition[] conditions) { + return new AddPerWorldPatternToScrollFunc(conditions); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/loot/AmethystReducerFunc.java b/Common/src/main/java/at/petrak/hexcasting/common/loot/AmethystReducerFunc.java index cee38be6dd..54246f6f81 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/loot/AmethystReducerFunc.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/loot/AmethystReducerFunc.java @@ -13,42 +13,44 @@ import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; public class AmethystReducerFunc extends LootItemConditionalFunction { - public final double delta; - - public AmethystReducerFunc(LootItemCondition[] lootItemConditions, double delta) { - super(lootItemConditions); - this.delta = delta; - } - - public static ItemStack doStatic(ItemStack stack, LootContext ctx, double amount) { - if (stack.is(Items.AMETHYST_SHARD)) { - stack.setCount((int) (stack.getCount() * (1 + amount))); - } - return stack; - } - - @Override - protected ItemStack run(ItemStack stack, LootContext ctx) { - return doStatic(stack, ctx, this.delta); - } - - @Override - public LootItemFunctionType getType() { - return HexLootFunctions.AMETHYST_SHARD_REDUCER; - } - - public static class Serializer extends LootItemConditionalFunction.Serializer<AmethystReducerFunc> { - @Override - public void serialize(JsonObject json, AmethystReducerFunc value, JsonSerializationContext ctx) { - super.serialize(json, value, ctx); - json.addProperty("delta", value.delta); - } - - @Override - public AmethystReducerFunc deserialize(JsonObject object, JsonDeserializationContext ctx, - LootItemCondition[] conditions) { - var delta = GsonHelper.getAsDouble(object, "delta"); - return new AmethystReducerFunc(conditions, delta); - } - } + public final double delta; + + public AmethystReducerFunc(LootItemCondition[] lootItemConditions, double delta) { + super(lootItemConditions); + this.delta = delta; + } + + public static ItemStack doStatic(ItemStack stack, LootContext ctx, double amount) { + if (stack.is(Items.AMETHYST_SHARD)) { + stack.setCount((int) (stack.getCount() * (1 + amount))); + } + return stack; + } + + @Override + protected ItemStack run(ItemStack stack, LootContext ctx) { + return doStatic(stack, ctx, this.delta); + } + + @Override + public LootItemFunctionType getType() { + return HexLootFunctions.AMETHYST_SHARD_REDUCER; + } + + public static class Serializer + extends LootItemConditionalFunction.Serializer<AmethystReducerFunc> { + @Override + public void serialize( + JsonObject json, AmethystReducerFunc value, JsonSerializationContext ctx) { + super.serialize(json, value, ctx); + json.addProperty("delta", value.delta); + } + + @Override + public AmethystReducerFunc deserialize( + JsonObject object, JsonDeserializationContext ctx, LootItemCondition[] conditions) { + var delta = GsonHelper.getAsDouble(object, "delta"); + return new AmethystReducerFunc(conditions, delta); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/loot/HexLootHandler.java b/Common/src/main/java/at/petrak/hexcasting/common/loot/HexLootHandler.java index e0788d5446..2a9aa836ed 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/loot/HexLootHandler.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/loot/HexLootHandler.java @@ -1,75 +1,81 @@ package at.petrak.hexcasting.common.loot; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import com.google.common.collect.ImmutableList; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.RandomSource; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - // https://github.com/VazkiiMods/Botania/blob/1.18.x/Xplat/src/main/java/vazkii/botania/common/loot/LootHandler.java -// We need to inject dungeon loot (scrolls and lore), make amethyst drop fewer shards, and the extra dust stuff. +// We need to inject dungeon loot (scrolls and lore), make amethyst drop fewer shards, and the extra +// dust stuff. // On forge: // - Scrolls and lore are done with a loot mod -// - Amethyst drop fiddling is done with another loot mod; the shard delta is in the loot mod data and the rest of +// - Amethyst drop fiddling is done with another loot mod; the shard delta is in the loot mod data +// and the rest of // the stuff is loaded from TABLE_INJECT_AMETHYST_CLUSTER // On fabric: // - Scrolls and lore are done with a lootLoad listener and the amounts are loaded from config -// - Amethyst shard reduction is done with a loot function mixed in to always be on amethyst clusters, god, cause I -// don't think it's facile to use the loot pool api to try to figure out which pool is for the amethyst and reduce it -// - Amethyst dust and crystals are done by adding the loot table Forge uses in directly via listener +// - Amethyst shard reduction is done with a loot function mixed in to always be on amethyst +// clusters, god, cause I +// don't think it's facile to use the loot pool api to try to figure out which pool is for the +// amethyst and reduce it +// - Amethyst dust and crystals are done by adding the loot table Forge uses in directly via +// listener public class HexLootHandler { - public static final ImmutableList<ScrollInjection> DEFAULT_SCROLL_INJECTS = ImmutableList.of( - // TODO: not sure what the lore implications of scrolls and the nether/end are. adding scrolls - // there for now just to be nice to players. - - // In places where it doesn't really make sense to have them lore-wise just put them rarely anyways - // to make it less of a PITA for new players - new ScrollInjection(new ResourceLocation("minecraft", "chests/simple_dungeon"), 1), - new ScrollInjection(new ResourceLocation("minecraft", "chests/abandoned_mineshaft"), 1), - new ScrollInjection(new ResourceLocation("minecraft", "chests/bastion_other"), 1), - new ScrollInjection(new ResourceLocation("minecraft", "chests/nether_bridge"), 1), - - new ScrollInjection(new ResourceLocation("minecraft", "chests/jungle_temple"), 2), - new ScrollInjection(new ResourceLocation("minecraft", "chests/desert_pyramid"), 2), - new ScrollInjection(new ResourceLocation("minecraft", "chests/village/village_cartographer"), 2), + public static final ImmutableList<ScrollInjection> DEFAULT_SCROLL_INJECTS = + ImmutableList.of( + // TODO: not sure what the lore implications of scrolls and the nether/end are. adding + // scrolls + // there for now just to be nice to players. - new ScrollInjection(new ResourceLocation("minecraft", "chests/shipwreck_map"), 3), - new ScrollInjection(new ResourceLocation("minecraft", "chests/bastion_treasure"), 3), - new ScrollInjection(new ResourceLocation("minecraft", "chests/end_city_treasure"), 3), + // In places where it doesn't really make sense to have them lore-wise just put them + // rarely anyways + // to make it less of a PITA for new players + new ScrollInjection(new ResourceLocation("minecraft", "chests/simple_dungeon"), 1), + new ScrollInjection(new ResourceLocation("minecraft", "chests/abandoned_mineshaft"), 1), + new ScrollInjection(new ResourceLocation("minecraft", "chests/bastion_other"), 1), + new ScrollInjection(new ResourceLocation("minecraft", "chests/nether_bridge"), 1), + new ScrollInjection(new ResourceLocation("minecraft", "chests/jungle_temple"), 2), + new ScrollInjection(new ResourceLocation("minecraft", "chests/desert_pyramid"), 2), + new ScrollInjection( + new ResourceLocation("minecraft", "chests/village/village_cartographer"), 2), + new ScrollInjection(new ResourceLocation("minecraft", "chests/shipwreck_map"), 3), + new ScrollInjection(new ResourceLocation("minecraft", "chests/bastion_treasure"), 3), + new ScrollInjection(new ResourceLocation("minecraft", "chests/end_city_treasure"), 3), - // ancient city chests have amethyst in them, thinking emoji - new ScrollInjection(new ResourceLocation("minecraft", "chests/ancient_city"), 4), - // wonder what those pillagers are up to with those scrolls - new ScrollInjection(new ResourceLocation("minecraft", "chests/pillager_outpost"), 4), + // ancient city chests have amethyst in them, thinking emoji + new ScrollInjection(new ResourceLocation("minecraft", "chests/ancient_city"), 4), + // wonder what those pillagers are up to with those scrolls + new ScrollInjection(new ResourceLocation("minecraft", "chests/pillager_outpost"), 4), - // if you manage to find one of these things you deserve a lot of scrolls - new ScrollInjection(new ResourceLocation("minecraft", "chests/woodland_mansion"), 5), - new ScrollInjection(new ResourceLocation("minecraft", "chests/stronghold_library"), 5) - ); + // if you manage to find one of these things you deserve a lot of scrolls + new ScrollInjection(new ResourceLocation("minecraft", "chests/woodland_mansion"), 5), + new ScrollInjection(new ResourceLocation("minecraft", "chests/stronghold_library"), 5)); - public static final ImmutableList<ResourceLocation> DEFAULT_LORE_INJECTS = ImmutableList.of( - new ResourceLocation("minecraft", "chests/simple_dungeon"), - new ResourceLocation("minecraft", "chests/abandoned_mineshaft"), - new ResourceLocation("minecraft", "chests/pillager_outpost"), - new ResourceLocation("minecraft", "chests/woodland_mansion"), - new ResourceLocation("minecraft", "chests/stronghold_library"), - // >:) - new ResourceLocation("minecraft", "chests/village/village_desert_house"), - new ResourceLocation("minecraft", "chests/village/village_plains_house"), - new ResourceLocation("minecraft", "chests/village/village_savanna_house"), - new ResourceLocation("minecraft", "chests/village/village_snowy_house"), - new ResourceLocation("minecraft", "chests/village/village_taiga_house") - ); + public static final ImmutableList<ResourceLocation> DEFAULT_LORE_INJECTS = + ImmutableList.of( + new ResourceLocation("minecraft", "chests/simple_dungeon"), + new ResourceLocation("minecraft", "chests/abandoned_mineshaft"), + new ResourceLocation("minecraft", "chests/pillager_outpost"), + new ResourceLocation("minecraft", "chests/woodland_mansion"), + new ResourceLocation("minecraft", "chests/stronghold_library"), + // >:) + new ResourceLocation("minecraft", "chests/village/village_desert_house"), + new ResourceLocation("minecraft", "chests/village/village_plains_house"), + new ResourceLocation("minecraft", "chests/village/village_savanna_house"), + new ResourceLocation("minecraft", "chests/village/village_snowy_house"), + new ResourceLocation("minecraft", "chests/village/village_taiga_house")); - public static int getScrollCount(int range, RandomSource random) { - return Math.max(random.nextIntBetweenInclusive(-range, range), 0); - } + public static int getScrollCount(int range, RandomSource random) { + return Math.max(random.nextIntBetweenInclusive(-range, range), 0); + } - public static final double DEFAULT_SHARD_MODIFICATION = -0.5; - public static final double DEFAULT_LORE_CHANCE = 0.4; + public static final double DEFAULT_SHARD_MODIFICATION = -0.5; + public static final double DEFAULT_LORE_CHANCE = 0.4; - public static final ResourceLocation TABLE_INJECT_AMETHYST_CLUSTER = modLoc("inject/amethyst_cluster"); + public static final ResourceLocation TABLE_INJECT_AMETHYST_CLUSTER = + modLoc("inject/amethyst_cluster"); - public record ScrollInjection(ResourceLocation injectee, int countRange) { - } + public record ScrollInjection(ResourceLocation injectee, int countRange) {} } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/misc/AkashicTreeGrower.java b/Common/src/main/java/at/petrak/hexcasting/common/misc/AkashicTreeGrower.java index 4e235769e8..70eaa00881 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/misc/AkashicTreeGrower.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/misc/AkashicTreeGrower.java @@ -2,26 +2,26 @@ import at.petrak.hexcasting.common.lib.HexConfiguredFeatures; import com.google.common.collect.Lists; +import java.util.List; import net.minecraft.resources.ResourceKey; import net.minecraft.util.RandomSource; import net.minecraft.world.level.block.grower.AbstractTreeGrower; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; -import java.util.List; - public class AkashicTreeGrower extends AbstractTreeGrower { - public static final AkashicTreeGrower INSTANCE = new AkashicTreeGrower(); + public static final AkashicTreeGrower INSTANCE = new AkashicTreeGrower(); - public static final List<ResourceKey<ConfiguredFeature<?, ?>>> GROWERS = Lists.newArrayList(); + public static final List<ResourceKey<ConfiguredFeature<?, ?>>> GROWERS = Lists.newArrayList(); - public static void init() { - GROWERS.add(HexConfiguredFeatures.AMETHYST_EDIFIED_TREE); - GROWERS.add(HexConfiguredFeatures.AVENTURINE_EDIFIED_TREE); - GROWERS.add(HexConfiguredFeatures.CITRINE_EDIFIED_TREE); - } + public static void init() { + GROWERS.add(HexConfiguredFeatures.AMETHYST_EDIFIED_TREE); + GROWERS.add(HexConfiguredFeatures.AVENTURINE_EDIFIED_TREE); + GROWERS.add(HexConfiguredFeatures.CITRINE_EDIFIED_TREE); + } - @Override - protected ResourceKey<ConfiguredFeature<?, ?>> getConfiguredFeature(RandomSource pRandom, boolean pLargeHive) { - return GROWERS.get(pRandom.nextInt(GROWERS.size())); - } + @Override + protected ResourceKey<ConfiguredFeature<?, ?>> getConfiguredFeature( + RandomSource pRandom, boolean pLargeHive) { + return GROWERS.get(pRandom.nextInt(GROWERS.size())); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/misc/BrainsweepingEvents.java b/Common/src/main/java/at/petrak/hexcasting/common/misc/BrainsweepingEvents.java index 4e6307460b..b05c35d5a4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/misc/BrainsweepingEvents.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/misc/BrainsweepingEvents.java @@ -12,21 +12,27 @@ import org.jetbrains.annotations.Nullable; public class BrainsweepingEvents { - public static InteractionResult interactWithBrainswept(Player player, Level world, InteractionHand hand, - Entity entity, @Nullable EntityHitResult hitResult) { - if (entity instanceof Mob mob && IXplatAbstractions.INSTANCE.isBrainswept(mob)) { - // As in, this interaction "successfully" consumes the result and doesn't pass it on - return InteractionResult.SUCCESS; - } + public static InteractionResult interactWithBrainswept( + Player player, + Level world, + InteractionHand hand, + Entity entity, + @Nullable EntityHitResult hitResult) { + if (entity instanceof Mob mob && IXplatAbstractions.INSTANCE.isBrainswept(mob)) { + // As in, this interaction "successfully" consumes the result and doesn't pass it on + return InteractionResult.SUCCESS; + } - return InteractionResult.PASS; - } + return InteractionResult.PASS; + } - public static InteractionResult copyBrainsweepPostTransformation(LivingEntity original, LivingEntity outcome) { - if (original instanceof Mob mOriginal && outcome instanceof Mob mOutcome - && IXplatAbstractions.INSTANCE.isBrainswept(mOriginal)) { - IXplatAbstractions.INSTANCE.setBrainsweepAddlData(mOutcome); - } - return InteractionResult.PASS; - } + public static InteractionResult copyBrainsweepPostTransformation( + LivingEntity original, LivingEntity outcome) { + if (original instanceof Mob mOriginal + && outcome instanceof Mob mOutcome + && IXplatAbstractions.INSTANCE.isBrainswept(mOriginal)) { + IXplatAbstractions.INSTANCE.setBrainsweepAddlData(mOutcome); + } + return InteractionResult.PASS; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/misc/HexMobEffect.java b/Common/src/main/java/at/petrak/hexcasting/common/misc/HexMobEffect.java index 4af9029f0b..fdbf55886a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/misc/HexMobEffect.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/misc/HexMobEffect.java @@ -3,11 +3,9 @@ import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectCategory; -/** - * Dodge protected ctor - */ +/** Dodge protected ctor */ public class HexMobEffect extends MobEffect { - public HexMobEffect(MobEffectCategory category, int color) { - super(category, color); - } + public HexMobEffect(MobEffectCategory category, int color) { + super(category, color); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/misc/PatternTooltip.java b/Common/src/main/java/at/petrak/hexcasting/common/misc/PatternTooltip.java index 0ed28e1307..e29c93cfa9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/misc/PatternTooltip.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/misc/PatternTooltip.java @@ -9,5 +9,5 @@ * * @see at.petrak.hexcasting.client.gui.PatternTooltipComponent the client-side renderer for this */ -public record PatternTooltip(HexPattern pattern, ResourceLocation background) implements TooltipComponent { -} +public record PatternTooltip(HexPattern pattern, ResourceLocation background) + implements TooltipComponent {} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/misc/PlayerPositionRecorder.java b/Common/src/main/java/at/petrak/hexcasting/common/misc/PlayerPositionRecorder.java index 6009991707..ec473062ad 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/misc/PlayerPositionRecorder.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/misc/PlayerPositionRecorder.java @@ -1,36 +1,32 @@ package at.petrak.hexcasting.common.misc; +import java.util.Map; +import java.util.WeakHashMap; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.phys.Vec3; -import java.util.Map; -import java.util.WeakHashMap; - public final class PlayerPositionRecorder { - private static final Map<Player, Vec3> LAST_SECOND_POSITION_MAP = new WeakHashMap<>(); - private static final Map<Player, Vec3> LAST_POSITION_MAP = new WeakHashMap<>(); + private static final Map<Player, Vec3> LAST_SECOND_POSITION_MAP = new WeakHashMap<>(); + private static final Map<Player, Vec3> LAST_POSITION_MAP = new WeakHashMap<>(); - public static void updateAllPlayers(ServerLevel world) { - for (ServerPlayer player : world.players()) { - var prev = LAST_POSITION_MAP.get(player); - if (prev != null) - LAST_SECOND_POSITION_MAP.put(player, prev); - LAST_POSITION_MAP.put(player, player.position()); - } - } + public static void updateAllPlayers(ServerLevel world) { + for (ServerPlayer player : world.players()) { + var prev = LAST_POSITION_MAP.get(player); + if (prev != null) LAST_SECOND_POSITION_MAP.put(player, prev); + LAST_POSITION_MAP.put(player, player.position()); + } + } - public static Vec3 getMotion(ServerPlayer player) { - Vec3 vec = LAST_POSITION_MAP.get(player); - Vec3 prev = LAST_SECOND_POSITION_MAP.get(player); + public static Vec3 getMotion(ServerPlayer player) { + Vec3 vec = LAST_POSITION_MAP.get(player); + Vec3 prev = LAST_SECOND_POSITION_MAP.get(player); - if (vec == null) - return Vec3.ZERO; + if (vec == null) return Vec3.ZERO; - if (prev == null) - return player.position().subtract(vec); + if (prev == null) return player.position().subtract(vec); - return vec.subtract(prev); - } + return vec.subtract(prev); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/misc/RegisterMisc.java b/Common/src/main/java/at/petrak/hexcasting/common/misc/RegisterMisc.java index 2559748264..5ba13c806f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/misc/RegisterMisc.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/misc/RegisterMisc.java @@ -10,36 +10,48 @@ import net.minecraft.world.phys.Vec3; public class RegisterMisc { - public static void register() { - HexAPI.instance().registerSpecialVelocityGetter(EntityType.PLAYER, player -> { - if (player instanceof ServerPlayer splayer) { - return PlayerPositionRecorder.getMotion(splayer); - } else { - // bruh - throw new IllegalStateException("Call this only on the server side, silly"); - } - }); + public static void register() { + HexAPI.instance() + .registerSpecialVelocityGetter( + EntityType.PLAYER, + player -> { + if (player instanceof ServerPlayer splayer) { + return PlayerPositionRecorder.getMotion(splayer); + } else { + // bruh + throw new IllegalStateException("Call this only on the server side, silly"); + } + }); - HexAPI.instance().registerSpecialVelocityGetter(EntityType.ARROW, RegisterMisc::arrowVelocitizer); - HexAPI.instance().registerSpecialVelocityGetter(EntityType.SPECTRAL_ARROW, RegisterMisc::arrowVelocitizer); - // this is an arrow apparently - HexAPI.instance().registerSpecialVelocityGetter(EntityType.TRIDENT, RegisterMisc::arrowVelocitizer); + HexAPI.instance() + .registerSpecialVelocityGetter(EntityType.ARROW, RegisterMisc::arrowVelocitizer); + HexAPI.instance() + .registerSpecialVelocityGetter(EntityType.SPECTRAL_ARROW, RegisterMisc::arrowVelocitizer); + // this is an arrow apparently + HexAPI.instance() + .registerSpecialVelocityGetter(EntityType.TRIDENT, RegisterMisc::arrowVelocitizer); - HexAPI.instance().registerCustomBrainsweepingBehavior(EntityType.VILLAGER, villager -> { - ((AccessorVillager) villager).hex$releaseAllPois(); - HexAPI.instance().defaultBrainsweepingBehavior().accept(villager); - }); - HexAPI.instance().registerCustomBrainsweepingBehavior(EntityType.ALLAY, allay -> { - allay.getBrain().eraseMemory(MemoryModuleType.LIKED_PLAYER); - HexAPI.instance().defaultBrainsweepingBehavior().accept(allay); - }); - } + HexAPI.instance() + .registerCustomBrainsweepingBehavior( + EntityType.VILLAGER, + villager -> { + ((AccessorVillager) villager).hex$releaseAllPois(); + HexAPI.instance().defaultBrainsweepingBehavior().accept(villager); + }); + HexAPI.instance() + .registerCustomBrainsweepingBehavior( + EntityType.ALLAY, + allay -> { + allay.getBrain().eraseMemory(MemoryModuleType.LIKED_PLAYER); + HexAPI.instance().defaultBrainsweepingBehavior().accept(allay); + }); + } - private static Vec3 arrowVelocitizer(AbstractArrow arrow) { - if (((AccessorAbstractArrow) arrow).hex$isInGround()) { - return Vec3.ZERO; - } else { - return arrow.getDeltaMovement(); - } - } + private static Vec3 arrowVelocitizer(AbstractArrow arrow) { + if (((AccessorAbstractArrow) arrow).hex$isInGround()) { + return Vec3.ZERO; + } else { + return arrow.getDeltaMovement(); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/msgs/IMessage.java b/Common/src/main/java/at/petrak/hexcasting/common/msgs/IMessage.java index ec7cdd8ef4..f974b85116 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/msgs/IMessage.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/msgs/IMessage.java @@ -7,18 +7,18 @@ // https://github.com/VazkiiMods/Botania/blob/1.18.x/Common/src/main/java/vazkii/botania/network/IPacket.java // yoink public interface IMessage { - default FriendlyByteBuf toBuf() { - var ret = new FriendlyByteBuf(Unpooled.buffer()); - serialize(ret); - return ret; - } + default FriendlyByteBuf toBuf() { + var ret = new FriendlyByteBuf(Unpooled.buffer()); + serialize(ret); + return ret; + } - void serialize(FriendlyByteBuf buf); + void serialize(FriendlyByteBuf buf); - /** - * Forge auto-assigns incrementing integers, Fabric requires us to declare an ID - * These are sent using vanilla's custom plugin channel system and thus are written to every single packet. - * So this ID tends to be more terse. - */ - ResourceLocation getFabricId(); + /** + * Forge auto-assigns incrementing integers, Fabric requires us to declare an ID These are sent + * using vanilla's custom plugin channel system and thus are written to every single packet. So + * this ID tends to be more terse. + */ + ResourceLocation getFabricId(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgBeepS2C.java b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgBeepS2C.java index 852fc675af..e0d94f5280 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgBeepS2C.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgBeepS2C.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.common.msgs; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import io.netty.buffer.ByteBuf; import net.minecraft.client.Minecraft; import net.minecraft.core.particles.ParticleTypes; @@ -9,49 +11,63 @@ import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; import net.minecraft.world.phys.Vec3; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - -public record MsgBeepS2C(Vec3 target, int note, NoteBlockInstrument instrument) implements IMessage { - public static final ResourceLocation ID = modLoc("beep"); +public record MsgBeepS2C(Vec3 target, int note, NoteBlockInstrument instrument) + implements IMessage { + public static final ResourceLocation ID = modLoc("beep"); - @Override - public ResourceLocation getFabricId() { - return ID; - } + @Override + public ResourceLocation getFabricId() { + return ID; + } - public static MsgBeepS2C deserialize(ByteBuf buffer) { - var buf = new FriendlyByteBuf(buffer); - var x = buf.readDouble(); - var y = buf.readDouble(); - var z = buf.readDouble(); - var note = buf.readInt(); - var instrument = buf.readEnum(NoteBlockInstrument.class); - return new MsgBeepS2C(new Vec3(x, y, z), note, instrument); - } + public static MsgBeepS2C deserialize(ByteBuf buffer) { + var buf = new FriendlyByteBuf(buffer); + var x = buf.readDouble(); + var y = buf.readDouble(); + var z = buf.readDouble(); + var note = buf.readInt(); + var instrument = buf.readEnum(NoteBlockInstrument.class); + return new MsgBeepS2C(new Vec3(x, y, z), note, instrument); + } - @Override - public void serialize(FriendlyByteBuf buf) { - buf.writeDouble(this.target.x); - buf.writeDouble(this.target.y); - buf.writeDouble(this.target.z); - buf.writeInt(this.note); - buf.writeEnum(instrument); - } + @Override + public void serialize(FriendlyByteBuf buf) { + buf.writeDouble(this.target.x); + buf.writeDouble(this.target.y); + buf.writeDouble(this.target.z); + buf.writeInt(this.note); + buf.writeEnum(instrument); + } - public static void handle(MsgBeepS2C msg) { - Minecraft.getInstance().execute(new Runnable() { - @Override - public void run() { - var minecraft = Minecraft.getInstance(); - var world = minecraft.level; - if (world != null) { - float pitch = (float) Math.pow(2, (msg.note() - 12) / 12.0); - world.playLocalSound(msg.target().x, msg.target().y, msg.target().z, - msg.instrument().getSoundEvent().value(), SoundSource.PLAYERS, 3, pitch, false); - world.addParticle(ParticleTypes.NOTE, msg.target().x, msg.target().y + 0.2, msg.target().z, - msg.note() / 24.0, 0, 0); - } - } - }); - } + public static void handle(MsgBeepS2C msg) { + Minecraft.getInstance() + .execute( + new Runnable() { + @Override + public void run() { + var minecraft = Minecraft.getInstance(); + var world = minecraft.level; + if (world != null) { + float pitch = (float) Math.pow(2, (msg.note() - 12) / 12.0); + world.playLocalSound( + msg.target().x, + msg.target().y, + msg.target().z, + msg.instrument().getSoundEvent().value(), + SoundSource.PLAYERS, + 3, + pitch, + false); + world.addParticle( + ParticleTypes.NOTE, + msg.target().x, + msg.target().y + 0.2, + msg.target().z, + msg.note() / 24.0, + 0, + 0); + } + } + }); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgBlinkS2C.java b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgBlinkS2C.java index ab75bc20ed..936e8275b8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgBlinkS2C.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgBlinkS2C.java @@ -1,46 +1,46 @@ package at.petrak.hexcasting.common.msgs; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import io.netty.buffer.ByteBuf; import net.minecraft.client.Minecraft; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.phys.Vec3; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - -/** - * Sent server->client to synchronize OpBlink when the target is a player. - */ +/** Sent server->client to synchronize OpBlink when the target is a player. */ public record MsgBlinkS2C(Vec3 addedPosition) implements IMessage { - public static final ResourceLocation ID = modLoc("blink"); + public static final ResourceLocation ID = modLoc("blink"); - @Override - public ResourceLocation getFabricId() { - return ID; - } + @Override + public ResourceLocation getFabricId() { + return ID; + } - public static MsgBlinkS2C deserialize(ByteBuf buffer) { - var buf = new FriendlyByteBuf(buffer); - var x = buf.readDouble(); - var y = buf.readDouble(); - var z = buf.readDouble(); - return new MsgBlinkS2C(new Vec3(x, y, z)); - } + public static MsgBlinkS2C deserialize(ByteBuf buffer) { + var buf = new FriendlyByteBuf(buffer); + var x = buf.readDouble(); + var y = buf.readDouble(); + var z = buf.readDouble(); + return new MsgBlinkS2C(new Vec3(x, y, z)); + } - @Override - public void serialize(FriendlyByteBuf buf) { - buf.writeDouble(this.addedPosition.x); - buf.writeDouble(this.addedPosition.y); - buf.writeDouble(this.addedPosition.z); - } + @Override + public void serialize(FriendlyByteBuf buf) { + buf.writeDouble(this.addedPosition.x); + buf.writeDouble(this.addedPosition.y); + buf.writeDouble(this.addedPosition.z); + } - public static void handle(MsgBlinkS2C self) { - Minecraft.getInstance().execute(new Runnable() { - @Override - public void run() { - var player = Minecraft.getInstance().player; - player.setPos(player.position().add(self.addedPosition())); - } - }); - } + public static void handle(MsgBlinkS2C self) { + Minecraft.getInstance() + .execute( + new Runnable() { + @Override + public void run() { + var player = Minecraft.getInstance().player; + player.setPos(player.position().add(self.addedPosition())); + } + }); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgCastParticleS2C.java b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgCastParticleS2C.java index 9ec659b8b6..4319a0d446 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgCastParticleS2C.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgCastParticleS2C.java @@ -1,110 +1,120 @@ package at.petrak.hexcasting.common.msgs; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.ParticleSpray; import at.petrak.hexcasting.api.pigment.FrozenPigment; import at.petrak.hexcasting.client.ClientTickCounter; import at.petrak.hexcasting.common.particles.ConjureParticleOptions; import io.netty.buffer.ByteBuf; +import java.util.Random; import net.minecraft.client.Minecraft; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec3; -import java.util.Random; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - -/** - * Sent server->client to spray particles everywhere. - */ +/** Sent server->client to spray particles everywhere. */ public record MsgCastParticleS2C(ParticleSpray spray, FrozenPigment colorizer) implements IMessage { - public static final ResourceLocation ID = modLoc("cprtcl"); - - @Override - public ResourceLocation getFabricId() { - return ID; - } + public static final ResourceLocation ID = modLoc("cprtcl"); - public static MsgCastParticleS2C deserialize(ByteBuf buffer) { - var buf = new FriendlyByteBuf(buffer); - var posX = buf.readDouble(); - var posY = buf.readDouble(); - var posZ = buf.readDouble(); - var velX = buf.readDouble(); - var velY = buf.readDouble(); - var velZ = buf.readDouble(); - var fuzziness = buf.readDouble(); - var spread = buf.readDouble(); - var count = buf.readInt(); - var tag = buf.readAnySizeNbt(); - var colorizer = FrozenPigment.fromNBT(tag); - return new MsgCastParticleS2C( - new ParticleSpray(new Vec3(posX, posY, posZ), new Vec3(velX, velY, velZ), fuzziness, spread, count), - colorizer); - } + @Override + public ResourceLocation getFabricId() { + return ID; + } - @Override - public void serialize(FriendlyByteBuf buf) { - buf.writeDouble(this.spray.getPos().x); - buf.writeDouble(this.spray.getPos().y); - buf.writeDouble(this.spray.getPos().z); - buf.writeDouble(this.spray.getVel().x); - buf.writeDouble(this.spray.getVel().y); - buf.writeDouble(this.spray.getVel().z); - buf.writeDouble(this.spray.getFuzziness()); - buf.writeDouble(this.spray.getSpread()); - buf.writeInt(this.spray.getCount()); - buf.writeNbt(this.colorizer.serializeToNBT()); - } + public static MsgCastParticleS2C deserialize(ByteBuf buffer) { + var buf = new FriendlyByteBuf(buffer); + var posX = buf.readDouble(); + var posY = buf.readDouble(); + var posZ = buf.readDouble(); + var velX = buf.readDouble(); + var velY = buf.readDouble(); + var velZ = buf.readDouble(); + var fuzziness = buf.readDouble(); + var spread = buf.readDouble(); + var count = buf.readInt(); + var tag = buf.readAnySizeNbt(); + var colorizer = FrozenPigment.fromNBT(tag); + return new MsgCastParticleS2C( + new ParticleSpray( + new Vec3(posX, posY, posZ), new Vec3(velX, velY, velZ), fuzziness, spread, count), + colorizer); + } + @Override + public void serialize(FriendlyByteBuf buf) { + buf.writeDouble(this.spray.getPos().x); + buf.writeDouble(this.spray.getPos().y); + buf.writeDouble(this.spray.getPos().z); + buf.writeDouble(this.spray.getVel().x); + buf.writeDouble(this.spray.getVel().y); + buf.writeDouble(this.spray.getVel().z); + buf.writeDouble(this.spray.getFuzziness()); + buf.writeDouble(this.spray.getSpread()); + buf.writeInt(this.spray.getCount()); + buf.writeNbt(this.colorizer.serializeToNBT()); + } - private static final Random RANDOM = new Random(); + private static final Random RANDOM = new Random(); - // https://math.stackexchange.com/questions/44689/how-to-find-a-random-axis-or-unit-vector-in-3d - private static Vec3 randomInCircle(double maxTh) { - var th = RANDOM.nextDouble(0.0, maxTh + 0.001); - var z = RANDOM.nextDouble(-1.0, 1.0); - return new Vec3(Math.sqrt(1.0 - z * z) * Math.cos(th), Math.sqrt(1.0 - z * z) * Math.sin(th), z); - } + // https://math.stackexchange.com/questions/44689/how-to-find-a-random-axis-or-unit-vector-in-3d + private static Vec3 randomInCircle(double maxTh) { + var th = RANDOM.nextDouble(0.0, maxTh + 0.001); + var z = RANDOM.nextDouble(-1.0, 1.0); + return new Vec3( + Math.sqrt(1.0 - z * z) * Math.cos(th), Math.sqrt(1.0 - z * z) * Math.sin(th), z); + } - public static void handle(MsgCastParticleS2C msg) { - Minecraft.getInstance().execute(new Runnable() { - @Override - public void run() { - var colProvider = msg.colorizer().getColorProvider(); - for (int i = 0; i < msg.spray().getCount(); i++) { - // For the colors, pick any random time to get a mix of colors + public static void handle(MsgCastParticleS2C msg) { + Minecraft.getInstance() + .execute( + new Runnable() { + @Override + public void run() { + var colProvider = msg.colorizer().getColorProvider(); + for (int i = 0; i < msg.spray().getCount(); i++) { + // For the colors, pick any random time to get a mix of colors - var offset = randomInCircle(Mth.TWO_PI).normalize() - .scale(RANDOM.nextFloat() * msg.spray().getFuzziness() / 2); - var pos = msg.spray().getPos().add(offset); + var offset = + randomInCircle(Mth.TWO_PI) + .normalize() + .scale(RANDOM.nextFloat() * msg.spray().getFuzziness() / 2); + var pos = msg.spray().getPos().add(offset); - var phi = Math.acos(1.0 - RANDOM.nextDouble() * (1.0 - Math.cos(msg.spray().getSpread()))); - var theta = Math.PI * 2.0 * RANDOM.nextDouble(); - var v = msg.spray().getVel().normalize(); - // pick any old vector to get a vector normal to v with - Vec3 k; - if (v.x == 0.0 && v.y == 0.0) { - // oops, pick a *different* normal - k = new Vec3(1.0, 0.0, 0.0); - } else { - k = v.cross(new Vec3(0.0, 0.0, 1.0)); - } - var velUnlen = v.scale(Math.cos(phi)) - .add(k.scale(Math.sin(phi) * Math.cos(theta))) - .add(v.cross(k).scale(Math.sin(phi) * Math.sin(theta))); - var vel = velUnlen.scale(msg.spray().getVel().length() / 20); + var phi = + Math.acos( + 1.0 - RANDOM.nextDouble() * (1.0 - Math.cos(msg.spray().getSpread()))); + var theta = Math.PI * 2.0 * RANDOM.nextDouble(); + var v = msg.spray().getVel().normalize(); + // pick any old vector to get a vector normal to v with + Vec3 k; + if (v.x == 0.0 && v.y == 0.0) { + // oops, pick a *different* normal + k = new Vec3(1.0, 0.0, 0.0); + } else { + k = v.cross(new Vec3(0.0, 0.0, 1.0)); + } + var velUnlen = + v.scale(Math.cos(phi)) + .add(k.scale(Math.sin(phi) * Math.cos(theta))) + .add(v.cross(k).scale(Math.sin(phi) * Math.sin(theta))); + var vel = velUnlen.scale(msg.spray().getVel().length() / 20); - var color = colProvider.getColor(ClientTickCounter.getTotal(), velUnlen); + var color = colProvider.getColor(ClientTickCounter.getTotal(), velUnlen); - Minecraft.getInstance().level.addParticle( - new ConjureParticleOptions(color), - pos.x, pos.y, pos.z, - vel.x, vel.y, vel.z - ); - } - } - }); - } + Minecraft.getInstance() + .level + .addParticle( + new ConjureParticleOptions(color), + pos.x, + pos.y, + pos.z, + vel.x, + vel.y, + vel.z); + } + } + }); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgClearSpiralPatternsS2C.java b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgClearSpiralPatternsS2C.java index 1f454ba700..2e56a26bfe 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgClearSpiralPatternsS2C.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgClearSpiralPatternsS2C.java @@ -1,46 +1,47 @@ package at.petrak.hexcasting.common.msgs; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.xplat.IClientXplatAbstractions; import io.netty.buffer.ByteBuf; +import java.util.UUID; import net.minecraft.client.Minecraft; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; -import java.util.UUID; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public record MsgClearSpiralPatternsS2C(UUID playerUUID) implements IMessage { - public static final ResourceLocation ID = modLoc("clr_spi_pats_sc"); - - @Override - public ResourceLocation getFabricId() { - return ID; - } - - public static MsgClearSpiralPatternsS2C deserialize(ByteBuf buffer) { - var buf = new FriendlyByteBuf(buffer); - - var player = buf.readUUID(); - - return new MsgClearSpiralPatternsS2C(player); - } - - @Override - public void serialize(FriendlyByteBuf buf) { - buf.writeUUID(playerUUID); - } - - public static void handle(MsgClearSpiralPatternsS2C self) { - Minecraft.getInstance().execute(new Runnable() { - @Override - public void run() { - var mc = Minecraft.getInstance(); - assert mc.level != null; - var player = mc.level.getPlayerByUUID(self.playerUUID); - var stack = IClientXplatAbstractions.INSTANCE.getClientCastingStack(player); - stack.slowClear(); - } - }); - } + public static final ResourceLocation ID = modLoc("clr_spi_pats_sc"); + + @Override + public ResourceLocation getFabricId() { + return ID; + } + + public static MsgClearSpiralPatternsS2C deserialize(ByteBuf buffer) { + var buf = new FriendlyByteBuf(buffer); + + var player = buf.readUUID(); + + return new MsgClearSpiralPatternsS2C(player); + } + + @Override + public void serialize(FriendlyByteBuf buf) { + buf.writeUUID(playerUUID); + } + + public static void handle(MsgClearSpiralPatternsS2C self) { + Minecraft.getInstance() + .execute( + new Runnable() { + @Override + public void run() { + var mc = Minecraft.getInstance(); + assert mc.level != null; + var player = mc.level.getPlayerByUUID(self.playerUUID); + var stack = IClientXplatAbstractions.INSTANCE.getClientCastingStack(player); + stack.slowClear(); + } + }); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpellPatternC2S.java b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpellPatternC2S.java index ce19d966b3..12217f853f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpellPatternC2S.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpellPatternC2S.java @@ -1,58 +1,57 @@ package at.petrak.hexcasting.common.msgs; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.eval.ResolvedPattern; import at.petrak.hexcasting.api.casting.eval.env.StaffCastEnv; import at.petrak.hexcasting.api.casting.math.HexPattern; import io.netty.buffer.ByteBuf; +import java.util.ArrayList; +import java.util.List; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; -import java.util.ArrayList; -import java.util.List; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - /** - * Sent client->server when the player finishes drawing a pattern. - * Server will send back a {@link MsgNewSpellPatternS2C} packet + * Sent client->server when the player finishes drawing a pattern. Server will send back a {@link + * MsgNewSpellPatternS2C} packet */ -public record MsgNewSpellPatternC2S(InteractionHand handUsed, HexPattern pattern, - List<ResolvedPattern> resolvedPatterns) - implements IMessage { - public static final ResourceLocation ID = modLoc("pat_cs"); - - @Override - public ResourceLocation getFabricId() { - return ID; - } - - public static MsgNewSpellPatternC2S deserialize(ByteBuf buffer) { - var buf = new FriendlyByteBuf(buffer); - var hand = buf.readEnum(InteractionHand.class); - var pattern = HexPattern.fromNBT(buf.readNbt()); - - var resolvedPatternsLen = buf.readInt(); - var resolvedPatterns = new ArrayList<ResolvedPattern>(resolvedPatternsLen); - for (int i = 0; i < resolvedPatternsLen; i++) { - resolvedPatterns.add(ResolvedPattern.fromNBT(buf.readNbt())); - } - return new MsgNewSpellPatternC2S(hand, pattern, resolvedPatterns); - } - - @Override - public void serialize(FriendlyByteBuf buf) { - buf.writeEnum(handUsed); - buf.writeNbt(this.pattern.serializeToNBT()); - buf.writeInt(this.resolvedPatterns.size()); - for (var pat : this.resolvedPatterns) { - buf.writeNbt(pat.serializeToNBT()); - } - } - - public void handle(MinecraftServer server, ServerPlayer sender) { - server.execute(() -> StaffCastEnv.handleNewPatternOnServer(sender, this)); - } +public record MsgNewSpellPatternC2S( + InteractionHand handUsed, HexPattern pattern, List<ResolvedPattern> resolvedPatterns) + implements IMessage { + public static final ResourceLocation ID = modLoc("pat_cs"); + + @Override + public ResourceLocation getFabricId() { + return ID; + } + + public static MsgNewSpellPatternC2S deserialize(ByteBuf buffer) { + var buf = new FriendlyByteBuf(buffer); + var hand = buf.readEnum(InteractionHand.class); + var pattern = HexPattern.fromNBT(buf.readNbt()); + + var resolvedPatternsLen = buf.readInt(); + var resolvedPatterns = new ArrayList<ResolvedPattern>(resolvedPatternsLen); + for (int i = 0; i < resolvedPatternsLen; i++) { + resolvedPatterns.add(ResolvedPattern.fromNBT(buf.readNbt())); + } + return new MsgNewSpellPatternC2S(hand, pattern, resolvedPatterns); + } + + @Override + public void serialize(FriendlyByteBuf buf) { + buf.writeEnum(handUsed); + buf.writeNbt(this.pattern.serializeToNBT()); + buf.writeInt(this.resolvedPatterns.size()); + for (var pat : this.resolvedPatterns) { + buf.writeNbt(pat.serializeToNBT()); + } + } + + public void handle(MinecraftServer server, ServerPlayer sender) { + server.execute(() -> StaffCastEnv.handleNewPatternOnServer(sender, this)); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpellPatternS2C.java b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpellPatternS2C.java index cadf3dd100..2291343e50 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpellPatternS2C.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpellPatternS2C.java @@ -1,68 +1,66 @@ package at.petrak.hexcasting.common.msgs; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.eval.ExecutionClientView; import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType; import at.petrak.hexcasting.client.gui.GuiSpellcasting; import at.petrak.hexcasting.common.lib.HexSounds; import io.netty.buffer.ByteBuf; +import java.util.Optional; import net.minecraft.client.Minecraft; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; -import java.util.Optional; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - -/** - * Sent server->client when the player finishes casting a spell. - */ +/** Sent server->client when the player finishes casting a spell. */ public record MsgNewSpellPatternS2C(ExecutionClientView info, int index) implements IMessage { - public static final ResourceLocation ID = modLoc("pat_sc"); + public static final ResourceLocation ID = modLoc("pat_sc"); - @Override - public ResourceLocation getFabricId() { - return ID; - } + @Override + public ResourceLocation getFabricId() { + return ID; + } - public static MsgNewSpellPatternS2C deserialize(ByteBuf buffer) { - var buf = new FriendlyByteBuf(buffer); + public static MsgNewSpellPatternS2C deserialize(ByteBuf buffer) { + var buf = new FriendlyByteBuf(buffer); - var isStackEmpty = buf.readBoolean(); - var resolutionType = buf.readEnum(ResolvedPatternType.class); - var index = buf.readInt(); + var isStackEmpty = buf.readBoolean(); + var resolutionType = buf.readEnum(ResolvedPatternType.class); + var index = buf.readInt(); - var stack = buf.readList(FriendlyByteBuf::readNbt); - var raven = buf.readOptional(FriendlyByteBuf::readNbt).orElse(null); + var stack = buf.readList(FriendlyByteBuf::readNbt); + var raven = buf.readOptional(FriendlyByteBuf::readNbt).orElse(null); - return new MsgNewSpellPatternS2C( - new ExecutionClientView(isStackEmpty, resolutionType, stack, raven), index - ); - } + return new MsgNewSpellPatternS2C( + new ExecutionClientView(isStackEmpty, resolutionType, stack, raven), index); + } - @Override - public void serialize(FriendlyByteBuf buf) { - buf.writeBoolean(this.info.isStackClear()); - buf.writeEnum(this.info.getResolutionType()); - buf.writeInt(this.index); + @Override + public void serialize(FriendlyByteBuf buf) { + buf.writeBoolean(this.info.isStackClear()); + buf.writeEnum(this.info.getResolutionType()); + buf.writeInt(this.index); - buf.writeCollection(this.info.getStackDescs(), FriendlyByteBuf::writeNbt); - buf.writeOptional(Optional.ofNullable(this.info.getRavenmind()), FriendlyByteBuf::writeNbt); - } + buf.writeCollection(this.info.getStackDescs(), FriendlyByteBuf::writeNbt); + buf.writeOptional(Optional.ofNullable(this.info.getRavenmind()), FriendlyByteBuf::writeNbt); + } - public static void handle(MsgNewSpellPatternS2C self) { - Minecraft.getInstance().execute(new Runnable() { - @Override - public void run() { - var mc = Minecraft.getInstance(); - if (self.info().isStackClear()) { - // don't pay attention to the screen, so it also stops when we die - mc.getSoundManager().stop(HexSounds.CASTING_AMBIANCE.getLocation(), null); - } - var screen = Minecraft.getInstance().screen; - if (screen instanceof GuiSpellcasting spellGui) { - spellGui.recvServerUpdate(self.info(), self.index()); - } - } - }); - } + public static void handle(MsgNewSpellPatternS2C self) { + Minecraft.getInstance() + .execute( + new Runnable() { + @Override + public void run() { + var mc = Minecraft.getInstance(); + if (self.info().isStackClear()) { + // don't pay attention to the screen, so it also stops when we die + mc.getSoundManager().stop(HexSounds.CASTING_AMBIANCE.getLocation(), null); + } + var screen = Minecraft.getInstance().screen; + if (screen instanceof GuiSpellcasting spellGui) { + spellGui.recvServerUpdate(self.info(), self.index()); + } + } + }); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpiralPatternsS2C.java b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpiralPatternsS2C.java index 9c5a02180c..d6684d9a1d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpiralPatternsS2C.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpiralPatternsS2C.java @@ -1,56 +1,56 @@ package at.petrak.hexcasting.common.msgs; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.math.HexPattern; import at.petrak.hexcasting.xplat.IClientXplatAbstractions; import io.netty.buffer.ByteBuf; -import net.minecraft.client.Minecraft; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; - import java.util.ArrayList; import java.util.List; import java.util.UUID; +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - -public record MsgNewSpiralPatternsS2C(UUID playerUUID, List<HexPattern> patterns, int lifetime) implements IMessage { - public static final ResourceLocation ID = modLoc("spi_pats_sc"); - - @Override - public ResourceLocation getFabricId() { - return ID; - } - - public static MsgNewSpiralPatternsS2C deserialize(ByteBuf buffer) { - var buf = new FriendlyByteBuf(buffer); - - var player = buf.readUUID(); - var patterns = buf.readCollection(ArrayList::new, buff -> HexPattern.fromNBT(buf.readNbt())); - var lifetime = buf.readInt(); - - - return new MsgNewSpiralPatternsS2C(player, patterns, lifetime); - } - - @Override - public void serialize(FriendlyByteBuf buf) { - buf.writeUUID(playerUUID); - buf.writeCollection(patterns, (buff, pattern) -> buff.writeNbt(pattern.serializeToNBT())); - buf.writeInt(lifetime); - } - - public static void handle(MsgNewSpiralPatternsS2C self) { - Minecraft.getInstance().execute(new Runnable() { - @Override - public void run() { - var mc = Minecraft.getInstance(); - assert mc.level != null; - var player = mc.level.getPlayerByUUID(self.playerUUID); - var stack = IClientXplatAbstractions.INSTANCE.getClientCastingStack(player); - - for (var pattern : self.patterns) - stack.addPattern(pattern, self.lifetime); - } - }); - } +public record MsgNewSpiralPatternsS2C(UUID playerUUID, List<HexPattern> patterns, int lifetime) + implements IMessage { + public static final ResourceLocation ID = modLoc("spi_pats_sc"); + + @Override + public ResourceLocation getFabricId() { + return ID; + } + + public static MsgNewSpiralPatternsS2C deserialize(ByteBuf buffer) { + var buf = new FriendlyByteBuf(buffer); + + var player = buf.readUUID(); + var patterns = buf.readCollection(ArrayList::new, buff -> HexPattern.fromNBT(buf.readNbt())); + var lifetime = buf.readInt(); + + return new MsgNewSpiralPatternsS2C(player, patterns, lifetime); + } + + @Override + public void serialize(FriendlyByteBuf buf) { + buf.writeUUID(playerUUID); + buf.writeCollection(patterns, (buff, pattern) -> buff.writeNbt(pattern.serializeToNBT())); + buf.writeInt(lifetime); + } + + public static void handle(MsgNewSpiralPatternsS2C self) { + Minecraft.getInstance() + .execute( + new Runnable() { + @Override + public void run() { + var mc = Minecraft.getInstance(); + assert mc.level != null; + var player = mc.level.getPlayerByUUID(self.playerUUID); + var stack = IClientXplatAbstractions.INSTANCE.getClientCastingStack(player); + + for (var pattern : self.patterns) stack.addPattern(pattern, self.lifetime); + } + }); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewWallScrollS2C.java b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewWallScrollS2C.java index 67e77248cc..bf153efb17 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewWallScrollS2C.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewWallScrollS2C.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.common.msgs; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.entities.EntityWallScroll; import net.minecraft.client.Minecraft; @@ -10,52 +12,58 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - // https://github.com/VazkiiMods/Botania/blob/1.18.x/Xplat/src/main/java/vazkii/botania/network/clientbound/PacketSpawnDoppleganger.java -public record MsgNewWallScrollS2C(ClientboundAddEntityPacket inner, BlockPos pos, Direction dir, ItemStack scrollItem, - boolean showsStrokeOrder, int blockSize) implements IMessage { - public static final ResourceLocation ID = modLoc("wallscr"); +public record MsgNewWallScrollS2C( + ClientboundAddEntityPacket inner, + BlockPos pos, + Direction dir, + ItemStack scrollItem, + boolean showsStrokeOrder, + int blockSize) + implements IMessage { + public static final ResourceLocation ID = modLoc("wallscr"); - @Override - public ResourceLocation getFabricId() { - return ID; - } + @Override + public ResourceLocation getFabricId() { + return ID; + } - @Override - public void serialize(FriendlyByteBuf buf) { - inner.write(buf); - buf.writeBlockPos(pos); - buf.writeByte(dir.ordinal()); - buf.writeItem(scrollItem); - buf.writeBoolean(showsStrokeOrder); - buf.writeVarInt(blockSize); - } + @Override + public void serialize(FriendlyByteBuf buf) { + inner.write(buf); + buf.writeBlockPos(pos); + buf.writeByte(dir.ordinal()); + buf.writeItem(scrollItem); + buf.writeBoolean(showsStrokeOrder); + buf.writeVarInt(blockSize); + } - public static MsgNewWallScrollS2C deserialize(FriendlyByteBuf buf) { - var inner = new ClientboundAddEntityPacket(buf); - var pos = buf.readBlockPos(); - var dir = HexUtils.getSafe(Direction.values(), buf.readByte()); - var scroll = buf.readItem(); - var strokeOrder = buf.readBoolean(); - var blockSize = buf.readVarInt(); - return new MsgNewWallScrollS2C(inner, pos, dir, scroll, strokeOrder, blockSize); - } + public static MsgNewWallScrollS2C deserialize(FriendlyByteBuf buf) { + var inner = new ClientboundAddEntityPacket(buf); + var pos = buf.readBlockPos(); + var dir = HexUtils.getSafe(Direction.values(), buf.readByte()); + var scroll = buf.readItem(); + var strokeOrder = buf.readBoolean(); + var blockSize = buf.readVarInt(); + return new MsgNewWallScrollS2C(inner, pos, dir, scroll, strokeOrder, blockSize); + } - public static void handle(MsgNewWallScrollS2C self) { - Minecraft.getInstance().execute(new Runnable() { - @Override - public void run() { - var player = Minecraft.getInstance().player; - if (player != null) { - player.connection.handleAddEntity(self.inner); - var e = player.level().getEntity(self.inner.getId()); - if (e instanceof EntityWallScroll scroll) { - scroll.readSpawnData(self.pos, self.dir, self.scrollItem, self.showsStrokeOrder, - self.blockSize); - } - } - } - }); - } + public static void handle(MsgNewWallScrollS2C self) { + Minecraft.getInstance() + .execute( + new Runnable() { + @Override + public void run() { + var player = Minecraft.getInstance().player; + if (player != null) { + player.connection.handleAddEntity(self.inner); + var e = player.level().getEntity(self.inner.getId()); + if (e instanceof EntityWallScroll scroll) { + scroll.readSpawnData( + self.pos, self.dir, self.scrollItem, self.showsStrokeOrder, self.blockSize); + } + } + } + }); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgOpenSpellGuiS2C.java b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgOpenSpellGuiS2C.java index a06e608bdb..89b33e9e01 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgOpenSpellGuiS2C.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgOpenSpellGuiS2C.java @@ -1,69 +1,72 @@ package at.petrak.hexcasting.common.msgs; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.eval.ResolvedPattern; import at.petrak.hexcasting.client.gui.GuiSpellcasting; import io.netty.buffer.ByteBuf; +import java.util.List; import net.minecraft.client.Minecraft; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.InteractionHand; -import java.util.List; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - /** - * Sent server->client when the player opens the spell gui to request the server provide the current stack. + * Sent server->client when the player opens the spell gui to request the server provide the current + * stack. */ -public record MsgOpenSpellGuiS2C(InteractionHand hand, List<ResolvedPattern> patterns, - List<CompoundTag> stack, - CompoundTag ravenmind, - int parenCount -) - implements IMessage { - public static final ResourceLocation ID = modLoc("cgui"); - - @Override - public ResourceLocation getFabricId() { - return ID; - } - - public static MsgOpenSpellGuiS2C deserialize(ByteBuf buffer) { - var buf = new FriendlyByteBuf(buffer); - - var hand = buf.readEnum(InteractionHand.class); - - var patterns = buf.readList(fbb -> ResolvedPattern.fromNBT(fbb.readAnySizeNbt())); - - var stack = buf.readList(FriendlyByteBuf::readNbt); - var raven = buf.readAnySizeNbt(); - - var parenCount = buf.readVarInt(); - - return new MsgOpenSpellGuiS2C(hand, patterns, stack, raven, parenCount); - } - - public void serialize(FriendlyByteBuf buf) { - buf.writeEnum(this.hand); - - buf.writeCollection(this.patterns, (fbb, pat) -> fbb.writeNbt(pat.serializeToNBT())); - - buf.writeCollection(this.stack, FriendlyByteBuf::writeNbt); - buf.writeNbt(this.ravenmind); - - buf.writeVarInt(this.parenCount); - } - - public static void handle(MsgOpenSpellGuiS2C msg) { - Minecraft.getInstance().execute(new Runnable() { - @Override - public void run() { - var mc = Minecraft.getInstance(); - mc.setScreen( - new GuiSpellcasting(msg.hand(), msg.patterns(), msg.stack, msg.ravenmind, - msg.parenCount)); - } - }); - } +public record MsgOpenSpellGuiS2C( + InteractionHand hand, + List<ResolvedPattern> patterns, + List<CompoundTag> stack, + CompoundTag ravenmind, + int parenCount) + implements IMessage { + public static final ResourceLocation ID = modLoc("cgui"); + + @Override + public ResourceLocation getFabricId() { + return ID; + } + + public static MsgOpenSpellGuiS2C deserialize(ByteBuf buffer) { + var buf = new FriendlyByteBuf(buffer); + + var hand = buf.readEnum(InteractionHand.class); + + var patterns = buf.readList(fbb -> ResolvedPattern.fromNBT(fbb.readAnySizeNbt())); + + var stack = buf.readList(FriendlyByteBuf::readNbt); + var raven = buf.readAnySizeNbt(); + + var parenCount = buf.readVarInt(); + + return new MsgOpenSpellGuiS2C(hand, patterns, stack, raven, parenCount); + } + + public void serialize(FriendlyByteBuf buf) { + buf.writeEnum(this.hand); + + buf.writeCollection(this.patterns, (fbb, pat) -> fbb.writeNbt(pat.serializeToNBT())); + + buf.writeCollection(this.stack, FriendlyByteBuf::writeNbt); + buf.writeNbt(this.ravenmind); + + buf.writeVarInt(this.parenCount); + } + + public static void handle(MsgOpenSpellGuiS2C msg) { + Minecraft.getInstance() + .execute( + new Runnable() { + @Override + public void run() { + var mc = Minecraft.getInstance(); + mc.setScreen( + new GuiSpellcasting( + msg.hand(), msg.patterns(), msg.stack, msg.ravenmind, msg.parenCount)); + } + }); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgRecalcWallScrollDisplayS2C.java b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgRecalcWallScrollDisplayS2C.java index 137c97f534..a6202e4e5a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgRecalcWallScrollDisplayS2C.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgRecalcWallScrollDisplayS2C.java @@ -1,48 +1,49 @@ package at.petrak.hexcasting.common.msgs; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.common.entities.EntityWallScroll; import io.netty.buffer.ByteBuf; import net.minecraft.client.Minecraft; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - -/** - * Sent S->C to have a wall scroll recalculate its pattern, to get readability offset. - */ -public record MsgRecalcWallScrollDisplayS2C(int entityId, boolean showStrokeOrder) implements IMessage { - public static final ResourceLocation ID = modLoc("redoscroll"); +/** Sent S->C to have a wall scroll recalculate its pattern, to get readability offset. */ +public record MsgRecalcWallScrollDisplayS2C(int entityId, boolean showStrokeOrder) + implements IMessage { + public static final ResourceLocation ID = modLoc("redoscroll"); - public static MsgRecalcWallScrollDisplayS2C deserialize(ByteBuf buffer) { - var buf = new FriendlyByteBuf(buffer); - var id = buf.readVarInt(); - var showStrokeOrder = buf.readBoolean(); - return new MsgRecalcWallScrollDisplayS2C(id, showStrokeOrder); - } + public static MsgRecalcWallScrollDisplayS2C deserialize(ByteBuf buffer) { + var buf = new FriendlyByteBuf(buffer); + var id = buf.readVarInt(); + var showStrokeOrder = buf.readBoolean(); + return new MsgRecalcWallScrollDisplayS2C(id, showStrokeOrder); + } - @Override - public void serialize(FriendlyByteBuf buf) { - buf.writeVarInt(entityId); - buf.writeBoolean(showStrokeOrder); - } + @Override + public void serialize(FriendlyByteBuf buf) { + buf.writeVarInt(entityId); + buf.writeBoolean(showStrokeOrder); + } - @Override - public ResourceLocation getFabricId() { - return ID; - } + @Override + public ResourceLocation getFabricId() { + return ID; + } - public static void handle(MsgRecalcWallScrollDisplayS2C msg) { - Minecraft.getInstance().execute(new Runnable() { - @Override - public void run() { - var mc = Minecraft.getInstance(); - var entity = mc.level.getEntity(msg.entityId); - if (entity instanceof EntityWallScroll scroll - && scroll.getShowsStrokeOrder() != msg.showStrokeOrder) { - scroll.recalculateDisplay(); - } - } - }); - } + public static void handle(MsgRecalcWallScrollDisplayS2C msg) { + Minecraft.getInstance() + .execute( + new Runnable() { + @Override + public void run() { + var mc = Minecraft.getInstance(); + var entity = mc.level.getEntity(msg.entityId); + if (entity instanceof EntityWallScroll scroll + && scroll.getShowsStrokeOrder() != msg.showStrokeOrder) { + scroll.recalculateDisplay(); + } + } + }); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgShiftScrollC2S.java b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgShiftScrollC2S.java index e1f4d354a6..1077914de1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgShiftScrollC2S.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgShiftScrollC2S.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.common.msgs; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.utils.NBTHelper; import at.petrak.hexcasting.common.items.storage.ItemAbacus; @@ -18,135 +20,163 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - /** - * Sent client->server when the client shift+scrolls with a shift-scrollable item - * or scrolls in the spellcasting UI. + * Sent client->server when the client shift+scrolls with a shift-scrollable item or scrolls in the + * spellcasting UI. */ -public record MsgShiftScrollC2S(double mainHandDelta, double offHandDelta, boolean isCtrl, boolean invertSpellbook, - boolean invertAbacus) implements IMessage { - public static final ResourceLocation ID = modLoc("scroll"); - - @Override - public ResourceLocation getFabricId() { - return ID; - } - - public static MsgShiftScrollC2S deserialize(ByteBuf buffer) { - var buf = new FriendlyByteBuf(buffer); - var mainHandDelta = buf.readDouble(); - var offHandDelta = buf.readDouble(); - var isCtrl = buf.readBoolean(); - var invertSpellbook = buf.readBoolean(); - var invertAbacus = buf.readBoolean(); - return new MsgShiftScrollC2S(mainHandDelta, offHandDelta, isCtrl, invertSpellbook, invertAbacus); - } - - public void serialize(FriendlyByteBuf buf) { - buf.writeDouble(this.mainHandDelta); - buf.writeDouble(this.offHandDelta); - buf.writeBoolean(this.isCtrl); - buf.writeBoolean(this.invertSpellbook); - buf.writeBoolean(this.invertAbacus); - } - - public void handle(MinecraftServer server, ServerPlayer sender) { - server.execute(() -> { - handleForHand(sender, InteractionHand.MAIN_HAND, mainHandDelta); - handleForHand(sender, InteractionHand.OFF_HAND, offHandDelta); - }); - } - - private void handleForHand(ServerPlayer sender, InteractionHand hand, double delta) { - if (delta != 0) { - var stack = sender.getItemInHand(hand); - - if (stack.getItem() == HexItems.SPELLBOOK) { - spellbook(sender, hand, stack, delta); - } else if (stack.getItem() == HexItems.ABACUS) { - abacus(sender, hand, stack, delta); - } - } - } - - private void spellbook(ServerPlayer sender, InteractionHand hand, ItemStack stack, double delta) { - if (invertSpellbook) { - delta = -delta; - } - - var newIdx = ItemSpellbook.rotatePageIdx(stack, delta < 0.0); - - var len = ItemSpellbook.highestPage(stack); - - var sealed = ItemSpellbook.isSealed(stack); - - MutableComponent component; - if (hand == InteractionHand.OFF_HAND && stack.hasCustomHoverName()) { - if (sealed) { - component = Component.translatable("hexcasting.tooltip.spellbook.page_with_name.sealed", - Component.literal(String.valueOf(newIdx)).withStyle(ChatFormatting.WHITE), - Component.literal(String.valueOf(len)).withStyle(ChatFormatting.WHITE), - Component.literal("").withStyle(stack.getRarity().color, ChatFormatting.ITALIC) - .append(stack.getHoverName()), - Component.translatable("hexcasting.tooltip.spellbook.sealed").withStyle(ChatFormatting.GOLD)); - } else { - component = Component.translatable("hexcasting.tooltip.spellbook.page_with_name", - Component.literal(String.valueOf(newIdx)).withStyle(ChatFormatting.WHITE), - Component.literal(String.valueOf(len)).withStyle(ChatFormatting.WHITE), - Component.literal("").withStyle(stack.getRarity().color, ChatFormatting.ITALIC) - .append(stack.getHoverName())); - } - - } else { - if (sealed) { - component = Component.translatable("hexcasting.tooltip.spellbook.page.sealed", - Component.literal(String.valueOf(newIdx)).withStyle(ChatFormatting.WHITE), - Component.literal(String.valueOf(len)).withStyle(ChatFormatting.WHITE), - Component.translatable("hexcasting.tooltip.spellbook.sealed").withStyle(ChatFormatting.GOLD)); - } else { - component = Component.translatable("hexcasting.tooltip.spellbook.page", - Component.literal(String.valueOf(newIdx)).withStyle(ChatFormatting.WHITE), - Component.literal(String.valueOf(len)).withStyle(ChatFormatting.WHITE)); - } - } - - sender.displayClientMessage(component.withStyle(ChatFormatting.GRAY), true); - } - - private void abacus(ServerPlayer sender, InteractionHand hand, ItemStack stack, double delta) { - if (invertAbacus) { - delta = -delta; - } - - var increase = delta < 0; - double num = NBTHelper.getDouble(stack, ItemAbacus.TAG_VALUE); - - double shiftDelta; - float pitch; - if (hand == InteractionHand.MAIN_HAND) { - shiftDelta = this.isCtrl ? 10 : 1; - pitch = this.isCtrl ? 0.7f : 0.9f; - } else { - shiftDelta = this.isCtrl ? 0.01 : 0.1; - pitch = this.isCtrl ? 1.3f : 1.0f; - } - - int scale = Math.max((int) Math.floor(Math.abs(delta)), 1); - - num += scale * shiftDelta * (increase ? 1 : -1); - NBTHelper.putDouble(stack, ItemAbacus.TAG_VALUE, num); - - pitch *= (increase ? 1.05f : 0.95f); - pitch += (Math.random() - 0.5) * 0.1; - sender.level().playSound(null, sender.getX(), sender.getY(), sender.getZ(), - HexSounds.ABACUS, SoundSource.PLAYERS, 0.5f, pitch); - - var datumTag = HexItems.ABACUS.readIotaTag(stack); - if (datumTag != null) { - var popup = IotaType.getDisplay(datumTag); - sender.displayClientMessage( - Component.translatable("hexcasting.tooltip.abacus", popup).withStyle(ChatFormatting.GREEN), true); - } - } +public record MsgShiftScrollC2S( + double mainHandDelta, + double offHandDelta, + boolean isCtrl, + boolean invertSpellbook, + boolean invertAbacus) + implements IMessage { + public static final ResourceLocation ID = modLoc("scroll"); + + @Override + public ResourceLocation getFabricId() { + return ID; + } + + public static MsgShiftScrollC2S deserialize(ByteBuf buffer) { + var buf = new FriendlyByteBuf(buffer); + var mainHandDelta = buf.readDouble(); + var offHandDelta = buf.readDouble(); + var isCtrl = buf.readBoolean(); + var invertSpellbook = buf.readBoolean(); + var invertAbacus = buf.readBoolean(); + return new MsgShiftScrollC2S( + mainHandDelta, offHandDelta, isCtrl, invertSpellbook, invertAbacus); + } + + public void serialize(FriendlyByteBuf buf) { + buf.writeDouble(this.mainHandDelta); + buf.writeDouble(this.offHandDelta); + buf.writeBoolean(this.isCtrl); + buf.writeBoolean(this.invertSpellbook); + buf.writeBoolean(this.invertAbacus); + } + + public void handle(MinecraftServer server, ServerPlayer sender) { + server.execute( + () -> { + handleForHand(sender, InteractionHand.MAIN_HAND, mainHandDelta); + handleForHand(sender, InteractionHand.OFF_HAND, offHandDelta); + }); + } + + private void handleForHand(ServerPlayer sender, InteractionHand hand, double delta) { + if (delta != 0) { + var stack = sender.getItemInHand(hand); + + if (stack.getItem() == HexItems.SPELLBOOK) { + spellbook(sender, hand, stack, delta); + } else if (stack.getItem() == HexItems.ABACUS) { + abacus(sender, hand, stack, delta); + } + } + } + + private void spellbook(ServerPlayer sender, InteractionHand hand, ItemStack stack, double delta) { + if (invertSpellbook) { + delta = -delta; + } + + var newIdx = ItemSpellbook.rotatePageIdx(stack, delta < 0.0); + + var len = ItemSpellbook.highestPage(stack); + + var sealed = ItemSpellbook.isSealed(stack); + + MutableComponent component; + if (hand == InteractionHand.OFF_HAND && stack.hasCustomHoverName()) { + if (sealed) { + component = + Component.translatable( + "hexcasting.tooltip.spellbook.page_with_name.sealed", + Component.literal(String.valueOf(newIdx)).withStyle(ChatFormatting.WHITE), + Component.literal(String.valueOf(len)).withStyle(ChatFormatting.WHITE), + Component.literal("") + .withStyle(stack.getRarity().color, ChatFormatting.ITALIC) + .append(stack.getHoverName()), + Component.translatable("hexcasting.tooltip.spellbook.sealed") + .withStyle(ChatFormatting.GOLD)); + } else { + component = + Component.translatable( + "hexcasting.tooltip.spellbook.page_with_name", + Component.literal(String.valueOf(newIdx)).withStyle(ChatFormatting.WHITE), + Component.literal(String.valueOf(len)).withStyle(ChatFormatting.WHITE), + Component.literal("") + .withStyle(stack.getRarity().color, ChatFormatting.ITALIC) + .append(stack.getHoverName())); + } + + } else { + if (sealed) { + component = + Component.translatable( + "hexcasting.tooltip.spellbook.page.sealed", + Component.literal(String.valueOf(newIdx)).withStyle(ChatFormatting.WHITE), + Component.literal(String.valueOf(len)).withStyle(ChatFormatting.WHITE), + Component.translatable("hexcasting.tooltip.spellbook.sealed") + .withStyle(ChatFormatting.GOLD)); + } else { + component = + Component.translatable( + "hexcasting.tooltip.spellbook.page", + Component.literal(String.valueOf(newIdx)).withStyle(ChatFormatting.WHITE), + Component.literal(String.valueOf(len)).withStyle(ChatFormatting.WHITE)); + } + } + + sender.displayClientMessage(component.withStyle(ChatFormatting.GRAY), true); + } + + private void abacus(ServerPlayer sender, InteractionHand hand, ItemStack stack, double delta) { + if (invertAbacus) { + delta = -delta; + } + + var increase = delta < 0; + double num = NBTHelper.getDouble(stack, ItemAbacus.TAG_VALUE); + + double shiftDelta; + float pitch; + if (hand == InteractionHand.MAIN_HAND) { + shiftDelta = this.isCtrl ? 10 : 1; + pitch = this.isCtrl ? 0.7f : 0.9f; + } else { + shiftDelta = this.isCtrl ? 0.01 : 0.1; + pitch = this.isCtrl ? 1.3f : 1.0f; + } + + int scale = Math.max((int) Math.floor(Math.abs(delta)), 1); + + num += scale * shiftDelta * (increase ? 1 : -1); + NBTHelper.putDouble(stack, ItemAbacus.TAG_VALUE, num); + + pitch *= (increase ? 1.05f : 0.95f); + pitch += (Math.random() - 0.5) * 0.1; + sender + .level() + .playSound( + null, + sender.getX(), + sender.getY(), + sender.getZ(), + HexSounds.ABACUS, + SoundSource.PLAYERS, + 0.5f, + pitch); + + var datumTag = HexItems.ABACUS.readIotaTag(stack); + if (datumTag != null) { + var popup = IotaType.getDisplay(datumTag); + sender.displayClientMessage( + Component.translatable("hexcasting.tooltip.abacus", popup) + .withStyle(ChatFormatting.GREEN), + true); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/particles/ConjureParticleOptions.java b/Common/src/main/java/at/petrak/hexcasting/common/particles/ConjureParticleOptions.java index 79df382994..4c1d441389 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/particles/ConjureParticleOptions.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/particles/ConjureParticleOptions.java @@ -5,62 +5,63 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import java.util.Locale; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleType; import net.minecraft.network.FriendlyByteBuf; -import java.util.Locale; - public record ConjureParticleOptions(int color) implements ParticleOptions { - @Override - public ParticleType<?> getType() { - return HexParticles.CONJURE_PARTICLE; - } + @Override + public ParticleType<?> getType() { + return HexParticles.CONJURE_PARTICLE; + } - @Override - public void writeToNetwork(FriendlyByteBuf buf) { - buf.writeInt(this.color); - } + @Override + public void writeToNetwork(FriendlyByteBuf buf) { + buf.writeInt(this.color); + } - @Override - public String writeToString() { - return String.format(Locale.ROOT, "%s %s", this.color); - } + @Override + public String writeToString() { + return String.format(Locale.ROOT, "%s %s", this.color); + } - public static final Deserializer<ConjureParticleOptions> DESERIALIZER = new Deserializer<>() { - @Override - public ConjureParticleOptions fromCommand(ParticleType<ConjureParticleOptions> type, - StringReader reader) throws CommandSyntaxException { + public static final Deserializer<ConjureParticleOptions> DESERIALIZER = + new Deserializer<>() { + @Override + public ConjureParticleOptions fromCommand( + ParticleType<ConjureParticleOptions> type, StringReader reader) + throws CommandSyntaxException { - reader.expect(' '); - var color = reader.readInt(); - return new ConjureParticleOptions(color); - } + reader.expect(' '); + var color = reader.readInt(); + return new ConjureParticleOptions(color); + } - @Override - public ConjureParticleOptions fromNetwork(ParticleType<ConjureParticleOptions> type, - FriendlyByteBuf buf) { - var col = buf.readInt(); - return new ConjureParticleOptions(col); - } - }; + @Override + public ConjureParticleOptions fromNetwork( + ParticleType<ConjureParticleOptions> type, FriendlyByteBuf buf) { + var col = buf.readInt(); + return new ConjureParticleOptions(col); + } + }; - public static class Type extends ParticleType<ConjureParticleOptions> { - public Type(boolean pOverrideLimiter) { - super(pOverrideLimiter, DESERIALIZER); - } + public static class Type extends ParticleType<ConjureParticleOptions> { + public Type(boolean pOverrideLimiter) { + super(pOverrideLimiter, DESERIALIZER); + } - public static final Codec<ConjureParticleOptions> CODEC = RecordCodecBuilder.create( - instance -> instance.group( - Codec.INT.fieldOf("color") - .forGetter((ConjureParticleOptions o) -> o.color) - ) - .apply(instance, ConjureParticleOptions::new) - ); + public static final Codec<ConjureParticleOptions> CODEC = + RecordCodecBuilder.create( + instance -> + instance + .group( + Codec.INT.fieldOf("color").forGetter((ConjureParticleOptions o) -> o.color)) + .apply(instance, ConjureParticleOptions::new)); - @Override - public Codec<ConjureParticleOptions> codec() { - return CODEC; - } - } + @Override + public Codec<ConjureParticleOptions> codec() { + return CODEC; + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/BrainsweepRecipe.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/BrainsweepRecipe.java index 8f6db1efb0..ff5a163894 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/BrainsweepRecipe.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/BrainsweepRecipe.java @@ -23,12 +23,12 @@ // God I am a horrible person public record BrainsweepRecipe( - ResourceLocation id, - StateIngredient blockIn, - BrainsweepeeIngredient entityIn, - long mediaCost, - BlockState result -) implements Recipe<Container> { + ResourceLocation id, + StateIngredient blockIn, + BrainsweepeeIngredient entityIn, + long mediaCost, + BlockState result) + implements Recipe<Container> { public boolean matches(BlockState blockIn, Entity victim, ServerLevel level) { return this.blockIn.test(blockIn) && this.entityIn.test(victim, level); } @@ -87,7 +87,8 @@ public static class Serializer extends RecipeSerializerBase<BrainsweepRecipe> { @Override public @NotNull BrainsweepRecipe fromJson(ResourceLocation recipeID, JsonObject json) { var blockIn = StateIngredientHelper.deserialize(GsonHelper.getAsJsonObject(json, "blockIn")); - var villagerIn = BrainsweepeeIngredient.deserialize(GsonHelper.getAsJsonObject(json, "entityIn")); + var villagerIn = + BrainsweepeeIngredient.deserialize(GsonHelper.getAsJsonObject(json, "entityIn")); var cost = GsonHelper.getAsInt(json, "cost"); var result = StateIngredientHelper.readBlockState(GsonHelper.getAsJsonObject(json, "result")); return new BrainsweepRecipe(recipeID, blockIn, villagerIn, cost, result); diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/HexRecipeStuffRegistry.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/HexRecipeStuffRegistry.java index cc2ffbba0f..b62f71aa51 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/HexRecipeStuffRegistry.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/HexRecipeStuffRegistry.java @@ -1,59 +1,61 @@ package at.petrak.hexcasting.common.recipe; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.HexAPI; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.BiConsumer; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.RecipeType; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.function.BiConsumer; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class HexRecipeStuffRegistry { - public static void registerSerializers(BiConsumer<RecipeSerializer<?>, ResourceLocation> r) { - for (var e : SERIALIZERS.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } - - public static void registerTypes(BiConsumer<RecipeType<?>, ResourceLocation> r) { - for (var e : TYPES.entrySet()) { - r.accept(e.getValue(), e.getKey()); - } - } - - private static final Map<ResourceLocation, RecipeSerializer<?>> SERIALIZERS = new LinkedHashMap<>(); - private static final Map<ResourceLocation, RecipeType<?>> TYPES = new LinkedHashMap<>(); - - public static final RecipeSerializer<?> BRAINSWEEP = registerSerializer("brainsweep", - new BrainsweepRecipe.Serializer()); - public static final RecipeSerializer<SealThingsRecipe> SEAL_FOCUS = registerSerializer( - "seal_focus", SealThingsRecipe.FOCUS_SERIALIZER); - public static final RecipeSerializer<SealThingsRecipe> SEAL_SPELLBOOK = registerSerializer( - "seal_spellbook", SealThingsRecipe.SPELLBOOK_SERIALIZER); - - public static RecipeType<BrainsweepRecipe> BRAINSWEEP_TYPE = registerType("brainsweep"); - - private static <T extends Recipe<?>> RecipeSerializer<T> registerSerializer(String name, RecipeSerializer<T> rs) { - var old = SERIALIZERS.put(modLoc(name), rs); - if (old != null) { - throw new IllegalArgumentException("Typo? Duplicate id " + name); - } - return rs; - } - - private static <T extends Recipe<?>> RecipeType<T> registerType(String name) { - var type = new RecipeType<T>() { - @Override - public String toString() { - return HexAPI.MOD_ID + ":" + name; - } - }; - // never will be a collision because it's a new object - TYPES.put(modLoc(name), type); - return type; - } + public static void registerSerializers(BiConsumer<RecipeSerializer<?>, ResourceLocation> r) { + for (var e : SERIALIZERS.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } + + public static void registerTypes(BiConsumer<RecipeType<?>, ResourceLocation> r) { + for (var e : TYPES.entrySet()) { + r.accept(e.getValue(), e.getKey()); + } + } + + private static final Map<ResourceLocation, RecipeSerializer<?>> SERIALIZERS = + new LinkedHashMap<>(); + private static final Map<ResourceLocation, RecipeType<?>> TYPES = new LinkedHashMap<>(); + + public static final RecipeSerializer<?> BRAINSWEEP = + registerSerializer("brainsweep", new BrainsweepRecipe.Serializer()); + public static final RecipeSerializer<SealThingsRecipe> SEAL_FOCUS = + registerSerializer("seal_focus", SealThingsRecipe.FOCUS_SERIALIZER); + public static final RecipeSerializer<SealThingsRecipe> SEAL_SPELLBOOK = + registerSerializer("seal_spellbook", SealThingsRecipe.SPELLBOOK_SERIALIZER); + + public static RecipeType<BrainsweepRecipe> BRAINSWEEP_TYPE = registerType("brainsweep"); + + private static <T extends Recipe<?>> RecipeSerializer<T> registerSerializer( + String name, RecipeSerializer<T> rs) { + var old = SERIALIZERS.put(modLoc(name), rs); + if (old != null) { + throw new IllegalArgumentException("Typo? Duplicate id " + name); + } + return rs; + } + + private static <T extends Recipe<?>> RecipeType<T> registerType(String name) { + var type = + new RecipeType<T>() { + @Override + public String toString() { + return HexAPI.MOD_ID + ":" + name; + } + }; + // never will be a collision because it's a new object + TYPES.put(modLoc(name), type); + return type; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/RecipeSerializerBase.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/RecipeSerializerBase.java index 58651bc6a5..9108895bb8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/RecipeSerializerBase.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/RecipeSerializerBase.java @@ -1,35 +1,31 @@ package at.petrak.hexcasting.common.recipe; import at.petrak.hexcasting.annotations.SoftImplement; +import javax.annotation.Nullable; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeSerializer; -import javax.annotation.Nullable; - // https://github.com/VazkiiMods/Botania/blob/1.18.x/Xplat/src/main/java/vazkii/botania/common/crafting/RecipeSerializerBase.java // TL;DR Forge bad, so we have to cursed self-mixin public abstract class RecipeSerializerBase<T extends Recipe<?>> implements RecipeSerializer<T> { - @Nullable - private ResourceLocation registryName; - - @SoftImplement("IForgeRegistryEntry") - public RecipeSerializerBase<T> setRegistryName(ResourceLocation name) { - registryName = name; - return this; - } + @Nullable private ResourceLocation registryName; - @SoftImplement("IForgeRegistryEntry") - @Nullable - public ResourceLocation getRegistryName() { - return registryName; - } + @SoftImplement("IForgeRegistryEntry") + public RecipeSerializerBase<T> setRegistryName(ResourceLocation name) { + registryName = name; + return this; + } - @SoftImplement("IForgeRegistryEntry") - @SuppressWarnings("unchecked") - public Class<RecipeSerializer<?>> getRegistryType() { - Class<?> clazz = RecipeSerializer.class; - return (Class<RecipeSerializer<?>>) clazz; - } + @SoftImplement("IForgeRegistryEntry") + @Nullable public ResourceLocation getRegistryName() { + return registryName; + } + @SoftImplement("IForgeRegistryEntry") + @SuppressWarnings("unchecked") + public Class<RecipeSerializer<?>> getRegistryType() { + Class<?> clazz = RecipeSerializer.class; + return (Class<RecipeSerializer<?>>) clazz; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/SealSpellbookRecipe.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/SealSpellbookRecipe.java index 570d6631be..3f4d290d24 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/SealSpellbookRecipe.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/SealSpellbookRecipe.java @@ -15,50 +15,50 @@ import org.jetbrains.annotations.NotNull; public class SealSpellbookRecipe extends ShapelessRecipe { - public static final SimpleCraftingRecipeSerializer<SealSpellbookRecipe> SERIALIZER = - new SimpleCraftingRecipeSerializer<>(SealSpellbookRecipe::new); + public static final SimpleCraftingRecipeSerializer<SealSpellbookRecipe> SERIALIZER = + new SimpleCraftingRecipeSerializer<>(SealSpellbookRecipe::new); - private static ItemStack getSealedStack() { - ItemStack output = new ItemStack(HexItems.SPELLBOOK); - ItemSpellbook.setSealed(output, true); - NBTHelper.putString(output, IotaHolderItem.TAG_OVERRIDE_VISUALLY, "any"); - return output; - } + private static ItemStack getSealedStack() { + ItemStack output = new ItemStack(HexItems.SPELLBOOK); + ItemSpellbook.setSealed(output, true); + NBTHelper.putString(output, IotaHolderItem.TAG_OVERRIDE_VISUALLY, "any"); + return output; + } - private static NonNullList<Ingredient> createIngredients() { - NonNullList<Ingredient> ingredients = NonNullList.createWithCapacity(2); - ingredients.add(IXplatAbstractions.INSTANCE.getUnsealedIngredient(new ItemStack(HexItems.SPELLBOOK))); - ingredients.add(Ingredient.of(Items.HONEYCOMB)); - return ingredients; - } + private static NonNullList<Ingredient> createIngredients() { + NonNullList<Ingredient> ingredients = NonNullList.createWithCapacity(2); + ingredients.add( + IXplatAbstractions.INSTANCE.getUnsealedIngredient(new ItemStack(HexItems.SPELLBOOK))); + ingredients.add(Ingredient.of(Items.HONEYCOMB)); + return ingredients; + } - public SealSpellbookRecipe(ResourceLocation id, CraftingBookCategory category) { - super(id, "", category, getSealedStack(), createIngredients()); - } + public SealSpellbookRecipe(ResourceLocation id, CraftingBookCategory category) { + super(id, "", category, getSealedStack(), createIngredients()); + } - @Override - public @NotNull ItemStack assemble(CraftingContainer inv, RegistryAccess access) { - ItemStack out = ItemStack.EMPTY; + @Override + public @NotNull ItemStack assemble(CraftingContainer inv, RegistryAccess access) { + ItemStack out = ItemStack.EMPTY; - for (int i = 0; i < inv.getContainerSize(); i++) { - var stack = inv.getItem(i); - if (stack.is(HexItems.SPELLBOOK)) { - out = stack.copy(); - break; - } - } + for (int i = 0; i < inv.getContainerSize(); i++) { + var stack = inv.getItem(i); + if (stack.is(HexItems.SPELLBOOK)) { + out = stack.copy(); + break; + } + } - if (!out.isEmpty()) { - ItemSpellbook.setSealed(out, true); - out.setCount(1); - } + if (!out.isEmpty()) { + ItemSpellbook.setSealed(out, true); + out.setCount(1); + } - return out; - } + return out; + } - @Override - public @NotNull RecipeSerializer<?> getSerializer() { - return SERIALIZER; - } + @Override + public @NotNull RecipeSerializer<?> getSerializer() { + return SERIALIZER; + } } - diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/SealThingsRecipe.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/SealThingsRecipe.java index 365d68fe59..3498a7397d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/SealThingsRecipe.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/SealThingsRecipe.java @@ -4,6 +4,7 @@ import at.petrak.hexcasting.common.items.storage.ItemFocus; import at.petrak.hexcasting.common.items.storage.ItemSpellbook; import at.petrak.hexcasting.common.lib.HexItems; +import java.util.Locale; import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.StringRepresentable; @@ -16,112 +17,110 @@ import net.minecraft.world.level.Level; import org.jetbrains.annotations.NotNull; -import java.util.Locale; - public class SealThingsRecipe extends CustomRecipe { - public final Sealee sealee; - - public static final SimpleCraftingRecipeSerializer<SealThingsRecipe> FOCUS_SERIALIZER = - new SimpleCraftingRecipeSerializer<>(SealThingsRecipe::focus); - public static final SimpleCraftingRecipeSerializer<SealThingsRecipe> SPELLBOOK_SERIALIZER = - new SimpleCraftingRecipeSerializer<>(SealThingsRecipe::spellbook); - - public SealThingsRecipe(ResourceLocation id, CraftingBookCategory category, Sealee sealee) { - super(id, category); - this.sealee = sealee; - } - - - @Override - public boolean canCraftInDimensions(int width, int height) { - return width * height >= 2; - } - - @Override - public boolean matches(CraftingContainer container, Level level) { - boolean foundComb = false; - boolean foundSealee = false; - - for (int i = 0; i < container.getContainerSize(); i++) { - var stack = container.getItem(i); - if (this.sealee.isCorrectSealee(stack)) { - if (foundSealee) return false; - foundSealee = true; - } else if (stack.is(HexTags.Items.SEAL_MATERIALS)) { - if (foundComb) return false; - foundComb = true; - } - } - - return foundComb && foundSealee; - } - - @Override - public ItemStack assemble(CraftingContainer inv, RegistryAccess registryAccess) { - ItemStack sealee = ItemStack.EMPTY; - - for (int i = 0; i < inv.getContainerSize(); i++) { - var stack = inv.getItem(i); - if (this.sealee.isCorrectSealee(stack)) { - sealee = stack.copy(); - break; - } - } - - if (!sealee.isEmpty()) { - this.sealee.seal(sealee); - sealee.setCount(1); - } - - return sealee; - } - - @Override - public @NotNull RecipeSerializer<?> getSerializer() { - return switch (this.sealee) { - case FOCUS -> FOCUS_SERIALIZER; - case SPELLBOOK -> SPELLBOOK_SERIALIZER; - }; - } - - public static SealThingsRecipe focus(ResourceLocation id, CraftingBookCategory category) { - return new SealThingsRecipe(id, category, Sealee.FOCUS); - } - - public static SealThingsRecipe spellbook(ResourceLocation id, CraftingBookCategory category) { - return new SealThingsRecipe(id, category, Sealee.SPELLBOOK); - } - - public enum Sealee implements StringRepresentable { - FOCUS, - SPELLBOOK; - - @Override - public String getSerializedName() { - return this.name().toLowerCase(Locale.ROOT); - } - - public boolean isCorrectSealee(ItemStack stack) { - return switch (this) { - case FOCUS -> stack.is(HexItems.FOCUS) - && HexItems.FOCUS.readIotaTag(stack) != null - && !ItemFocus.isSealed(stack); - case SPELLBOOK -> stack.is(HexItems.SPELLBOOK) - && HexItems.SPELLBOOK.readIotaTag(stack) != null - && !ItemSpellbook.isSealed(stack); - }; - } - - public void seal(ItemStack stack) { - switch (this) { - case FOCUS -> { - ItemFocus.seal(stack); - } - case SPELLBOOK -> { - ItemSpellbook.setSealed(stack, true); - } - } - } - } + public final Sealee sealee; + + public static final SimpleCraftingRecipeSerializer<SealThingsRecipe> FOCUS_SERIALIZER = + new SimpleCraftingRecipeSerializer<>(SealThingsRecipe::focus); + public static final SimpleCraftingRecipeSerializer<SealThingsRecipe> SPELLBOOK_SERIALIZER = + new SimpleCraftingRecipeSerializer<>(SealThingsRecipe::spellbook); + + public SealThingsRecipe(ResourceLocation id, CraftingBookCategory category, Sealee sealee) { + super(id, category); + this.sealee = sealee; + } + + @Override + public boolean canCraftInDimensions(int width, int height) { + return width * height >= 2; + } + + @Override + public boolean matches(CraftingContainer container, Level level) { + boolean foundComb = false; + boolean foundSealee = false; + + for (int i = 0; i < container.getContainerSize(); i++) { + var stack = container.getItem(i); + if (this.sealee.isCorrectSealee(stack)) { + if (foundSealee) return false; + foundSealee = true; + } else if (stack.is(HexTags.Items.SEAL_MATERIALS)) { + if (foundComb) return false; + foundComb = true; + } + } + + return foundComb && foundSealee; + } + + @Override + public ItemStack assemble(CraftingContainer inv, RegistryAccess registryAccess) { + ItemStack sealee = ItemStack.EMPTY; + + for (int i = 0; i < inv.getContainerSize(); i++) { + var stack = inv.getItem(i); + if (this.sealee.isCorrectSealee(stack)) { + sealee = stack.copy(); + break; + } + } + + if (!sealee.isEmpty()) { + this.sealee.seal(sealee); + sealee.setCount(1); + } + + return sealee; + } + + @Override + public @NotNull RecipeSerializer<?> getSerializer() { + return switch (this.sealee) { + case FOCUS -> FOCUS_SERIALIZER; + case SPELLBOOK -> SPELLBOOK_SERIALIZER; + }; + } + + public static SealThingsRecipe focus(ResourceLocation id, CraftingBookCategory category) { + return new SealThingsRecipe(id, category, Sealee.FOCUS); + } + + public static SealThingsRecipe spellbook(ResourceLocation id, CraftingBookCategory category) { + return new SealThingsRecipe(id, category, Sealee.SPELLBOOK); + } + + public enum Sealee implements StringRepresentable { + FOCUS, + SPELLBOOK; + + @Override + public String getSerializedName() { + return this.name().toLowerCase(Locale.ROOT); + } + + public boolean isCorrectSealee(ItemStack stack) { + return switch (this) { + case FOCUS -> + stack.is(HexItems.FOCUS) + && HexItems.FOCUS.readIotaTag(stack) != null + && !ItemFocus.isSealed(stack); + case SPELLBOOK -> + stack.is(HexItems.SPELLBOOK) + && HexItems.SPELLBOOK.readIotaTag(stack) != null + && !ItemSpellbook.isSealed(stack); + }; + } + + public void seal(ItemStack stack) { + switch (this) { + case FOCUS -> { + ItemFocus.seal(stack); + } + case SPELLBOOK -> { + ItemSpellbook.setSealed(stack, true); + } + } + } + } } - diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredient.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredient.java index cd2cca2268..e5526910a4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredient.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredient.java @@ -1,37 +1,33 @@ package at.petrak.hexcasting.common.recipe.ingredient; - import com.google.gson.JsonObject; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.state.BlockState; - import java.util.Collections; import java.util.List; import java.util.Random; import java.util.function.Predicate; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; // https://github.com/VazkiiMods/Botania/blob/1.18.x/Common/src/main/java/vazkii/botania/api/recipe/StateIngredient.java // good artists copy and all public interface StateIngredient extends Predicate<BlockState> { - @Override - boolean test(BlockState state); + @Override + boolean test(BlockState state); - BlockState pick(Random random); + BlockState pick(Random random); - JsonObject serialize(); + JsonObject serialize(); - void write(FriendlyByteBuf buffer); + void write(FriendlyByteBuf buffer); - List<ItemStack> getDisplayedStacks(); + List<ItemStack> getDisplayedStacks(); - /** - * A description tooltip to display in areas like JEI recipes. - */ - default List<Component> descriptionTooltip() { - return Collections.emptyList(); - } + /** A description tooltip to display in areas like JEI recipes. */ + default List<Component> descriptionTooltip() { + return Collections.emptyList(); + } - List<BlockState> getDisplayed(); -} \ No newline at end of file + List<BlockState> getDisplayed(); +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientBlock.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientBlock.java index ac9febaf7f..8f455e4337 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientBlock.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientBlock.java @@ -1,7 +1,9 @@ package at.petrak.hexcasting.common.recipe.ingredient; import com.google.gson.JsonObject; -import net.minecraft.core.Registry; +import java.util.Collections; +import java.util.List; +import java.util.Random; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.item.ItemStack; @@ -9,76 +11,72 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; -import java.util.Collections; -import java.util.List; -import java.util.Random; - public class StateIngredientBlock implements StateIngredient { - private final Block block; + private final Block block; - public StateIngredientBlock(Block block) { - this.block = block; - } + public StateIngredientBlock(Block block) { + this.block = block; + } - @Override - public boolean test(BlockState blockState) { - return block == blockState.getBlock(); - } + @Override + public boolean test(BlockState blockState) { + return block == blockState.getBlock(); + } - @Override - public BlockState pick(Random random) { - return block.defaultBlockState(); - } + @Override + public BlockState pick(Random random) { + return block.defaultBlockState(); + } - @Override - public JsonObject serialize() { - JsonObject object = new JsonObject(); - object.addProperty("type", "block"); - object.addProperty("block", BuiltInRegistries.BLOCK.getKey(block).toString()); - return object; - } + @Override + public JsonObject serialize() { + JsonObject object = new JsonObject(); + object.addProperty("type", "block"); + object.addProperty("block", BuiltInRegistries.BLOCK.getKey(block).toString()); + return object; + } - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeVarInt(1); - buffer.writeVarInt(BuiltInRegistries.BLOCK.getId(block)); - } + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeVarInt(1); + buffer.writeVarInt(BuiltInRegistries.BLOCK.getId(block)); + } - @Override - public List<ItemStack> getDisplayedStacks() { - if (block.asItem() == Items.AIR) { - return Collections.emptyList(); - } - return Collections.singletonList(new ItemStack(block)); - } + @Override + public List<ItemStack> getDisplayedStacks() { + if (block.asItem() == Items.AIR) { + return Collections.emptyList(); + } + return Collections.singletonList(new ItemStack(block)); + } - @Override - public List<BlockState> getDisplayed() { - return Collections.singletonList(block.defaultBlockState()); - } + @Override + public List<BlockState> getDisplayed() { + return Collections.singletonList(block.defaultBlockState()); + } - public Block getBlock() { - return block; - } + public Block getBlock() { + return block; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - return block == ((StateIngredientBlock) o).block; - } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return block == ((StateIngredientBlock) o).block; + } - @Override - public int hashCode() { - return block.hashCode(); - } + @Override + public int hashCode() { + return block.hashCode(); + } - @Override - public String toString() { - return "StateIngredientBlock{" + block + "}"; - } -} \ No newline at end of file + @Override + public String toString() { + return "StateIngredientBlock{" + block + "}"; + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientBlockState.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientBlockState.java index c1018f47df..e224feb647 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientBlockState.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientBlockState.java @@ -2,6 +2,8 @@ import com.google.common.collect.ImmutableMap; import com.google.gson.JsonObject; +import java.util.*; +import javax.annotation.Nullable; import net.minecraft.ChatFormatting; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; @@ -11,93 +13,89 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.Property; -import javax.annotation.Nullable; -import java.util.*; - public class StateIngredientBlockState implements StateIngredient { - private final BlockState state; - - public StateIngredientBlockState(BlockState state) { - this.state = state; - } - - @Override - public boolean test(BlockState blockState) { - return this.state == blockState; - } - - @Override - public BlockState pick(Random random) { - return state; - } - - @Override - public JsonObject serialize() { - JsonObject object = StateIngredientHelper.serializeBlockState(state); - object.addProperty("type", "state"); - return object; - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeVarInt(2); - buffer.writeVarInt(Block.getId(state)); - } - - @Override - public List<ItemStack> getDisplayedStacks() { - Block block = state.getBlock(); - if (block.asItem() == Items.AIR) { - return Collections.emptyList(); - } - return Collections.singletonList(new ItemStack(block)); - } - - @Nullable - @Override - public List<Component> descriptionTooltip() { - ImmutableMap<Property<?>, Comparable<?>> map = state.getValues(); - if (map.isEmpty()) { - return StateIngredient.super.descriptionTooltip(); - } - List<Component> tooltip = new ArrayList<>(map.size()); - for (Map.Entry<Property<?>, Comparable<?>> entry : map.entrySet()) { - Property<?> key = entry.getKey(); - @SuppressWarnings({"unchecked", "rawtypes"}) - String name = ((Property) key).getName(entry.getValue()); - - tooltip.add(Component.literal(key.getName() + " = " + name).withStyle(ChatFormatting.GRAY)); - } - return tooltip; - } - - @Override - public List<BlockState> getDisplayed() { - return Collections.singletonList(state); - } - - public BlockState getState() { - return state; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - return state == ((StateIngredientBlockState) o).state; - } - - @Override - public int hashCode() { - return state.hashCode(); - } - - @Override - public String toString() { - return "StateIngredientBlockState{" + state + "}"; - } -} \ No newline at end of file + private final BlockState state; + + public StateIngredientBlockState(BlockState state) { + this.state = state; + } + + @Override + public boolean test(BlockState blockState) { + return this.state == blockState; + } + + @Override + public BlockState pick(Random random) { + return state; + } + + @Override + public JsonObject serialize() { + JsonObject object = StateIngredientHelper.serializeBlockState(state); + object.addProperty("type", "state"); + return object; + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeVarInt(2); + buffer.writeVarInt(Block.getId(state)); + } + + @Override + public List<ItemStack> getDisplayedStacks() { + Block block = state.getBlock(); + if (block.asItem() == Items.AIR) { + return Collections.emptyList(); + } + return Collections.singletonList(new ItemStack(block)); + } + + @Nullable @Override + public List<Component> descriptionTooltip() { + ImmutableMap<Property<?>, Comparable<?>> map = state.getValues(); + if (map.isEmpty()) { + return StateIngredient.super.descriptionTooltip(); + } + List<Component> tooltip = new ArrayList<>(map.size()); + for (Map.Entry<Property<?>, Comparable<?>> entry : map.entrySet()) { + Property<?> key = entry.getKey(); + @SuppressWarnings({"unchecked", "rawtypes"}) + String name = ((Property) key).getName(entry.getValue()); + + tooltip.add(Component.literal(key.getName() + " = " + name).withStyle(ChatFormatting.GRAY)); + } + return tooltip; + } + + @Override + public List<BlockState> getDisplayed() { + return Collections.singletonList(state); + } + + public BlockState getState() { + return state; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return state == ((StateIngredientBlockState) o).state; + } + + @Override + public int hashCode() { + return state.hashCode(); + } + + @Override + public String toString() { + return "StateIngredientBlockState{" + state + "}"; + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientBlocks.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientBlocks.java index eb0291709f..46f914bba2 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientBlocks.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientBlocks.java @@ -3,7 +3,12 @@ import com.google.common.collect.ImmutableSet; import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import net.minecraft.core.Registry; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Random; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.item.ItemStack; @@ -11,88 +16,81 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; -import javax.annotation.Nonnull; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.Random; -import java.util.stream.Collectors; - public class StateIngredientBlocks implements StateIngredient { - protected final ImmutableSet<Block> blocks; + protected final ImmutableSet<Block> blocks; - public StateIngredientBlocks(Collection<Block> blocks) { - this.blocks = ImmutableSet.copyOf(blocks); - } + public StateIngredientBlocks(Collection<Block> blocks) { + this.blocks = ImmutableSet.copyOf(blocks); + } - @Override - public boolean test(BlockState state) { - return blocks.contains(state.getBlock()); - } + @Override + public boolean test(BlockState state) { + return blocks.contains(state.getBlock()); + } - @Override - public BlockState pick(Random random) { - return blocks.asList().get(random.nextInt(blocks.size())).defaultBlockState(); - } + @Override + public BlockState pick(Random random) { + return blocks.asList().get(random.nextInt(blocks.size())).defaultBlockState(); + } - @Override - public JsonObject serialize() { - JsonObject object = new JsonObject(); - object.addProperty("type", "blocks"); - JsonArray array = new JsonArray(); - for (Block block : blocks) { - array.add(BuiltInRegistries.BLOCK.getKey(block).toString()); - } - object.add("blocks", array); - return object; - } + @Override + public JsonObject serialize() { + JsonObject object = new JsonObject(); + object.addProperty("type", "blocks"); + JsonArray array = new JsonArray(); + for (Block block : blocks) { + array.add(BuiltInRegistries.BLOCK.getKey(block).toString()); + } + object.add("blocks", array); + return object; + } - @Override - public void write(FriendlyByteBuf buffer) { - List<Block> blocks = getBlocks(); - buffer.writeVarInt(0); - buffer.writeVarInt(blocks.size()); - for (Block block : blocks) { - buffer.writeVarInt(BuiltInRegistries.BLOCK.getId(block)); - } - } + @Override + public void write(FriendlyByteBuf buffer) { + List<Block> blocks = getBlocks(); + buffer.writeVarInt(0); + buffer.writeVarInt(blocks.size()); + for (Block block : blocks) { + buffer.writeVarInt(BuiltInRegistries.BLOCK.getId(block)); + } + } - @Override - public List<ItemStack> getDisplayedStacks() { - return blocks.stream() - .filter(b -> b.asItem() != Items.AIR) - .map(ItemStack::new) - .collect(Collectors.toList()); - } + @Override + public List<ItemStack> getDisplayedStacks() { + return blocks.stream() + .filter(b -> b.asItem() != Items.AIR) + .map(ItemStack::new) + .collect(Collectors.toList()); + } - @Override - public List<BlockState> getDisplayed() { - return blocks.stream().map(Block::defaultBlockState).collect(Collectors.toList()); - } + @Override + public List<BlockState> getDisplayed() { + return blocks.stream().map(Block::defaultBlockState).collect(Collectors.toList()); + } - @Nonnull - protected List<Block> getBlocks() { - return blocks.asList(); - } + @Nonnull + protected List<Block> getBlocks() { + return blocks.asList(); + } - @Override - public String toString() { - return "StateIngredientBlocks{" + blocks.toString() + "}"; - } + @Override + public String toString() { + return "StateIngredientBlocks{" + blocks.toString() + "}"; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - return blocks.equals(((StateIngredientBlocks) o).blocks); - } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return blocks.equals(((StateIngredientBlocks) o).blocks); + } - @Override - public int hashCode() { - return Objects.hash(blocks); - } + @Override + public int hashCode() { + return Objects.hash(blocks); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientHelper.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientHelper.java index 97e09d9d36..fd411230f3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientHelper.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientHelper.java @@ -5,7 +5,9 @@ import com.google.gson.JsonParseException; import com.mojang.serialization.Dynamic; import com.mojang.serialization.JsonOps; -import net.minecraft.core.Registry; +import java.util.*; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtOps; @@ -19,149 +21,142 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.*; - public class StateIngredientHelper { - public static StateIngredient of(Block block) { - return new StateIngredientBlock(block); - } + public static StateIngredient of(Block block) { + return new StateIngredientBlock(block); + } - public static StateIngredient of(BlockState state) { - return new StateIngredientBlockState(state); - } + public static StateIngredient of(BlockState state) { + return new StateIngredientBlockState(state); + } - public static StateIngredient of(TagKey<Block> tag) { - return of(tag.location()); - } + public static StateIngredient of(TagKey<Block> tag) { + return of(tag.location()); + } - public static StateIngredient of(ResourceLocation id) { - return new StateIngredientTag(id); - } + public static StateIngredient of(ResourceLocation id) { + return new StateIngredientTag(id); + } - public static StateIngredient of(Collection<Block> blocks) { - return new StateIngredientBlocks(blocks); - } + public static StateIngredient of(Collection<Block> blocks) { + return new StateIngredientBlocks(blocks); + } - public static StateIngredient tagExcluding(TagKey<Block> tag, StateIngredient... excluded) { - return new StateIngredientTagExcluding(tag.location(), List.of(excluded)); - } + public static StateIngredient tagExcluding(TagKey<Block> tag, StateIngredient... excluded) { + return new StateIngredientTagExcluding(tag.location(), List.of(excluded)); + } - public static StateIngredient deserialize(JsonObject object) { - switch (GsonHelper.getAsString(object, "type")) { - case "tag": - return new StateIngredientTag(new ResourceLocation(GsonHelper.getAsString(object, "tag"))); - case "block": - return new StateIngredientBlock( - BuiltInRegistries.BLOCK.get(new ResourceLocation(GsonHelper.getAsString(object, "block")))); - case "state": - return new StateIngredientBlockState(readBlockState(object)); - case "blocks": - List<Block> blocks = new ArrayList<>(); - for (JsonElement element : GsonHelper.getAsJsonArray(object, "blocks")) { - blocks.add(BuiltInRegistries.BLOCK.get(new ResourceLocation(element.getAsString()))); - } - return new StateIngredientBlocks(blocks); - case "tag_excluding": - ResourceLocation tag = new ResourceLocation(GsonHelper.getAsString(object, "tag")); - List<StateIngredient> ingr = new ArrayList<>(); - for (JsonElement element : GsonHelper.getAsJsonArray(object, "exclude")) { - ingr.add(deserialize(GsonHelper.convertToJsonObject(element, "exclude entry"))); - } - return new StateIngredientTagExcluding(tag, ingr); - default: - throw new JsonParseException("Unknown type!"); - } - } + public static StateIngredient deserialize(JsonObject object) { + switch (GsonHelper.getAsString(object, "type")) { + case "tag": + return new StateIngredientTag(new ResourceLocation(GsonHelper.getAsString(object, "tag"))); + case "block": + return new StateIngredientBlock( + BuiltInRegistries.BLOCK.get( + new ResourceLocation(GsonHelper.getAsString(object, "block")))); + case "state": + return new StateIngredientBlockState(readBlockState(object)); + case "blocks": + List<Block> blocks = new ArrayList<>(); + for (JsonElement element : GsonHelper.getAsJsonArray(object, "blocks")) { + blocks.add(BuiltInRegistries.BLOCK.get(new ResourceLocation(element.getAsString()))); + } + return new StateIngredientBlocks(blocks); + case "tag_excluding": + ResourceLocation tag = new ResourceLocation(GsonHelper.getAsString(object, "tag")); + List<StateIngredient> ingr = new ArrayList<>(); + for (JsonElement element : GsonHelper.getAsJsonArray(object, "exclude")) { + ingr.add(deserialize(GsonHelper.convertToJsonObject(element, "exclude entry"))); + } + return new StateIngredientTagExcluding(tag, ingr); + default: + throw new JsonParseException("Unknown type!"); + } + } - /** - * Deserializes a state ingredient, but removes air from its data, - * and returns null if the ingredient only matched air. - */ - @Nullable - public static StateIngredient tryDeserialize(JsonObject object) { - StateIngredient ingr = deserialize(object); - if (ingr instanceof StateIngredientTag sit) { - if (sit.resolve().findAny().isEmpty()) { - return null; - } - return ingr; - } - if (ingr instanceof StateIngredientBlock || ingr instanceof StateIngredientBlockState) { - if (ingr.test(Blocks.AIR.defaultBlockState())) { - return null; - } - } else if (ingr instanceof StateIngredientBlocks sib) { - Collection<Block> blocks = sib.blocks; - List<Block> list = new ArrayList<>(blocks); - if (list.removeIf(b -> b == Blocks.AIR)) { - if (list.size() == 0) { - return null; - } - return of(list); - } - } - return ingr; - } + /** + * Deserializes a state ingredient, but removes air from its data, and returns null if the + * ingredient only matched air. + */ + @Nullable public static StateIngredient tryDeserialize(JsonObject object) { + StateIngredient ingr = deserialize(object); + if (ingr instanceof StateIngredientTag sit) { + if (sit.resolve().findAny().isEmpty()) { + return null; + } + return ingr; + } + if (ingr instanceof StateIngredientBlock || ingr instanceof StateIngredientBlockState) { + if (ingr.test(Blocks.AIR.defaultBlockState())) { + return null; + } + } else if (ingr instanceof StateIngredientBlocks sib) { + Collection<Block> blocks = sib.blocks; + List<Block> list = new ArrayList<>(blocks); + if (list.removeIf(b -> b == Blocks.AIR)) { + if (list.size() == 0) { + return null; + } + return of(list); + } + } + return ingr; + } - public static StateIngredient read(FriendlyByteBuf buffer) { - switch (buffer.readVarInt()) { - case 0: - int count = buffer.readVarInt(); - Set<Block> set = new HashSet<>(); - for (int i = 0; i < count; i++) { - int id = buffer.readVarInt(); - Block block = BuiltInRegistries.BLOCK.byId(id); - set.add(block); - } - return new StateIngredientBlocks(set); - case 1: - return new StateIngredientBlock(BuiltInRegistries.BLOCK.byId(buffer.readVarInt())); - case 2: - return new StateIngredientBlockState(Block.stateById(buffer.readVarInt())); - default: - throw new IllegalArgumentException("Unknown input discriminator!"); - } - } + public static StateIngredient read(FriendlyByteBuf buffer) { + switch (buffer.readVarInt()) { + case 0: + int count = buffer.readVarInt(); + Set<Block> set = new HashSet<>(); + for (int i = 0; i < count; i++) { + int id = buffer.readVarInt(); + Block block = BuiltInRegistries.BLOCK.byId(id); + set.add(block); + } + return new StateIngredientBlocks(set); + case 1: + return new StateIngredientBlock(BuiltInRegistries.BLOCK.byId(buffer.readVarInt())); + case 2: + return new StateIngredientBlockState(Block.stateById(buffer.readVarInt())); + default: + throw new IllegalArgumentException("Unknown input discriminator!"); + } + } - /** - * Writes data about the block state to the provided json object. - */ - public static JsonObject serializeBlockState(BlockState state) { - CompoundTag nbt = NbtUtils.writeBlockState(state); - renameTag(nbt, "Name", "name"); - renameTag(nbt, "Properties", "properties"); - Dynamic<net.minecraft.nbt.Tag> dyn = new Dynamic<>(NbtOps.INSTANCE, nbt); - return dyn.convert(JsonOps.INSTANCE).getValue().getAsJsonObject(); - } + /** Writes data about the block state to the provided json object. */ + public static JsonObject serializeBlockState(BlockState state) { + CompoundTag nbt = NbtUtils.writeBlockState(state); + renameTag(nbt, "Name", "name"); + renameTag(nbt, "Properties", "properties"); + Dynamic<net.minecraft.nbt.Tag> dyn = new Dynamic<>(NbtOps.INSTANCE, nbt); + return dyn.convert(JsonOps.INSTANCE).getValue().getAsJsonObject(); + } - /** - * Reads the block state from the provided json object. - */ - public static BlockState readBlockState(JsonObject object) { - CompoundTag nbt = (CompoundTag) new Dynamic<>(JsonOps.INSTANCE, object).convert(NbtOps.INSTANCE).getValue(); - renameTag(nbt, "name", "Name"); - renameTag(nbt, "properties", "Properties"); - String name = nbt.getString("Name"); - ResourceLocation id = ResourceLocation.tryParse(name); - if (id == null || !BuiltInRegistries.BLOCK.getOptional(id).isPresent()) { - throw new IllegalArgumentException("Invalid or unknown block ID: " + name); - } - return NbtUtils.readBlockState(BuiltInRegistries.BLOCK.asLookup(), nbt); - } + /** Reads the block state from the provided json object. */ + public static BlockState readBlockState(JsonObject object) { + CompoundTag nbt = + (CompoundTag) new Dynamic<>(JsonOps.INSTANCE, object).convert(NbtOps.INSTANCE).getValue(); + renameTag(nbt, "name", "Name"); + renameTag(nbt, "properties", "Properties"); + String name = nbt.getString("Name"); + ResourceLocation id = ResourceLocation.tryParse(name); + if (id == null || !BuiltInRegistries.BLOCK.getOptional(id).isPresent()) { + throw new IllegalArgumentException("Invalid or unknown block ID: " + name); + } + return NbtUtils.readBlockState(BuiltInRegistries.BLOCK.asLookup(), nbt); + } - @Deprecated - @Nonnull - public static List<ItemStack> toStackList(StateIngredient input) { - return input.getDisplayedStacks(); - } + @Deprecated + @Nonnull + public static List<ItemStack> toStackList(StateIngredient input) { + return input.getDisplayedStacks(); + } - private static void renameTag(CompoundTag tag, String from, String to) { - var t = tag.get(from); - if (t != null) { - tag.remove(from); - tag.put(to, t); - } - } -} \ No newline at end of file + private static void renameTag(CompoundTag tag, String from, String to) { + var t = tag.get(from); + if (t != null) { + tag.remove(from); + tag.put(to, t); + } + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientTag.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientTag.java index 5850bd1bf2..1f00ba8a55 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientTag.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientTag.java @@ -2,8 +2,13 @@ import com.google.common.collect.ImmutableSet; import com.google.gson.JsonObject; +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; +import javax.annotation.Nonnull; import net.minecraft.core.Holder; -import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; @@ -13,13 +18,6 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; -import javax.annotation.Nonnull; -import java.util.List; -import java.util.Random; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - public class StateIngredientTag extends StateIngredientBlocks { private final TagKey<Block> tag; @@ -30,7 +28,7 @@ public StateIngredientTag(ResourceLocation tag) { public Stream<Block> resolve() { return StreamSupport.stream(BuiltInRegistries.BLOCK.getTagOrEmpty(tag).spliterator(), false) - .map(Holder::value); + .map(Holder::value); } @Override @@ -58,9 +56,9 @@ public JsonObject serialize() { @Override public List<ItemStack> getDisplayedStacks() { return resolve() - .filter(b -> b.asItem() != Items.AIR) - .map(ItemStack::new) - .collect(Collectors.toList()); + .filter(b -> b.asItem() != Items.AIR) + .map(ItemStack::new) + .collect(Collectors.toList()); } @Nonnull diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientTagExcluding.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientTagExcluding.java index b77dd7ddc3..e966c63188 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientTagExcluding.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/StateIngredientTagExcluding.java @@ -2,6 +2,9 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import java.util.Collection; +import java.util.List; +import java.util.Random; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -9,87 +12,75 @@ import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.NotNull; -import java.util.Collection; -import java.util.List; -import java.util.Random; - public class StateIngredientTagExcluding extends StateIngredientTag { - private final List<StateIngredient> excludes; + private final List<StateIngredient> excludes; - public StateIngredientTagExcluding(ResourceLocation id, Collection<StateIngredient> excludes) { - super(id); - this.excludes = List.copyOf(excludes); - } + public StateIngredientTagExcluding(ResourceLocation id, Collection<StateIngredient> excludes) { + super(id); + this.excludes = List.copyOf(excludes); + } - @Override - public boolean test(BlockState state) { - if (!super.test(state)) { - return false; - } - return isNotExcluded(state); - } + @Override + public boolean test(BlockState state) { + if (!super.test(state)) { + return false; + } + return isNotExcluded(state); + } - @Override - public BlockState pick(Random random) { - List<Block> blocks = getBlocks(); - if (blocks.isEmpty()) { - return null; - } - return blocks.get(random.nextInt(blocks.size())).defaultBlockState(); - } + @Override + public BlockState pick(Random random) { + List<Block> blocks = getBlocks(); + if (blocks.isEmpty()) { + return null; + } + return blocks.get(random.nextInt(blocks.size())).defaultBlockState(); + } - private boolean isNotExcluded(BlockState state) { - for (StateIngredient exclude : excludes) { - if (exclude.test(state)) { - return false; - } - } - return true; - } + private boolean isNotExcluded(BlockState state) { + for (StateIngredient exclude : excludes) { + if (exclude.test(state)) { + return false; + } + } + return true; + } - @Override - public boolean equals(Object o) { - return super.equals(o) && this.excludes.equals(((StateIngredientTagExcluding) o).excludes); - } + @Override + public boolean equals(Object o) { + return super.equals(o) && this.excludes.equals(((StateIngredientTagExcluding) o).excludes); + } - @Override - public int hashCode() { - return super.hashCode(); - } + @Override + public int hashCode() { + return super.hashCode(); + } - @Override - public JsonObject serialize() { - JsonObject object = new JsonObject(); - object.addProperty("type", "tag_excluding"); - object.addProperty("tag", getTagId().toString()); - JsonArray array = new JsonArray(); - for (StateIngredient exclude : excludes) { - array.add(exclude.serialize()); - } - object.add("exclude", array); - return object; - } + @Override + public JsonObject serialize() { + JsonObject object = new JsonObject(); + object.addProperty("type", "tag_excluding"); + object.addProperty("tag", getTagId().toString()); + JsonArray array = new JsonArray(); + for (StateIngredient exclude : excludes) { + array.add(exclude.serialize()); + } + object.add("exclude", array); + return object; + } - @Override - public List<ItemStack> getDisplayedStacks() { - return getBlocks().stream() - .filter(b -> b.asItem() != Items.AIR) - .map(ItemStack::new) - .toList(); - } + @Override + public List<ItemStack> getDisplayedStacks() { + return getBlocks().stream().filter(b -> b.asItem() != Items.AIR).map(ItemStack::new).toList(); + } - @NotNull - @Override - protected List<Block> getBlocks() { - return super.getBlocks().stream() - .filter(b -> isNotExcluded(b.defaultBlockState())) - .toList(); - } + @NotNull @Override + protected List<Block> getBlocks() { + return super.getBlocks().stream().filter(b -> isNotExcluded(b.defaultBlockState())).toList(); + } - @Override - public List<BlockState> getDisplayed() { - return super.getDisplayed().stream() - .filter(this::isNotExcluded) - .toList(); - } -} \ No newline at end of file + @Override + public List<BlockState> getDisplayed() { + return super.getDisplayed().stream().filter(this::isNotExcluded).toList(); + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/BrainsweepeeIngredient.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/BrainsweepeeIngredient.java index 6e777cc2d0..ee6debfe34 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/BrainsweepeeIngredient.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/BrainsweepeeIngredient.java @@ -2,6 +2,8 @@ import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.google.gson.JsonObject; +import java.util.List; +import java.util.Locale; import net.minecraft.ChatFormatting; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; @@ -12,75 +14,71 @@ import net.minecraft.world.level.Level; import org.jetbrains.annotations.Nullable; -import java.util.List; -import java.util.Locale; - // Partially based on: // https://github.com/SlimeKnights/Mantle/blob/1.18.2/src/main/java/slimeknights/mantle/recipe/ingredient/EntityIngredient.java // Licensed under MIT // // .equals must make sense public abstract class BrainsweepeeIngredient { - public abstract boolean test(Entity entity, ServerLevel level); - - public abstract Component getName(); - - public abstract List<Component> getTooltip(boolean advanced); - - public abstract JsonObject serialize(); - - public void wrapWrite(FriendlyByteBuf buf) { - buf.writeEnum(this.ingrType()); - this.write(buf); - } - - public abstract void write(FriendlyByteBuf buf); - - /** - * For the benefit of showing to the client, return an example of the entity. - * <p> - * Can return null in case someone did something stupid with a recipe - */ - @Nullable - public abstract Entity exampleEntity(Level level); - - public abstract Type ingrType(); - - public abstract String getSomeKindOfReasonableIDForEmi(); - - public static BrainsweepeeIngredient read(FriendlyByteBuf buf) { - var type = buf.readEnum(Type.class); - return switch (type) { - case VILLAGER -> VillagerIngredient.read(buf); - case ENTITY_TYPE -> EntityTypeIngredient.read(buf); - case ENTITY_TAG -> EntityTagIngredient.read(buf); - }; - } - - public static BrainsweepeeIngredient deserialize(JsonObject json) { - var typestr = GsonHelper.getAsString(json, "type"); - var type = Type.valueOf(typestr.toUpperCase(Locale.ROOT)); - return switch (type) { - case VILLAGER -> VillagerIngredient.deserialize(json); - case ENTITY_TYPE -> EntityTypeIngredient.deserialize(json); - case ENTITY_TAG -> EntityTagIngredient.deserialize(json); - }; - } - - // TODO: make this a registry? - public enum Type implements StringRepresentable { - VILLAGER, - ENTITY_TYPE, - ENTITY_TAG; - - @Override - public String getSerializedName() { - return this.name().toLowerCase(Locale.ROOT); - } - } - - public static Component getModNameComponent(String namespace) { - String mod = IXplatAbstractions.INSTANCE.getModName(namespace); - return Component.literal(mod).withStyle(ChatFormatting.BLUE, ChatFormatting.ITALIC); - } + public abstract boolean test(Entity entity, ServerLevel level); + + public abstract Component getName(); + + public abstract List<Component> getTooltip(boolean advanced); + + public abstract JsonObject serialize(); + + public void wrapWrite(FriendlyByteBuf buf) { + buf.writeEnum(this.ingrType()); + this.write(buf); + } + + public abstract void write(FriendlyByteBuf buf); + + /** + * For the benefit of showing to the client, return an example of the entity. + * + * <p>Can return null in case someone did something stupid with a recipe + */ + @Nullable public abstract Entity exampleEntity(Level level); + + public abstract Type ingrType(); + + public abstract String getSomeKindOfReasonableIDForEmi(); + + public static BrainsweepeeIngredient read(FriendlyByteBuf buf) { + var type = buf.readEnum(Type.class); + return switch (type) { + case VILLAGER -> VillagerIngredient.read(buf); + case ENTITY_TYPE -> EntityTypeIngredient.read(buf); + case ENTITY_TAG -> EntityTagIngredient.read(buf); + }; + } + + public static BrainsweepeeIngredient deserialize(JsonObject json) { + var typestr = GsonHelper.getAsString(json, "type"); + var type = Type.valueOf(typestr.toUpperCase(Locale.ROOT)); + return switch (type) { + case VILLAGER -> VillagerIngredient.deserialize(json); + case ENTITY_TYPE -> EntityTypeIngredient.deserialize(json); + case ENTITY_TAG -> EntityTagIngredient.deserialize(json); + }; + } + + // TODO: make this a registry? + public enum Type implements StringRepresentable { + VILLAGER, + ENTITY_TYPE, + ENTITY_TAG; + + @Override + public String getSerializedName() { + return this.name().toLowerCase(Locale.ROOT); + } + } + + public static Component getModNameComponent(String namespace) { + String mod = IXplatAbstractions.INSTANCE.getModName(namespace); + return Component.literal(mod).withStyle(ChatFormatting.BLUE, ChatFormatting.ITALIC); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/EntityTagIngredient.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/EntityTagIngredient.java index cb6b0a0912..d69c3b0ff4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/EntityTagIngredient.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/EntityTagIngredient.java @@ -1,9 +1,11 @@ package at.petrak.hexcasting.common.recipe.ingredient.brainsweep; import com.google.gson.JsonObject; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; import net.minecraft.ChatFormatting; import net.minecraft.client.resources.language.I18n; -import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.network.FriendlyByteBuf; @@ -16,122 +18,111 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.Level; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - public class EntityTagIngredient extends BrainsweepeeIngredient { - public final TagKey<EntityType<?>> entityTypeTag; - - public EntityTagIngredient(TagKey<EntityType<?>> tag) { - this.entityTypeTag = tag; - } - - @Override - public boolean test(Entity entity, ServerLevel level) { - return entity.getType().is(this.entityTypeTag); - } - - private static String tagKey(ResourceLocation tagLoc) { - return "tag." - + tagLoc.getNamespace() - + "." - + tagLoc.getPath().replace('/', '.'); - } - - @Override - public Component getName() { - String key = tagKey(this.entityTypeTag.location()); - boolean moddersDidAGoodJob = I18n.exists(key); - return moddersDidAGoodJob - ? Component.translatable(key) - : Component.literal("#" + this.entityTypeTag.location()); - } - - @Override - public List<Component> getTooltip(boolean advanced) { - ResourceLocation loc = this.entityTypeTag.location(); - String key = tagKey(loc); - boolean moddersDidAGoodJob = I18n.exists(key); - - var out = new ArrayList<Component>(); - out.add(moddersDidAGoodJob - ? Component.translatable(key) - : Component.literal("#" + loc)); - if (advanced && moddersDidAGoodJob) { - // Print it anyways - out.add(Component.literal("#" + loc).withStyle(ChatFormatting.DARK_GRAY)); - } - - out.add(BrainsweepeeIngredient.getModNameComponent(loc.getNamespace())); - - return out; - } - - @Override - public Entity exampleEntity(Level level) { - var someEntityTys = BuiltInRegistries.ENTITY_TYPE.getTagOrEmpty(this.entityTypeTag).iterator(); - if (someEntityTys.hasNext()) { - var someTy = someEntityTys.next(); - return someTy.value().create(level); - } else { - return null; - } - } - - @Override - public JsonObject serialize() { - var obj = new JsonObject(); - obj.addProperty("type", Type.ENTITY_TAG.getSerializedName()); - - obj.addProperty("tag", this.entityTypeTag.location().toString()); - - return obj; - } - - @Override - public void write(FriendlyByteBuf buf) { - buf.writeResourceLocation(this.entityTypeTag.location()); - } - - public static EntityTagIngredient deserialize(JsonObject obj) { - var tagLoc = ResourceLocation.tryParse(GsonHelper.getAsString(obj, "tag")); - if (tagLoc == null) { - throw new IllegalArgumentException("unknown tag " + obj); - } - var type = TagKey.create(Registries.ENTITY_TYPE, tagLoc); - return new EntityTagIngredient(type); - } - - public static EntityTagIngredient read(FriendlyByteBuf buf) { - var typeLoc = buf.readResourceLocation(); - var type = TagKey.create(Registries.ENTITY_TYPE, typeLoc); - return new EntityTagIngredient(type); - } - - @Override - public Type ingrType() { - return Type.ENTITY_TAG; - } - - @Override - public String getSomeKindOfReasonableIDForEmi() { - var resloc = this.entityTypeTag.location(); - return resloc.getNamespace() - + "//" - + resloc.getPath(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - EntityTagIngredient that = (EntityTagIngredient) o; - return Objects.equals(entityTypeTag, that.entityTypeTag); - } - - @Override - public int hashCode() { - return Objects.hashCode(this.entityTypeTag); - } + public final TagKey<EntityType<?>> entityTypeTag; + + public EntityTagIngredient(TagKey<EntityType<?>> tag) { + this.entityTypeTag = tag; + } + + @Override + public boolean test(Entity entity, ServerLevel level) { + return entity.getType().is(this.entityTypeTag); + } + + private static String tagKey(ResourceLocation tagLoc) { + return "tag." + tagLoc.getNamespace() + "." + tagLoc.getPath().replace('/', '.'); + } + + @Override + public Component getName() { + String key = tagKey(this.entityTypeTag.location()); + boolean moddersDidAGoodJob = I18n.exists(key); + return moddersDidAGoodJob + ? Component.translatable(key) + : Component.literal("#" + this.entityTypeTag.location()); + } + + @Override + public List<Component> getTooltip(boolean advanced) { + ResourceLocation loc = this.entityTypeTag.location(); + String key = tagKey(loc); + boolean moddersDidAGoodJob = I18n.exists(key); + + var out = new ArrayList<Component>(); + out.add(moddersDidAGoodJob ? Component.translatable(key) : Component.literal("#" + loc)); + if (advanced && moddersDidAGoodJob) { + // Print it anyways + out.add(Component.literal("#" + loc).withStyle(ChatFormatting.DARK_GRAY)); + } + + out.add(BrainsweepeeIngredient.getModNameComponent(loc.getNamespace())); + + return out; + } + + @Override + public Entity exampleEntity(Level level) { + var someEntityTys = BuiltInRegistries.ENTITY_TYPE.getTagOrEmpty(this.entityTypeTag).iterator(); + if (someEntityTys.hasNext()) { + var someTy = someEntityTys.next(); + return someTy.value().create(level); + } else { + return null; + } + } + + @Override + public JsonObject serialize() { + var obj = new JsonObject(); + obj.addProperty("type", Type.ENTITY_TAG.getSerializedName()); + + obj.addProperty("tag", this.entityTypeTag.location().toString()); + + return obj; + } + + @Override + public void write(FriendlyByteBuf buf) { + buf.writeResourceLocation(this.entityTypeTag.location()); + } + + public static EntityTagIngredient deserialize(JsonObject obj) { + var tagLoc = ResourceLocation.tryParse(GsonHelper.getAsString(obj, "tag")); + if (tagLoc == null) { + throw new IllegalArgumentException("unknown tag " + obj); + } + var type = TagKey.create(Registries.ENTITY_TYPE, tagLoc); + return new EntityTagIngredient(type); + } + + public static EntityTagIngredient read(FriendlyByteBuf buf) { + var typeLoc = buf.readResourceLocation(); + var type = TagKey.create(Registries.ENTITY_TYPE, typeLoc); + return new EntityTagIngredient(type); + } + + @Override + public Type ingrType() { + return Type.ENTITY_TAG; + } + + @Override + public String getSomeKindOfReasonableIDForEmi() { + var resloc = this.entityTypeTag.location(); + return resloc.getNamespace() + "//" + resloc.getPath(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + EntityTagIngredient that = (EntityTagIngredient) o; + return Objects.equals(entityTypeTag, that.entityTypeTag); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.entityTypeTag); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/EntityTypeIngredient.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/EntityTypeIngredient.java index f510c17d2e..5eb0f9f766 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/EntityTypeIngredient.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/EntityTypeIngredient.java @@ -1,7 +1,8 @@ package at.petrak.hexcasting.common.recipe.ingredient.brainsweep; import com.google.gson.JsonObject; -import net.minecraft.core.Registry; +import java.util.List; +import java.util.Objects; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; @@ -12,90 +13,85 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.Level; -import java.util.List; -import java.util.Objects; - public class EntityTypeIngredient extends BrainsweepeeIngredient { - public final EntityType<?> entityType; - - public EntityTypeIngredient(EntityType<?> entityType) { - this.entityType = entityType; - } - - @Override - public boolean test(Entity entity, ServerLevel level) { - // entity types are singletons - return entity.getType() == this.entityType; - } - - @Override - public Component getName() { - return this.entityType.getDescription(); - } - - @Override - public List<Component> getTooltip(boolean advanced) { - return List.of( - this.entityType.getDescription(), - BrainsweepeeIngredient.getModNameComponent(BuiltInRegistries.ENTITY_TYPE.getKey(this.entityType).getNamespace()) - ); - } - - @Override - public Entity exampleEntity(Level level) { - return this.entityType.create(level); - } - - @Override - public JsonObject serialize() { - var obj = new JsonObject(); - obj.addProperty("type", Type.ENTITY_TYPE.getSerializedName()); - obj.addProperty("entityType", BuiltInRegistries.ENTITY_TYPE.getKey(this.entityType).toString()); - - return obj; - } - - @Override - public void write(FriendlyByteBuf buf) { - buf.writeVarInt(BuiltInRegistries.ENTITY_TYPE.getId(this.entityType)); - } - - public static EntityTypeIngredient deserialize(JsonObject obj) { - var typeLoc = ResourceLocation.tryParse(GsonHelper.getAsString(obj, "entityType")); - if (typeLoc == null || !BuiltInRegistries.ENTITY_TYPE.containsKey(typeLoc)) { - throw new IllegalArgumentException("unknown entity type " + typeLoc); - } - return new EntityTypeIngredient(BuiltInRegistries.ENTITY_TYPE.get(typeLoc)); - } - - public static EntityTypeIngredient read(FriendlyByteBuf buf) { - var tyId = buf.readVarInt(); - return new EntityTypeIngredient(BuiltInRegistries.ENTITY_TYPE.byId(tyId)); - } - - @Override - public Type ingrType() { - return Type.ENTITY_TYPE; - } - - @Override - public String getSomeKindOfReasonableIDForEmi() { - var resloc = BuiltInRegistries.ENTITY_TYPE.getKey(this.entityType); - return resloc.getNamespace() - + "//" - + resloc.getPath(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - EntityTypeIngredient that = (EntityTypeIngredient) o; - return Objects.equals(entityType, that.entityType); - } - - @Override - public int hashCode() { - return Objects.hash(entityType); - } + public final EntityType<?> entityType; + + public EntityTypeIngredient(EntityType<?> entityType) { + this.entityType = entityType; + } + + @Override + public boolean test(Entity entity, ServerLevel level) { + // entity types are singletons + return entity.getType() == this.entityType; + } + + @Override + public Component getName() { + return this.entityType.getDescription(); + } + + @Override + public List<Component> getTooltip(boolean advanced) { + return List.of( + this.entityType.getDescription(), + BrainsweepeeIngredient.getModNameComponent( + BuiltInRegistries.ENTITY_TYPE.getKey(this.entityType).getNamespace())); + } + + @Override + public Entity exampleEntity(Level level) { + return this.entityType.create(level); + } + + @Override + public JsonObject serialize() { + var obj = new JsonObject(); + obj.addProperty("type", Type.ENTITY_TYPE.getSerializedName()); + obj.addProperty("entityType", BuiltInRegistries.ENTITY_TYPE.getKey(this.entityType).toString()); + + return obj; + } + + @Override + public void write(FriendlyByteBuf buf) { + buf.writeVarInt(BuiltInRegistries.ENTITY_TYPE.getId(this.entityType)); + } + + public static EntityTypeIngredient deserialize(JsonObject obj) { + var typeLoc = ResourceLocation.tryParse(GsonHelper.getAsString(obj, "entityType")); + if (typeLoc == null || !BuiltInRegistries.ENTITY_TYPE.containsKey(typeLoc)) { + throw new IllegalArgumentException("unknown entity type " + typeLoc); + } + return new EntityTypeIngredient(BuiltInRegistries.ENTITY_TYPE.get(typeLoc)); + } + + public static EntityTypeIngredient read(FriendlyByteBuf buf) { + var tyId = buf.readVarInt(); + return new EntityTypeIngredient(BuiltInRegistries.ENTITY_TYPE.byId(tyId)); + } + + @Override + public Type ingrType() { + return Type.ENTITY_TYPE; + } + + @Override + public String getSomeKindOfReasonableIDForEmi() { + var resloc = BuiltInRegistries.ENTITY_TYPE.getKey(this.entityType); + return resloc.getNamespace() + "//" + resloc.getPath(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + EntityTypeIngredient that = (EntityTypeIngredient) o; + return Objects.equals(entityType, that.entityType); + } + + @Override + public int hashCode() { + return Objects.hash(entityType); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/VillagerIngredient.java b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/VillagerIngredient.java index d3cf2e63ef..db49fd5996 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/VillagerIngredient.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/brainsweep/VillagerIngredient.java @@ -1,8 +1,10 @@ package at.petrak.hexcasting.common.recipe.ingredient.brainsweep; import com.google.gson.JsonObject; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; import net.minecraft.ChatFormatting; -import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; @@ -19,238 +21,232 @@ import net.minecraft.world.level.Level; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -/** - * Special case for villagers so we can have biome/profession/level reqs - */ +/** Special case for villagers so we can have biome/profession/level reqs */ public class VillagerIngredient extends BrainsweepeeIngredient { - public final @Nullable VillagerProfession profession; - public final @Nullable VillagerType biome; - public final int minLevel; - - public VillagerIngredient( - @Nullable VillagerProfession profession, - @Nullable VillagerType biome, - int minLevel - ) { - this.profession = profession; - this.biome = biome; - this.minLevel = minLevel; - } - - @Override - public boolean test(Entity entity, ServerLevel level) { - if (!(entity instanceof Villager villager)) return false; - - var data = villager.getVillagerData(); - - return (this.profession == null || this.profession.equals(data.getProfession())) - && (this.biome == null || this.biome.equals(data.getType())) - && this.minLevel <= data.getLevel(); - } - - @Override - public Entity exampleEntity(Level level) { - var biome = Objects.requireNonNullElse(this.biome, VillagerType.PLAINS); - var profession = Objects.requireNonNullElse(this.profession, VillagerProfession.TOOLSMITH); - var tradeLevel = Math.min(this.minLevel, 1); - - var out = new Villager(EntityType.VILLAGER, level); - - var data = out.getVillagerData(); - data - .setProfession(profession) - .setType(biome) - .setLevel(tradeLevel); - out.setVillagerData(data); - - // just random bullshit go to try and get it to update for god's sake - var tag = new CompoundTag(); - out.save(tag); - - return out; - } - - @Override - public List<Component> getTooltip(boolean advanced) { - List<Component> tooltip = new ArrayList<>(); - tooltip.add(this.getName()); - - if (advanced) { - if (minLevel >= 5) { - tooltip.add(Component.translatable("hexcasting.tooltip.brainsweep.level", 5) - .withStyle(ChatFormatting.DARK_GRAY)); - } else if (minLevel > 1) { - tooltip.add(Component.translatable("hexcasting.tooltip.brainsweep.min_level", minLevel) - .withStyle(ChatFormatting.DARK_GRAY)); - } - - if (this.biome != null) { - tooltip.add(Component.literal(this.biome.toString()).withStyle(ChatFormatting.DARK_GRAY)); - } - - if (this.profession != null) { - tooltip.add(Component.literal(this.profession.toString()).withStyle(ChatFormatting.DARK_GRAY)); - } - } - - tooltip.add(BrainsweepeeIngredient.getModNameComponent( - this.profession == null - ? "minecraft" - : BuiltInRegistries.VILLAGER_PROFESSION.getKey(this.profession).getNamespace())); - - return tooltip; - } - - @Override - public Component getName() { - MutableComponent component = Component.literal(""); - - boolean addedAny = false; - - if (minLevel >= 5) { - component.append(Component.translatable("merchant.level.5")); - addedAny = true; - } else if (minLevel > 1) { - component.append(Component.translatable("merchant.level." + minLevel)); - addedAny = true; - } else if (profession != null) { - component.append(Component.translatable("merchant.level.1")); - addedAny = true; - } - - if (biome != null) { - if (addedAny) { - component.append(" "); - } - var biomeLoc = BuiltInRegistries.VILLAGER_TYPE.getKey(this.biome); - component.append(Component.translatable("biome." + biomeLoc.getNamespace() + "." + biomeLoc.getPath())); - addedAny = true; - } - - if (profession != null) { - // We've for sure added something - component.append(" "); - var professionLoc = BuiltInRegistries.VILLAGER_PROFESSION.getKey(this.profession); - // TODO: what's the convention used for modded villager types? - // Villager::getTypeName implies that it there's no namespace information. - // i hope there is some convention - component.append(Component.translatable("entity.minecraft.villager." + professionLoc.getPath())); - } else { - if (addedAny) { - component.append(" "); - } - component.append(EntityType.VILLAGER.getDescription()); - } - - return component; - } - - @Override - public JsonObject serialize() { - var obj = new JsonObject(); - obj.addProperty("type", Type.VILLAGER.getSerializedName()); - - if (this.profession != null) { - obj.addProperty("profession", this.profession.toString()); - } - if (this.biome != null) { - obj.addProperty("biome", this.biome.toString()); - } - obj.addProperty("minLevel", this.minLevel); - return obj; - } - - @Override - public void write(FriendlyByteBuf buf) { - if (this.profession != null) { - buf.writeVarInt(1); - buf.writeVarInt(BuiltInRegistries.VILLAGER_PROFESSION.getId(this.profession)); - } else { - buf.writeVarInt(0); - } - if (this.biome != null) { - buf.writeVarInt(1); - buf.writeVarInt(BuiltInRegistries.VILLAGER_TYPE.getId(this.biome)); - } else { - buf.writeVarInt(0); - } - buf.writeInt(this.minLevel); - } - - public static VillagerIngredient deserialize(JsonObject json) { - VillagerProfession profession = null; - if (json.has("profession") && !json.get("profession").isJsonNull()) { - profession = BuiltInRegistries.VILLAGER_PROFESSION.get(new ResourceLocation(GsonHelper.getAsString(json, - "profession"))); - } - VillagerType biome = null; - if (json.has("biome") && !json.get("biome").isJsonNull()) { - biome = BuiltInRegistries.VILLAGER_TYPE.get(new ResourceLocation(GsonHelper.getAsString(json, "biome"))); - } - int minLevel = GsonHelper.getAsInt(json, "minLevel"); - return new VillagerIngredient(profession, biome, minLevel); - } - - public static VillagerIngredient read(FriendlyByteBuf buf) { - VillagerProfession profession = null; - var hasProfession = buf.readVarInt(); - if (hasProfession != 0) { - profession = BuiltInRegistries.VILLAGER_PROFESSION.byId(buf.readVarInt()); - } - VillagerType biome = null; - var hasBiome = buf.readVarInt(); - if (hasBiome != 0) { - biome = BuiltInRegistries.VILLAGER_TYPE.byId(buf.readVarInt()); - } - int minLevel = buf.readInt(); - return new VillagerIngredient(profession, biome, minLevel); - } - - @Override - public Type ingrType() { - return Type.VILLAGER; - } - - @Override - public String getSomeKindOfReasonableIDForEmi() { - var bob = new StringBuilder(); - if (this.profession != null) { - var profLoc = BuiltInRegistries.VILLAGER_PROFESSION.getKey(this.profession); - bob.append(profLoc.getNamespace()) - .append("//") - .append(profLoc.getPath()); - } else { - bob.append("null"); - } - bob.append("_"); - if (this.biome != null) { - var biomeLoc = BuiltInRegistries.VILLAGER_TYPE.getKey(this.biome); - bob.append(biomeLoc.getNamespace()) - .append("//") - .append(biomeLoc.getPath()); - } else { - bob.append("null"); - } - - bob.append(this.minLevel); - return bob.toString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - VillagerIngredient that = (VillagerIngredient) o; - return minLevel == that.minLevel && Objects.equals(profession, that.profession) && Objects.equals(biome, - that.biome); - } - - @Override - public int hashCode() { - return Objects.hash(profession, biome, minLevel); - } + public final @Nullable VillagerProfession profession; + public final @Nullable VillagerType biome; + public final int minLevel; + + public VillagerIngredient( + @Nullable VillagerProfession profession, @Nullable VillagerType biome, int minLevel) { + this.profession = profession; + this.biome = biome; + this.minLevel = minLevel; + } + + @Override + public boolean test(Entity entity, ServerLevel level) { + if (!(entity instanceof Villager villager)) return false; + + var data = villager.getVillagerData(); + + return (this.profession == null || this.profession.equals(data.getProfession())) + && (this.biome == null || this.biome.equals(data.getType())) + && this.minLevel <= data.getLevel(); + } + + @Override + public Entity exampleEntity(Level level) { + var biome = Objects.requireNonNullElse(this.biome, VillagerType.PLAINS); + var profession = Objects.requireNonNullElse(this.profession, VillagerProfession.TOOLSMITH); + var tradeLevel = Math.min(this.minLevel, 1); + + var out = new Villager(EntityType.VILLAGER, level); + + var data = out.getVillagerData(); + data.setProfession(profession).setType(biome).setLevel(tradeLevel); + out.setVillagerData(data); + + // just random bullshit go to try and get it to update for god's sake + var tag = new CompoundTag(); + out.save(tag); + + return out; + } + + @Override + public List<Component> getTooltip(boolean advanced) { + List<Component> tooltip = new ArrayList<>(); + tooltip.add(this.getName()); + + if (advanced) { + if (minLevel >= 5) { + tooltip.add( + Component.translatable("hexcasting.tooltip.brainsweep.level", 5) + .withStyle(ChatFormatting.DARK_GRAY)); + } else if (minLevel > 1) { + tooltip.add( + Component.translatable("hexcasting.tooltip.brainsweep.min_level", minLevel) + .withStyle(ChatFormatting.DARK_GRAY)); + } + + if (this.biome != null) { + tooltip.add(Component.literal(this.biome.toString()).withStyle(ChatFormatting.DARK_GRAY)); + } + + if (this.profession != null) { + tooltip.add( + Component.literal(this.profession.toString()).withStyle(ChatFormatting.DARK_GRAY)); + } + } + + tooltip.add( + BrainsweepeeIngredient.getModNameComponent( + this.profession == null + ? "minecraft" + : BuiltInRegistries.VILLAGER_PROFESSION.getKey(this.profession).getNamespace())); + + return tooltip; + } + + @Override + public Component getName() { + MutableComponent component = Component.literal(""); + + boolean addedAny = false; + + if (minLevel >= 5) { + component.append(Component.translatable("merchant.level.5")); + addedAny = true; + } else if (minLevel > 1) { + component.append(Component.translatable("merchant.level." + minLevel)); + addedAny = true; + } else if (profession != null) { + component.append(Component.translatable("merchant.level.1")); + addedAny = true; + } + + if (biome != null) { + if (addedAny) { + component.append(" "); + } + var biomeLoc = BuiltInRegistries.VILLAGER_TYPE.getKey(this.biome); + component.append( + Component.translatable("biome." + biomeLoc.getNamespace() + "." + biomeLoc.getPath())); + addedAny = true; + } + + if (profession != null) { + // We've for sure added something + component.append(" "); + var professionLoc = BuiltInRegistries.VILLAGER_PROFESSION.getKey(this.profession); + // TODO: what's the convention used for modded villager types? + // Villager::getTypeName implies that it there's no namespace information. + // i hope there is some convention + component.append( + Component.translatable("entity.minecraft.villager." + professionLoc.getPath())); + } else { + if (addedAny) { + component.append(" "); + } + component.append(EntityType.VILLAGER.getDescription()); + } + + return component; + } + + @Override + public JsonObject serialize() { + var obj = new JsonObject(); + obj.addProperty("type", Type.VILLAGER.getSerializedName()); + + if (this.profession != null) { + obj.addProperty("profession", this.profession.toString()); + } + if (this.biome != null) { + obj.addProperty("biome", this.biome.toString()); + } + obj.addProperty("minLevel", this.minLevel); + return obj; + } + + @Override + public void write(FriendlyByteBuf buf) { + if (this.profession != null) { + buf.writeVarInt(1); + buf.writeVarInt(BuiltInRegistries.VILLAGER_PROFESSION.getId(this.profession)); + } else { + buf.writeVarInt(0); + } + if (this.biome != null) { + buf.writeVarInt(1); + buf.writeVarInt(BuiltInRegistries.VILLAGER_TYPE.getId(this.biome)); + } else { + buf.writeVarInt(0); + } + buf.writeInt(this.minLevel); + } + + public static VillagerIngredient deserialize(JsonObject json) { + VillagerProfession profession = null; + if (json.has("profession") && !json.get("profession").isJsonNull()) { + profession = + BuiltInRegistries.VILLAGER_PROFESSION.get( + new ResourceLocation(GsonHelper.getAsString(json, "profession"))); + } + VillagerType biome = null; + if (json.has("biome") && !json.get("biome").isJsonNull()) { + biome = + BuiltInRegistries.VILLAGER_TYPE.get( + new ResourceLocation(GsonHelper.getAsString(json, "biome"))); + } + int minLevel = GsonHelper.getAsInt(json, "minLevel"); + return new VillagerIngredient(profession, biome, minLevel); + } + + public static VillagerIngredient read(FriendlyByteBuf buf) { + VillagerProfession profession = null; + var hasProfession = buf.readVarInt(); + if (hasProfession != 0) { + profession = BuiltInRegistries.VILLAGER_PROFESSION.byId(buf.readVarInt()); + } + VillagerType biome = null; + var hasBiome = buf.readVarInt(); + if (hasBiome != 0) { + biome = BuiltInRegistries.VILLAGER_TYPE.byId(buf.readVarInt()); + } + int minLevel = buf.readInt(); + return new VillagerIngredient(profession, biome, minLevel); + } + + @Override + public Type ingrType() { + return Type.VILLAGER; + } + + @Override + public String getSomeKindOfReasonableIDForEmi() { + var bob = new StringBuilder(); + if (this.profession != null) { + var profLoc = BuiltInRegistries.VILLAGER_PROFESSION.getKey(this.profession); + bob.append(profLoc.getNamespace()).append("//").append(profLoc.getPath()); + } else { + bob.append("null"); + } + bob.append("_"); + if (this.biome != null) { + var biomeLoc = BuiltInRegistries.VILLAGER_TYPE.getKey(this.biome); + bob.append(biomeLoc.getNamespace()).append("//").append(biomeLoc.getPath()); + } else { + bob.append("null"); + } + + bob.append(this.minLevel); + return bob.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + VillagerIngredient that = (VillagerIngredient) o; + return minLevel == that.minLevel + && Objects.equals(profession, that.profession) + && Objects.equals(biome, that.biome); + } + + @Override + public int hashCode() { + return Objects.hash(profession, biome, minLevel); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/HexAdvancements.java b/Common/src/main/java/at/petrak/hexcasting/datagen/HexAdvancements.java index d095b06044..2b15bfa039 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/HexAdvancements.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/HexAdvancements.java @@ -11,6 +11,7 @@ import at.petrak.hexcasting.common.lib.HexBlocks; import at.petrak.hexcasting.common.lib.HexItems; import at.petrak.paucal.api.datagen.PaucalAdvancementSubProvider; +import java.util.function.Consumer; import net.minecraft.advancements.Advancement; import net.minecraft.advancements.DisplayInfo; import net.minecraft.advancements.FrameType; @@ -21,111 +22,158 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import java.util.function.Consumer; - public class HexAdvancements extends PaucalAdvancementSubProvider { - public static final OvercastTrigger.Instance ENLIGHTEN = - new OvercastTrigger.Instance(ContextAwarePredicate.ANY, - MinMaxBounds.Ints.ANY, - // add a little bit of slop here. use 80% or more health ... - MinMaxBounds.Doubles.atLeast(0.8), - // and be left with under 1 healthpoint (half a heart) - // TODO this means if 80% of your health is less than half a heart, so if you have 2.5 hearts or - // less, you can't become enlightened. - MinMaxBounds.Doubles.between(Double.MIN_NORMAL, 1.0)); + public static final OvercastTrigger.Instance ENLIGHTEN = + new OvercastTrigger.Instance( + ContextAwarePredicate.ANY, + MinMaxBounds.Ints.ANY, + // add a little bit of slop here. use 80% or more health ... + MinMaxBounds.Doubles.atLeast(0.8), + // and be left with under 1 healthpoint (half a heart) + // TODO this means if 80% of your health is less than half a heart, so if you have 2.5 + // hearts or + // less, you can't become enlightened. + MinMaxBounds.Doubles.between(Double.MIN_NORMAL, 1.0)); - public HexAdvancements() { - super(HexAPI.MOD_ID); - } + public HexAdvancements() { + super(HexAPI.MOD_ID); + } - @Override - public void generate(HolderLookup.Provider provider, Consumer<Advancement> consumer) { - var root = Advancement.Builder.advancement() - // what an ergonomic design decision - // i am so happy that data generators are the future - .display(new DisplayInfo(new ItemStack(Items.BUDDING_AMETHYST), - Component.translatable("advancement.hexcasting:root"), - Component.translatable("advancement.hexcasting:root.desc"), - new ResourceLocation("minecraft", "textures/block/calcite.png"), - FrameType.TASK, true, true, true)) - // the only thing making this vaguely tolerable is the knowledge the json files are worse somehow - .addCriterion("has_charged_amethyst", InventoryChangeTrigger.TriggerInstance.hasItems( - ItemPredicate.Builder.item().of(HexTags.Items.GRANTS_ROOT_ADVANCEMENT).build())) - .save(consumer, prefix("root")); // how the hell does one even read this + @Override + public void generate(HolderLookup.Provider provider, Consumer<Advancement> consumer) { + var root = + Advancement.Builder.advancement() + // what an ergonomic design decision + // i am so happy that data generators are the future + .display( + new DisplayInfo( + new ItemStack(Items.BUDDING_AMETHYST), + Component.translatable("advancement.hexcasting:root"), + Component.translatable("advancement.hexcasting:root.desc"), + new ResourceLocation("minecraft", "textures/block/calcite.png"), + FrameType.TASK, + true, + true, + true)) + // the only thing making this vaguely tolerable is the knowledge the json files are + // worse somehow + .addCriterion( + "has_charged_amethyst", + InventoryChangeTrigger.TriggerInstance.hasItems( + ItemPredicate.Builder.item().of(HexTags.Items.GRANTS_ROOT_ADVANCEMENT).build())) + .save(consumer, prefix("root")); // how the hell does one even read this - //Creative Debug Unlocker - Advancement.Builder.advancement() - .display(new DisplayInfo(new ItemStack(HexItems.CREATIVE_UNLOCKER), - Component.translatable("advancement.hexcasting:creative_unlocker"), - Component.translatable("advancement.hexcasting:creative_unlocker.desc"), - new ResourceLocation("minecraft", "textures/block/calcite.png"), - FrameType.TASK, true, false, true)) - .parent(root) - .addCriterion("has_creative_unlocker", InventoryChangeTrigger.TriggerInstance.hasItems( - ItemPredicate.Builder.item().of(HexItems.CREATIVE_UNLOCKER).build())) - .save(consumer, prefix("creative_unlocker")); + // Creative Debug Unlocker + Advancement.Builder.advancement() + .display( + new DisplayInfo( + new ItemStack(HexItems.CREATIVE_UNLOCKER), + Component.translatable("advancement.hexcasting:creative_unlocker"), + Component.translatable("advancement.hexcasting:creative_unlocker.desc"), + new ResourceLocation("minecraft", "textures/block/calcite.png"), + FrameType.TASK, + true, + false, + true)) + .parent(root) + .addCriterion( + "has_creative_unlocker", + InventoryChangeTrigger.TriggerInstance.hasItems( + ItemPredicate.Builder.item().of(HexItems.CREATIVE_UNLOCKER).build())) + .save(consumer, prefix("creative_unlocker")); - // weird names so we have alphabetical parity - Advancement.Builder.advancement() - .display(simpleDisplay(Items.GLISTERING_MELON_SLICE, "wasteful_cast", FrameType.TASK)) - .parent(root) - .addCriterion("waste_amt", new SpendMediaTrigger.Instance(ContextAwarePredicate.ANY, - MinMaxLongs.ANY, - MinMaxLongs.atLeast(89 * MediaConstants.DUST_UNIT / 10))) - .save(consumer, prefix("aaa_wasteful_cast")); - Advancement.Builder.advancement() - .display(simpleDisplay(HexItems.CHARGED_AMETHYST, "big_cast", FrameType.TASK)) - .parent(root) - .addCriterion("cast_amt", new SpendMediaTrigger.Instance(ContextAwarePredicate.ANY, - MinMaxLongs.atLeast(64 * MediaConstants.CRYSTAL_UNIT), - MinMaxLongs.ANY)) - .save(consumer, prefix("aab_big_cast")); + // weird names so we have alphabetical parity + Advancement.Builder.advancement() + .display(simpleDisplay(Items.GLISTERING_MELON_SLICE, "wasteful_cast", FrameType.TASK)) + .parent(root) + .addCriterion( + "waste_amt", + new SpendMediaTrigger.Instance( + ContextAwarePredicate.ANY, + MinMaxLongs.ANY, + MinMaxLongs.atLeast(89 * MediaConstants.DUST_UNIT / 10))) + .save(consumer, prefix("aaa_wasteful_cast")); + Advancement.Builder.advancement() + .display(simpleDisplay(HexItems.CHARGED_AMETHYST, "big_cast", FrameType.TASK)) + .parent(root) + .addCriterion( + "cast_amt", + new SpendMediaTrigger.Instance( + ContextAwarePredicate.ANY, + MinMaxLongs.atLeast(64 * MediaConstants.CRYSTAL_UNIT), + MinMaxLongs.ANY)) + .save(consumer, prefix("aab_big_cast")); - var impotence = Advancement.Builder.advancement() - .display(simpleDisplay(Items.BLAZE_POWDER, "y_u_no_cast_angy", FrameType.TASK)) - .parent(root) - .addCriterion("did_the_thing", - new FailToCastGreatSpellTrigger.Instance(ContextAwarePredicate.ANY)) - .save(consumer, prefix("y_u_no_cast_angy")); + var impotence = + Advancement.Builder.advancement() + .display(simpleDisplay(Items.BLAZE_POWDER, "y_u_no_cast_angy", FrameType.TASK)) + .parent(root) + .addCriterion( + "did_the_thing", + new FailToCastGreatSpellTrigger.Instance(ContextAwarePredicate.ANY)) + .save(consumer, prefix("y_u_no_cast_angy")); - var opened_eyes = Advancement.Builder.advancement() - .display(simpleDisplay(Items.ENDER_EYE, "opened_eyes", FrameType.TASK)) - .parent(impotence) - .addCriterion("health_used", - new OvercastTrigger.Instance(ContextAwarePredicate.ANY, - MinMaxBounds.Ints.ANY, - MinMaxBounds.Doubles.ANY, - // you can't just kill yourself - MinMaxBounds.Doubles.atLeast(0.0))) - .save(consumer, prefix("opened_eyes")); + var opened_eyes = + Advancement.Builder.advancement() + .display(simpleDisplay(Items.ENDER_EYE, "opened_eyes", FrameType.TASK)) + .parent(impotence) + .addCriterion( + "health_used", + new OvercastTrigger.Instance( + ContextAwarePredicate.ANY, + MinMaxBounds.Ints.ANY, + MinMaxBounds.Doubles.ANY, + // you can't just kill yourself + MinMaxBounds.Doubles.atLeast(0.0))) + .save(consumer, prefix("opened_eyes")); - Advancement.Builder.advancement() - .display(new DisplayInfo(new ItemStack(Items.MUSIC_DISC_11), - Component.translatable("advancement.hexcasting:enlightenment"), - Component.translatable("advancement.hexcasting:enlightenment.desc"), - null, - FrameType.CHALLENGE, true, true, true)) - .parent(opened_eyes) - .addCriterion("health_used", ENLIGHTEN) - .save(consumer, prefix("enlightenment")); + Advancement.Builder.advancement() + .display( + new DisplayInfo( + new ItemStack(Items.MUSIC_DISC_11), + Component.translatable("advancement.hexcasting:enlightenment"), + Component.translatable("advancement.hexcasting:enlightenment.desc"), + null, + FrameType.CHALLENGE, + true, + true, + true)) + .parent(opened_eyes) + .addCriterion("health_used", ENLIGHTEN) + .save(consumer, prefix("enlightenment")); - var loreRoot = Advancement.Builder.advancement() - .display(simpleDisplayWithBackground(HexBlocks.AKASHIC_LIGATURE, "lore", FrameType.GOAL, - modLoc("textures/block/slate.png"))) - .addCriterion("used_item", new ConsumeItemTrigger.TriggerInstance(ContextAwarePredicate.ANY, - ItemPredicate.Builder.item().of(HexItems.LORE_FRAGMENT).build())) - .save(consumer, prefix("lore")); + var loreRoot = + Advancement.Builder.advancement() + .display( + simpleDisplayWithBackground( + HexBlocks.AKASHIC_LIGATURE, + "lore", + FrameType.GOAL, + modLoc("textures/block/slate.png"))) + .addCriterion( + "used_item", + new ConsumeItemTrigger.TriggerInstance( + ContextAwarePredicate.ANY, + ItemPredicate.Builder.item().of(HexItems.LORE_FRAGMENT).build())) + .save(consumer, prefix("lore")); - for (var advId : ItemLoreFragment.NAMES) { - Advancement.Builder.advancement() - .display(new DisplayInfo(new ItemStack(HexItems.LORE_FRAGMENT), - Component.translatable("advancement." + advId), Component.empty(), - null, FrameType.TASK, true, true, true)) - .parent(loreRoot) - .addCriterion(ItemLoreFragment.CRITEREON_KEY, new ImpossibleTrigger.TriggerInstance()) - .save(consumer, advId.toString()); - } + for (var advId : ItemLoreFragment.NAMES) { + Advancement.Builder.advancement() + .display( + new DisplayInfo( + new ItemStack(HexItems.LORE_FRAGMENT), + Component.translatable("advancement." + advId), + Component.empty(), + null, + FrameType.TASK, + true, + true, + true)) + .parent(loreRoot) + .addCriterion(ItemLoreFragment.CRITEREON_KEY, new ImpossibleTrigger.TriggerInstance()) + .save(consumer, advId.toString()); + } -// super.registerAdvancements(consumer, fileHelper); - } + // super.registerAdvancements(consumer, fileHelper); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/HexLootTables.java b/Common/src/main/java/at/petrak/hexcasting/datagen/HexLootTables.java index 386320703c..a1593b6c69 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/HexLootTables.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/HexLootTables.java @@ -7,11 +7,11 @@ import at.petrak.hexcasting.common.loot.HexLootHandler; import at.petrak.hexcasting.xplat.IXplatAbstractions; import at.petrak.paucal.api.datagen.PaucalLootTableSubProvider; +import java.util.Map; import net.minecraft.advancements.critereon.EnchantmentPredicate; import net.minecraft.advancements.critereon.ItemPredicate; import net.minecraft.advancements.critereon.MinMaxBounds; import net.minecraft.advancements.critereon.StatePropertiesPredicate; -import net.minecraft.data.DataProvider; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.ItemTags; import net.minecraft.world.item.enchantment.Enchantments; @@ -33,122 +33,186 @@ import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator; -import java.util.Map; - public class HexLootTables extends PaucalLootTableSubProvider { - public HexLootTables() { - super(HexAPI.MOD_ID); - } - - @Override - protected void makeLootTables(Map<Block, LootTable.Builder> blockTables, - Map<ResourceLocation, LootTable.Builder> lootTables) { - dropSelf(blockTables, HexBlocks.IMPETUS_EMPTY, - HexBlocks.IMPETUS_RIGHTCLICK, HexBlocks.IMPETUS_LOOK, HexBlocks.IMPETUS_REDSTONE, - HexBlocks.EMPTY_DIRECTRIX, HexBlocks.DIRECTRIX_REDSTONE, HexBlocks.DIRECTRIX_BOOLEAN, - HexBlocks.AKASHIC_RECORD, HexBlocks.AKASHIC_BOOKSHELF, HexBlocks.AKASHIC_LIGATURE, - HexBlocks.SLATE_BLOCK, HexBlocks.SLATE_TILES, HexBlocks.SLATE_BRICKS, HexBlocks.SLATE_BRICKS_SMALL, - HexBlocks.SLATE_PILLAR, HexBlocks.AMETHYST_DUST_BLOCK, HexBlocks.AMETHYST_TILES, HexBlocks.AMETHYST_BRICKS, - HexBlocks.AMETHYST_BRICKS_SMALL, HexBlocks.AMETHYST_PILLAR, HexBlocks.SLATE_AMETHYST_TILES, - HexBlocks.SLATE_AMETHYST_BRICKS, HexBlocks.SLATE_AMETHYST_BRICKS_SMALL, HexBlocks.SLATE_AMETHYST_PILLAR, - HexBlocks.QUENCHED_ALLAY_TILES, HexBlocks.QUENCHED_ALLAY_BRICKS, HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL, - HexBlocks.SCROLL_PAPER, HexBlocks.ANCIENT_SCROLL_PAPER, HexBlocks.SCROLL_PAPER_LANTERN, - HexBlocks.ANCIENT_SCROLL_PAPER_LANTERN, HexBlocks.SCONCE, - HexBlocks.EDIFIED_LOG, HexBlocks.EDIFIED_LOG_AMETHYST, HexBlocks.EDIFIED_LOG_AVENTURINE, - HexBlocks.EDIFIED_LOG_CITRINE, HexBlocks.EDIFIED_LOG_PURPLE, HexBlocks.STRIPPED_EDIFIED_LOG, - HexBlocks.EDIFIED_WOOD, HexBlocks.STRIPPED_EDIFIED_WOOD, - HexBlocks.EDIFIED_PLANKS, HexBlocks.EDIFIED_TILE, HexBlocks.EDIFIED_PANEL, - HexBlocks.EDIFIED_TRAPDOOR, HexBlocks.EDIFIED_STAIRS, HexBlocks.EDIFIED_FENCE, HexBlocks.EDIFIED_FENCE_GATE, HexBlocks.EDIFIED_PRESSURE_PLATE, - HexBlocks.EDIFIED_BUTTON); - - makeSlabTable(blockTables, HexBlocks.EDIFIED_SLAB); - - makeLeafTable(blockTables, HexBlocks.AMETHYST_EDIFIED_LEAVES); - makeLeafTable(blockTables, HexBlocks.AVENTURINE_EDIFIED_LEAVES); - makeLeafTable(blockTables, HexBlocks.CITRINE_EDIFIED_LEAVES); - - var slatePool = LootPool.lootPool() - .setRolls(ConstantValue.exactly(1)) - .add(LootItem.lootTableItem(HexBlocks.SLATE) - .apply(CopyNbtFunction.copyData(ContextNbtProvider.BLOCK_ENTITY) - .copy(BlockEntitySlate.TAG_PATTERN, "BlockEntityTag." + BlockEntitySlate.TAG_PATTERN))); - blockTables.put(HexBlocks.SLATE, LootTable.lootTable().withPool(slatePool)); - - var doorPool = dropThisPool(HexBlocks.EDIFIED_DOOR, 1) - .when(new LootItemBlockStatePropertyCondition.Builder(HexBlocks.EDIFIED_DOOR).setProperties( - StatePropertiesPredicate.Builder.properties().hasProperty(DoorBlock.HALF, DoubleBlockHalf.LOWER) - )); - blockTables.put(HexBlocks.EDIFIED_DOOR, LootTable.lootTable().withPool(doorPool)); - - - var silkTouchCond = MatchTool.toolMatches( - ItemPredicate.Builder.item().hasEnchantment( - new EnchantmentPredicate(Enchantments.SILK_TOUCH, MinMaxBounds.Ints.ANY))); - var noSilkTouchCond = silkTouchCond.invert(); - var goodAtAmethystingCond = MatchTool.toolMatches( - ItemPredicate.Builder.item().of(ItemTags.CLUSTER_MAX_HARVESTABLES) - ); - - var dustPoolWhenGood = LootPool.lootPool() - .add(LootItem.lootTableItem(HexItems.AMETHYST_DUST)) - .apply(SetItemCountFunction.setCount(UniformGenerator.between(1, 4))) - .apply(ApplyBonusCount.addOreBonusCount(Enchantments.BLOCK_FORTUNE)) - .when(noSilkTouchCond).when(goodAtAmethystingCond); - - var dustPoolWhenBad = LootPool.lootPool() - .add(LootItem.lootTableItem(HexItems.AMETHYST_DUST)) - .apply(SetItemCountFunction.setCount(UniformGenerator.between(0, 2))) - .when(noSilkTouchCond).when(goodAtAmethystingCond.invert()); - - var isThatAnMFingBrandonSandersonReference = LootPool.lootPool() - .add(LootItem.lootTableItem(HexItems.CHARGED_AMETHYST)) - .apply(SetItemCountFunction.setCount(ConstantValue.exactly(1))) - .when(noSilkTouchCond).when(goodAtAmethystingCond) - .when(BonusLevelTableCondition.bonusLevelFlatChance(Enchantments.BLOCK_FORTUNE, - 0.25f, 0.35f, 0.5f, 0.75f, 1.0f)); - - var isThatAnMFingBadBrandonSandersonReference = LootPool.lootPool() - .add(LootItem.lootTableItem(HexItems.CHARGED_AMETHYST)) - .apply(SetItemCountFunction.setCount(ConstantValue.exactly(1))) - .when(noSilkTouchCond).when(goodAtAmethystingCond.invert()) - .when(LootItemRandomChanceCondition.randomChance(0.125f)); - - lootTables.put(HexLootHandler.TABLE_INJECT_AMETHYST_CLUSTER, LootTable.lootTable() - .withPool(dustPoolWhenGood) - .withPool(dustPoolWhenBad) - .withPool(isThatAnMFingBrandonSandersonReference) - .withPool(isThatAnMFingBadBrandonSandersonReference)); - - // it looks like loot groups are bugged? - // so instead we add some and then *increment* the amount, gated behind the cond - var quenchedPool = LootPool.lootPool().add(AlternativesEntry.alternatives( - LootItem.lootTableItem(HexBlocks.QUENCHED_ALLAY).when(silkTouchCond), - LootItem.lootTableItem(HexItems.QUENCHED_SHARD) - .apply(SetItemCountFunction.setCount(UniformGenerator.between(2f, 4f))) - .apply(SetItemCountFunction.setCount(ConstantValue.exactly(1), true) - .when(BonusLevelTableCondition.bonusLevelFlatChance(Enchantments.BLOCK_FORTUNE, - 0.25f, 0.5f, 0.75f, 1.0f))) - )); - blockTables.put(HexBlocks.QUENCHED_ALLAY, LootTable.lootTable().withPool(quenchedPool)); - } - - private void makeLeafTable(Map<Block, LootTable.Builder> lootTables, Block block) { - var leafPool = dropThisPool(block, 1) - .when(AnyOfCondition.anyOf( - IXplatAbstractions.INSTANCE.isShearsCondition(), - MatchTool.toolMatches(ItemPredicate.Builder.item() - .hasEnchantment(new EnchantmentPredicate(Enchantments.SILK_TOUCH, MinMaxBounds.Ints.atLeast(1)))) - )); - lootTables.put(block, LootTable.lootTable().withPool(leafPool)); - } - - private void makeSlabTable(Map<Block, LootTable.Builder> lootTables, Block block) { - var leafPool = dropThisPool(block, 1) - .apply(SetItemCountFunction.setCount(ConstantValue.exactly(2)) - .when(new LootItemBlockStatePropertyCondition.Builder(block).setProperties( - StatePropertiesPredicate.Builder.properties().hasProperty(SlabBlock.TYPE, SlabType.DOUBLE) - ))) - .apply(ApplyExplosionDecay.explosionDecay()); - lootTables.put(block, LootTable.lootTable().withPool(leafPool)); - } + public HexLootTables() { + super(HexAPI.MOD_ID); + } + + @Override + protected void makeLootTables( + Map<Block, LootTable.Builder> blockTables, + Map<ResourceLocation, LootTable.Builder> lootTables) { + dropSelf( + blockTables, + HexBlocks.IMPETUS_EMPTY, + HexBlocks.IMPETUS_RIGHTCLICK, + HexBlocks.IMPETUS_LOOK, + HexBlocks.IMPETUS_REDSTONE, + HexBlocks.EMPTY_DIRECTRIX, + HexBlocks.DIRECTRIX_REDSTONE, + HexBlocks.DIRECTRIX_BOOLEAN, + HexBlocks.AKASHIC_RECORD, + HexBlocks.AKASHIC_BOOKSHELF, + HexBlocks.AKASHIC_LIGATURE, + HexBlocks.SLATE_BLOCK, + HexBlocks.SLATE_TILES, + HexBlocks.SLATE_BRICKS, + HexBlocks.SLATE_BRICKS_SMALL, + HexBlocks.SLATE_PILLAR, + HexBlocks.AMETHYST_DUST_BLOCK, + HexBlocks.AMETHYST_TILES, + HexBlocks.AMETHYST_BRICKS, + HexBlocks.AMETHYST_BRICKS_SMALL, + HexBlocks.AMETHYST_PILLAR, + HexBlocks.SLATE_AMETHYST_TILES, + HexBlocks.SLATE_AMETHYST_BRICKS, + HexBlocks.SLATE_AMETHYST_BRICKS_SMALL, + HexBlocks.SLATE_AMETHYST_PILLAR, + HexBlocks.QUENCHED_ALLAY_TILES, + HexBlocks.QUENCHED_ALLAY_BRICKS, + HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL, + HexBlocks.SCROLL_PAPER, + HexBlocks.ANCIENT_SCROLL_PAPER, + HexBlocks.SCROLL_PAPER_LANTERN, + HexBlocks.ANCIENT_SCROLL_PAPER_LANTERN, + HexBlocks.SCONCE, + HexBlocks.EDIFIED_LOG, + HexBlocks.EDIFIED_LOG_AMETHYST, + HexBlocks.EDIFIED_LOG_AVENTURINE, + HexBlocks.EDIFIED_LOG_CITRINE, + HexBlocks.EDIFIED_LOG_PURPLE, + HexBlocks.STRIPPED_EDIFIED_LOG, + HexBlocks.EDIFIED_WOOD, + HexBlocks.STRIPPED_EDIFIED_WOOD, + HexBlocks.EDIFIED_PLANKS, + HexBlocks.EDIFIED_TILE, + HexBlocks.EDIFIED_PANEL, + HexBlocks.EDIFIED_TRAPDOOR, + HexBlocks.EDIFIED_STAIRS, + HexBlocks.EDIFIED_FENCE, + HexBlocks.EDIFIED_FENCE_GATE, + HexBlocks.EDIFIED_PRESSURE_PLATE, + HexBlocks.EDIFIED_BUTTON); + + makeSlabTable(blockTables, HexBlocks.EDIFIED_SLAB); + + makeLeafTable(blockTables, HexBlocks.AMETHYST_EDIFIED_LEAVES); + makeLeafTable(blockTables, HexBlocks.AVENTURINE_EDIFIED_LEAVES); + makeLeafTable(blockTables, HexBlocks.CITRINE_EDIFIED_LEAVES); + + var slatePool = + LootPool.lootPool() + .setRolls(ConstantValue.exactly(1)) + .add( + LootItem.lootTableItem(HexBlocks.SLATE) + .apply( + CopyNbtFunction.copyData(ContextNbtProvider.BLOCK_ENTITY) + .copy( + BlockEntitySlate.TAG_PATTERN, + "BlockEntityTag." + BlockEntitySlate.TAG_PATTERN))); + blockTables.put(HexBlocks.SLATE, LootTable.lootTable().withPool(slatePool)); + + var doorPool = + dropThisPool(HexBlocks.EDIFIED_DOOR, 1) + .when( + new LootItemBlockStatePropertyCondition.Builder(HexBlocks.EDIFIED_DOOR) + .setProperties( + StatePropertiesPredicate.Builder.properties() + .hasProperty(DoorBlock.HALF, DoubleBlockHalf.LOWER))); + blockTables.put(HexBlocks.EDIFIED_DOOR, LootTable.lootTable().withPool(doorPool)); + + var silkTouchCond = + MatchTool.toolMatches( + ItemPredicate.Builder.item() + .hasEnchantment( + new EnchantmentPredicate(Enchantments.SILK_TOUCH, MinMaxBounds.Ints.ANY))); + var noSilkTouchCond = silkTouchCond.invert(); + var goodAtAmethystingCond = + MatchTool.toolMatches(ItemPredicate.Builder.item().of(ItemTags.CLUSTER_MAX_HARVESTABLES)); + + var dustPoolWhenGood = + LootPool.lootPool() + .add(LootItem.lootTableItem(HexItems.AMETHYST_DUST)) + .apply(SetItemCountFunction.setCount(UniformGenerator.between(1, 4))) + .apply(ApplyBonusCount.addOreBonusCount(Enchantments.BLOCK_FORTUNE)) + .when(noSilkTouchCond) + .when(goodAtAmethystingCond); + + var dustPoolWhenBad = + LootPool.lootPool() + .add(LootItem.lootTableItem(HexItems.AMETHYST_DUST)) + .apply(SetItemCountFunction.setCount(UniformGenerator.between(0, 2))) + .when(noSilkTouchCond) + .when(goodAtAmethystingCond.invert()); + + var isThatAnMFingBrandonSandersonReference = + LootPool.lootPool() + .add(LootItem.lootTableItem(HexItems.CHARGED_AMETHYST)) + .apply(SetItemCountFunction.setCount(ConstantValue.exactly(1))) + .when(noSilkTouchCond) + .when(goodAtAmethystingCond) + .when( + BonusLevelTableCondition.bonusLevelFlatChance( + Enchantments.BLOCK_FORTUNE, 0.25f, 0.35f, 0.5f, 0.75f, 1.0f)); + + var isThatAnMFingBadBrandonSandersonReference = + LootPool.lootPool() + .add(LootItem.lootTableItem(HexItems.CHARGED_AMETHYST)) + .apply(SetItemCountFunction.setCount(ConstantValue.exactly(1))) + .when(noSilkTouchCond) + .when(goodAtAmethystingCond.invert()) + .when(LootItemRandomChanceCondition.randomChance(0.125f)); + + lootTables.put( + HexLootHandler.TABLE_INJECT_AMETHYST_CLUSTER, + LootTable.lootTable() + .withPool(dustPoolWhenGood) + .withPool(dustPoolWhenBad) + .withPool(isThatAnMFingBrandonSandersonReference) + .withPool(isThatAnMFingBadBrandonSandersonReference)); + + // it looks like loot groups are bugged? + // so instead we add some and then *increment* the amount, gated behind the cond + var quenchedPool = + LootPool.lootPool() + .add( + AlternativesEntry.alternatives( + LootItem.lootTableItem(HexBlocks.QUENCHED_ALLAY).when(silkTouchCond), + LootItem.lootTableItem(HexItems.QUENCHED_SHARD) + .apply(SetItemCountFunction.setCount(UniformGenerator.between(2f, 4f))) + .apply( + SetItemCountFunction.setCount(ConstantValue.exactly(1), true) + .when( + BonusLevelTableCondition.bonusLevelFlatChance( + Enchantments.BLOCK_FORTUNE, 0.25f, 0.5f, 0.75f, 1.0f))))); + blockTables.put(HexBlocks.QUENCHED_ALLAY, LootTable.lootTable().withPool(quenchedPool)); + } + + private void makeLeafTable(Map<Block, LootTable.Builder> lootTables, Block block) { + var leafPool = + dropThisPool(block, 1) + .when( + AnyOfCondition.anyOf( + IXplatAbstractions.INSTANCE.isShearsCondition(), + MatchTool.toolMatches( + ItemPredicate.Builder.item() + .hasEnchantment( + new EnchantmentPredicate( + Enchantments.SILK_TOUCH, MinMaxBounds.Ints.atLeast(1)))))); + lootTables.put(block, LootTable.lootTable().withPool(leafPool)); + } + + private void makeSlabTable(Map<Block, LootTable.Builder> lootTables, Block block) { + var leafPool = + dropThisPool(block, 1) + .apply( + SetItemCountFunction.setCount(ConstantValue.exactly(2)) + .when( + new LootItemBlockStatePropertyCondition.Builder(block) + .setProperties( + StatePropertiesPredicate.Builder.properties() + .hasProperty(SlabBlock.TYPE, SlabType.DOUBLE)))) + .apply(ApplyExplosionDecay.explosionDecay()); + lootTables.put(block, LootTable.lootTable().withPool(leafPool)); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/IXplatConditionsBuilder.java b/Common/src/main/java/at/petrak/hexcasting/datagen/IXplatConditionsBuilder.java index d283711fab..453eb4ffa5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/IXplatConditionsBuilder.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/IXplatConditionsBuilder.java @@ -3,7 +3,7 @@ import net.minecraft.data.recipes.RecipeBuilder; public interface IXplatConditionsBuilder extends RecipeBuilder { - IXplatConditionsBuilder whenModLoaded(String modid); + IXplatConditionsBuilder whenModLoaded(String modid); - IXplatConditionsBuilder whenModMissing(String modid); + IXplatConditionsBuilder whenModMissing(String modid); } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/IXplatIngredients.java b/Common/src/main/java/at/petrak/hexcasting/datagen/IXplatIngredients.java index e378438608..c1ee62dc36 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/IXplatIngredients.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/IXplatIngredients.java @@ -1,33 +1,33 @@ package at.petrak.hexcasting.datagen; import at.petrak.hexcasting.datagen.recipe.builders.FarmersDelightToolIngredient; +import java.util.EnumMap; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.crafting.Ingredient; -import java.util.EnumMap; - public interface IXplatIngredients { - Ingredient glowstoneDust(); + Ingredient glowstoneDust(); - Ingredient leather(); + Ingredient leather(); - Ingredient ironNugget(); + Ingredient ironNugget(); - Ingredient goldNugget(); + Ingredient goldNugget(); - Ingredient copperIngot(); + Ingredient copperIngot(); - Ingredient ironIngot(); + Ingredient ironIngot(); - Ingredient goldIngot(); + Ingredient goldIngot(); - EnumMap<DyeColor, Ingredient> dyes(); + EnumMap<DyeColor, Ingredient> dyes(); - Ingredient stick(); + Ingredient stick(); - Ingredient whenModIngredient(Ingredient defaultIngredient, String modid, Ingredient modIngredient); + Ingredient whenModIngredient( + Ingredient defaultIngredient, String modid, Ingredient modIngredient); - FarmersDelightToolIngredient axeStrip(); + FarmersDelightToolIngredient axeStrip(); - FarmersDelightToolIngredient axeDig(); + FarmersDelightToolIngredient axeDig(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/HexplatRecipes.java b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/HexplatRecipes.java index 828c8ad92f..5316fbdd6e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/HexplatRecipes.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/HexplatRecipes.java @@ -20,6 +20,10 @@ import at.petrak.hexcasting.datagen.recipe.builders.CreateCrushingRecipeBuilder; import at.petrak.hexcasting.datagen.recipe.builders.FarmersDelightCuttingRecipeBuilder; import at.petrak.paucal.api.datagen.PaucalRecipeProvider; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.PackOutput; import net.minecraft.data.recipes.*; @@ -36,538 +40,681 @@ import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer; import net.minecraft.world.level.block.Blocks; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; - -// TODO: need to do a big refactor of this class cause it's giant and unwieldy, probably as part of #360 +// TODO: need to do a big refactor of this class cause it's giant and unwieldy, probably as part of +// #360 public class HexplatRecipes extends PaucalRecipeProvider { - private final IXplatIngredients ingredients; - private final Function<RecipeBuilder, IXplatConditionsBuilder> conditions; - - private final List<BlockAkashicLog> EDIFIED_LOGS = List.of( - HexBlocks.EDIFIED_LOG, HexBlocks.EDIFIED_LOG_AMETHYST, - HexBlocks.EDIFIED_LOG_AVENTURINE, HexBlocks.EDIFIED_LOG_CITRINE, - HexBlocks.EDIFIED_LOG_PURPLE); - - private final Map<BlockAkashicLog, BlockAkashicLog> EDIFIED_LOG_TO_WOOD = Map.ofEntries( - Map.entry(HexBlocks.EDIFIED_LOG, HexBlocks.EDIFIED_WOOD), -// These don't exist, idk if they should -// Map.entry(HexBlocks.EDIFIED_LOG_AMETHYST, HexBlocks.EDIFIED_WOOD_AMETHYST), -// Map.entry(HexBlocks.EDIFIED_LOG_AVENTURINE, HexBlocks.EDIFIED_WOOD_AVENTURINE), -// Map.entry(HexBlocks.EDIFIED_LOG_CITRINE, HexBlocks.EDIFIED_WOOD_CITRINE), -// Map.entry(HexBlocks.EDIFIED_LOG_PURPLE, HexBlocks.EDIFIED_WOOD_PURPLE), - Map.entry(HexBlocks.STRIPPED_EDIFIED_LOG, HexBlocks.STRIPPED_EDIFIED_WOOD) - ); - - public HexplatRecipes(PackOutput output, IXplatIngredients ingredients, - Function<RecipeBuilder, IXplatConditionsBuilder> conditions) { - super(output, HexAPI.MOD_ID); - this.ingredients = ingredients; - this.conditions = conditions; - } - - @Override - public void buildRecipes(Consumer<FinishedRecipe> recipes) { - specialRecipe(recipes, SealThingsRecipe.FOCUS_SERIALIZER); - specialRecipe(recipes, SealThingsRecipe.SPELLBOOK_SERIALIZER); - - staffRecipe(recipes, HexItems.STAFF_OAK, Items.OAK_PLANKS); - staffRecipe(recipes, HexItems.STAFF_BIRCH, Items.BIRCH_PLANKS); - staffRecipe(recipes, HexItems.STAFF_SPRUCE, Items.SPRUCE_PLANKS); - staffRecipe(recipes, HexItems.STAFF_JUNGLE, Items.JUNGLE_PLANKS); - staffRecipe(recipes, HexItems.STAFF_DARK_OAK, Items.DARK_OAK_PLANKS); - staffRecipe(recipes, HexItems.STAFF_ACACIA, Items.ACACIA_PLANKS); - staffRecipe(recipes, HexItems.STAFF_CRIMSON, Items.CRIMSON_PLANKS); - staffRecipe(recipes, HexItems.STAFF_WARPED, Items.WARPED_PLANKS); - staffRecipe(recipes, HexItems.STAFF_MANGROVE, Items.MANGROVE_PLANKS); - staffRecipe(recipes, HexItems.STAFF_CHERRY, Items.CHERRY_PLANKS); - staffRecipe(recipes, HexItems.STAFF_BAMBOO, Items.BAMBOO_PLANKS); - staffRecipe(recipes, HexItems.STAFF_EDIFIED, HexBlocks.EDIFIED_PLANKS.asItem()); - staffRecipe(recipes, HexItems.STAFF_QUENCHED, HexItems.QUENCHED_SHARD); - staffRecipe(recipes, HexItems.STAFF_MINDSPLICE, Ingredient.of(HexTags.Items.MINDFLAYED_CIRCLE_COMPONENTS)); - - ShapelessRecipeBuilder.shapeless(RecipeCategory.TOOLS, HexItems.THOUGHT_KNOT) - .requires(HexItems.AMETHYST_DUST) - .requires(Items.STRING) - .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)) - .save(recipes); - ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, HexItems.FOCUS) - .define('G', ingredients.glowstoneDust()) - .define('L', ingredients.leather()) - .define('P', Items.PAPER) - .define('A', HexItems.CHARGED_AMETHYST) - .pattern("GLG") - .pattern("PAP") - .pattern("GLG") - .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)) - .save(recipes); - ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, HexItems.FOCUS) - .define('G', ingredients.glowstoneDust()) - .define('L', ingredients.leather()) - .define('P', Items.PAPER) - .define('A', HexItems.CHARGED_AMETHYST) - .pattern("GPG") - .pattern("LAL") - .pattern("GPG") - .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)) - .save(recipes, modLoc("focus_rotated")); - - ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, HexItems.SPELLBOOK) - .define('N', ingredients.goldNugget()) - .define('B', Items.WRITABLE_BOOK) - .define('A', HexItems.CHARGED_AMETHYST) - .define('F', Items.CHORUS_FRUIT) // i wanna gate this behind the end SOMEHOW - // hey look its my gender ^^ - .pattern("NBA") - .pattern("NFA") - .pattern("NBA") - .unlockedBy("has_focus", hasItem(HexItems.FOCUS)) - .unlockedBy("has_chorus", hasItem(Items.CHORUS_FRUIT)).save(recipes); - - ringCornerless(RecipeCategory.TOOLS, - HexItems.CYPHER, 1, - ingredients.copperIngot(), - Ingredient.of(HexItems.AMETHYST_DUST)) - .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)).save(recipes); - - ringCornerless(RecipeCategory.TOOLS, - HexItems.TRINKET, 1, - ingredients.ironIngot(), - Ingredient.of(Items.AMETHYST_SHARD)) - .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, HexItems.ARTIFACT) - .define('F', ingredients.goldIngot()) - .define('A', HexItems.CHARGED_AMETHYST) - // why in god's name does minecraft have two different places for item tags - .define('D', ItemTags.MUSIC_DISCS) - .pattern(" F ") - .pattern("FAF") - .pattern(" D ") - .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)).save(recipes); - - ringCornerless(RecipeCategory.TOOLS, HexItems.SCRYING_LENS, 1, Items.GLASS, HexItems.AMETHYST_DUST) - .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, HexItems.ABACUS) - .define('S', Items.STICK) - .define('A', Items.AMETHYST_SHARD) - .define('W', ItemTags.PLANKS) - .pattern("WAW") - .pattern("SAS") - .pattern("WAW") - .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)).save(recipes); - - // Why am I like this - ShapedRecipeBuilder.shaped(RecipeCategory.FOOD, HexItems.SUBMARINE_SANDWICH) - .define('S', Items.STICK) - .define('A', Items.AMETHYST_SHARD) - .define('C', Items.COOKED_BEEF) - .define('B', Items.BREAD) - .pattern(" SA") - .pattern(" C ") - .pattern(" B ") - .unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes); - - for (var dye : DyeColor.values()) { - var item = HexItems.DYE_PIGMENTS.get(dye); - ShapedRecipeBuilder.shaped(RecipeCategory.MISC, item) - .define('D', HexItems.AMETHYST_DUST) - .define('C', DyeItem.byColor(dye)) - .pattern(" D ") - .pattern("DCD") - .pattern(" D ") - .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)).save(recipes); - } - - gayRecipe(recipes, ItemPridePigment.Type.AGENDER, Ingredient.of(Items.GLASS)); - gayRecipe(recipes, ItemPridePigment.Type.AROACE, Ingredient.of(Items.WHEAT_SEEDS)); - gayRecipe(recipes, ItemPridePigment.Type.AROMANTIC, Ingredient.of(Items.ARROW)); - gayRecipe(recipes, ItemPridePigment.Type.ASEXUAL, Ingredient.of(Items.BREAD)); - gayRecipe(recipes, ItemPridePigment.Type.BISEXUAL, Ingredient.of(Items.WHEAT)); - gayRecipe(recipes, ItemPridePigment.Type.DEMIBOY, Ingredient.of(Items.RAW_IRON)); - gayRecipe(recipes, ItemPridePigment.Type.DEMIGIRL, Ingredient.of(Items.RAW_COPPER)); - gayRecipe(recipes, ItemPridePigment.Type.GAY, Ingredient.of(Items.STONE_BRICK_WALL)); - gayRecipe(recipes, ItemPridePigment.Type.GENDERFLUID, Ingredient.of(Items.WATER_BUCKET)); - gayRecipe(recipes, ItemPridePigment.Type.GENDERQUEER, Ingredient.of(Items.GLASS_BOTTLE)); - gayRecipe(recipes, ItemPridePigment.Type.INTERSEX, Ingredient.of(Items.AZALEA)); - gayRecipe(recipes, ItemPridePigment.Type.LESBIAN, Ingredient.of(Items.HONEYCOMB)); - gayRecipe(recipes, ItemPridePigment.Type.NONBINARY, Ingredient.of(Items.MOSS_BLOCK)); - gayRecipe(recipes, ItemPridePigment.Type.PANSEXUAL, ingredients.whenModIngredient( - Ingredient.of(Items.CARROT), - "farmersdelight", - CompatIngredientValue.of("farmersdelight:skillet") - )); - gayRecipe(recipes, ItemPridePigment.Type.PLURAL, Ingredient.of(Items.REPEATER)); - gayRecipe(recipes, ItemPridePigment.Type.TRANSGENDER, Ingredient.of(Items.EGG)); - - ring(RecipeCategory.MISC, HexItems.UUID_PIGMENT, 1, HexItems.AMETHYST_DUST, Items.AMETHYST_SHARD) - .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)).save(recipes); - ring(RecipeCategory.MISC, HexItems.DEFAULT_PIGMENT, 1, HexItems.AMETHYST_DUST, Items.COPPER_INGOT) - .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, HexItems.SCROLL_SMOL) - .define('P', Items.PAPER) - .define('A', HexItems.AMETHYST_DUST) - .pattern(" A") - .pattern("P ") - .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, HexItems.SCROLL_MEDIUM) - .define('P', Items.PAPER) - .define('A', HexItems.AMETHYST_DUST) - .pattern(" A") - .pattern("PP ") - .pattern("PP ") - .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, HexItems.SCROLL_LARGE) - .define('P', Items.PAPER) - .define('A', HexItems.AMETHYST_DUST) - .pattern("PPA") - .pattern("PPP") - .pattern("PPP") - .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, HexItems.SLATE, 6) - .define('S', Items.DEEPSLATE) - .define('A', HexItems.AMETHYST_DUST) - .pattern(" A ") - .pattern("SSS") - .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, HexItems.JEWELER_HAMMER) - .define('I', ingredients.ironIngot()) - .define('N', ingredients.ironNugget()) - .define('A', Items.AMETHYST_SHARD) - .define('S', ingredients.stick()) - .pattern("IAN") - .pattern(" S ") - .pattern(" S ") - .unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes); - - ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, HexItems.AMETHYST_DUST, - (int) (MediaConstants.QUENCHED_SHARD_UNIT / MediaConstants.DUST_UNIT) + 1) - .requires(HexItems.QUENCHED_SHARD) - .requires(HexItems.AMETHYST_DUST) - .unlockedBy("has_item", hasItem(HexItems.QUENCHED_SHARD)) - .save(recipes, modLoc("decompose_quenched_shard/dust")); - ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, Items.AMETHYST_SHARD, - (int) (MediaConstants.QUENCHED_SHARD_UNIT / MediaConstants.SHARD_UNIT) + 1) - .requires(HexItems.QUENCHED_SHARD) - .requires(Items.AMETHYST_SHARD) - .unlockedBy("has_item", hasItem(HexItems.QUENCHED_SHARD)) - .save(recipes, modLoc("decompose_quenched_shard/shard")); - ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, HexItems.CHARGED_AMETHYST, - (int) (MediaConstants.QUENCHED_SHARD_UNIT / MediaConstants.CRYSTAL_UNIT) + 1) - .requires(HexItems.QUENCHED_SHARD) - .requires(HexItems.CHARGED_AMETHYST) - .unlockedBy("has_item", hasItem(HexItems.QUENCHED_SHARD)) - .save(recipes, modLoc("decompose_quenched_shard/charged")); - - ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, HexBlocks.SLATE_BLOCK) - .define('S', HexItems.SLATE) - .pattern("S") - .pattern("S") - .unlockedBy("has_item", hasItem(HexItems.SLATE)) - .save(recipes, modLoc("slate_block_from_slates")); - - ringAll(RecipeCategory.BUILDING_BLOCKS, HexBlocks.SLATE_BLOCK, 8, Blocks.DEEPSLATE, HexItems.AMETHYST_DUST) - .unlockedBy("has_item", hasItem(HexItems.SLATE)).save(recipes); - - packing(RecipeCategory.BUILDING_BLOCKS, HexItems.AMETHYST_DUST, HexBlocks.AMETHYST_DUST_BLOCK.asItem(), "amethyst_dust", - false, recipes); - - ringAll(RecipeCategory.BUILDING_BLOCKS, HexBlocks.AMETHYST_TILES, 8, Blocks.AMETHYST_BLOCK, HexItems.AMETHYST_DUST) - .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)).save(recipes); - - SingleItemRecipeBuilder.stonecutting(Ingredient.of(Blocks.AMETHYST_BLOCK), RecipeCategory.BUILDING_BLOCKS, HexBlocks.AMETHYST_TILES) - .unlockedBy("has_item", hasItem(Blocks.AMETHYST_BLOCK)) - .save(recipes, modLoc("stonecutting/amethyst_tiles")); - - ringAll(RecipeCategory.BUILDING_BLOCKS, HexBlocks.SCROLL_PAPER, 8, Items.PAPER, Items.AMETHYST_SHARD) - .unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes); - - ShapelessRecipeBuilder.shapeless(RecipeCategory.BUILDING_BLOCKS, HexBlocks.ANCIENT_SCROLL_PAPER, 8) - .requires(ingredients.dyes().get(DyeColor.BROWN)) - .requires(HexBlocks.SCROLL_PAPER, 8) - .unlockedBy("has_item", hasItem(HexBlocks.SCROLL_PAPER)).save(recipes); - - stack(RecipeCategory.DECORATIONS, HexBlocks.SCROLL_PAPER_LANTERN, 1, HexBlocks.SCROLL_PAPER, Items.TORCH) - .unlockedBy("has_item", hasItem(HexBlocks.SCROLL_PAPER)).save(recipes); - - stack(RecipeCategory.DECORATIONS, HexBlocks.ANCIENT_SCROLL_PAPER_LANTERN, 1, HexBlocks.ANCIENT_SCROLL_PAPER, Items.TORCH) - .unlockedBy("has_item", hasItem(HexBlocks.ANCIENT_SCROLL_PAPER)).save(recipes); - - ShapelessRecipeBuilder.shapeless(RecipeCategory.DECORATIONS, HexBlocks.ANCIENT_SCROLL_PAPER_LANTERN, 8) - .requires(ingredients.dyes().get(DyeColor.BROWN)) - .requires(HexBlocks.SCROLL_PAPER_LANTERN, 8) - .unlockedBy("has_item", hasItem(HexBlocks.SCROLL_PAPER_LANTERN)) - .save(recipes, modLoc("ageing_scroll_paper_lantern")); - - stack(RecipeCategory.DECORATIONS, HexBlocks.SCONCE, 4, - Ingredient.of(HexItems.CHARGED_AMETHYST), - ingredients.copperIngot()) - .unlockedBy("has_item", hasItem(HexItems.CHARGED_AMETHYST)).save(recipes); - - ShapelessRecipeBuilder.shapeless(RecipeCategory.BUILDING_BLOCKS, HexBlocks.EDIFIED_PLANKS, 4) - .requires(HexTags.Items.EDIFIED_LOGS) - .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_LOGS)).save(recipes); - - for (var entry : EDIFIED_LOG_TO_WOOD.entrySet()) { - var log = entry.getKey(); - var wood = entry.getValue(); - ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, wood, 3) - .define('W', log) - .pattern("WW") - .pattern("WW") - .unlockedBy("has_item", hasItem(log)).save(recipes); - } - - ring(RecipeCategory.BUILDING_BLOCKS, HexBlocks.EDIFIED_PANEL, 8, - HexTags.Items.EDIFIED_PLANKS, null) - .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, HexBlocks.EDIFIED_TILE, 6) - .define('W', HexTags.Items.EDIFIED_PLANKS) - .pattern("WW ") - .pattern("W W") - .pattern(" WW") - .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.REDSTONE, HexBlocks.EDIFIED_DOOR, 3) - .define('W', HexTags.Items.EDIFIED_PLANKS) - .pattern("WW") - .pattern("WW") - .pattern("WW") - .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.REDSTONE, HexBlocks.EDIFIED_TRAPDOOR, 2) - .define('W', HexTags.Items.EDIFIED_PLANKS) - .pattern("WWW") - .pattern("WWW") - .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, HexBlocks.EDIFIED_STAIRS, 4) - .define('W', HexTags.Items.EDIFIED_PLANKS) - .pattern("W ") - .pattern("WW ") - .pattern("WWW") - .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, HexBlocks.EDIFIED_FENCE, 3) - .define('W', HexTags.Items.EDIFIED_PLANKS) - .define('S', Items.STICK) - .pattern("WSW") - .pattern("WSW") - .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, HexBlocks.EDIFIED_FENCE_GATE, 1) - .define('W', HexTags.Items.EDIFIED_PLANKS) - .define('S', Items.STICK) - .pattern("SWS") - .pattern("SWS") - .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)).save(recipes); - - - ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, HexBlocks.EDIFIED_SLAB, 6) - .define('W', HexTags.Items.EDIFIED_PLANKS) - .pattern("WWW") - .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.REDSTONE, HexBlocks.EDIFIED_PRESSURE_PLATE, 1) - .define('W', HexTags.Items.EDIFIED_PLANKS) - .pattern("WW") - .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)).save(recipes); - - ShapelessRecipeBuilder.shapeless(RecipeCategory.REDSTONE, HexBlocks.EDIFIED_BUTTON) - .requires(HexTags.Items.EDIFIED_PLANKS) - .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)).save(recipes); - - var enlightenment = HexAdvancements.ENLIGHTEN; - ShapedRecipeBuilder.shaped(RecipeCategory.REDSTONE, HexBlocks.IMPETUS_EMPTY) - .define('B', Items.IRON_BARS) - .define('A', HexItems.CHARGED_AMETHYST) - .define('S', HexBlocks.SLATE_BLOCK) - .define('P', Items.PURPUR_BLOCK) - .pattern("PSS") - .pattern("BAB") - .pattern("SSP") - .unlockedBy("enlightenment", enlightenment).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.REDSTONE, HexBlocks.EMPTY_DIRECTRIX) - .define('C', Items.COMPARATOR) - .define('O', Items.OBSERVER) - .define('A', HexItems.CHARGED_AMETHYST) - .define('S', HexBlocks.SLATE_BLOCK) - .pattern("CSS") - .pattern("OAO") - .pattern("SSC") - .unlockedBy("enlightenment", enlightenment).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.REDSTONE, HexBlocks.AKASHIC_BOOKSHELF) - .define('L', HexTags.Items.EDIFIED_LOGS) - .define('P', HexTags.Items.EDIFIED_PLANKS) - .define('C', Items.BOOK) - /*this is the*/.pattern("LPL") // and what i have for you today is - .pattern("CCC") - .pattern("LPL") - .unlockedBy("enlightenment", enlightenment).save(recipes); - - ShapedRecipeBuilder.shaped(RecipeCategory.REDSTONE, HexBlocks.AKASHIC_LIGATURE, 4) - .define('L', HexTags.Items.EDIFIED_LOGS) - .define('P', HexTags.Items.EDIFIED_PLANKS) - .define('1', HexItems.AMETHYST_DUST) - .define('2', Items.AMETHYST_SHARD) - .define('3', HexItems.CHARGED_AMETHYST) - .pattern("LPL") - .pattern("123") - .pattern("LPL") - .unlockedBy("enlightenment", enlightenment).save(recipes); - - new BrainsweepRecipeBuilder(StateIngredientHelper.of(Blocks.AMETHYST_BLOCK), - new VillagerIngredient(null, null, 3), - Blocks.BUDDING_AMETHYST.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10) - .unlockedBy("enlightenment", enlightenment) - .save(recipes, modLoc("brainsweep/budding_amethyst")); - - new BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.IMPETUS_EMPTY), - new VillagerIngredient(VillagerProfession.TOOLSMITH, null, 2), - HexBlocks.IMPETUS_RIGHTCLICK.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10) - .unlockedBy("enlightenment", enlightenment) - .save(recipes, modLoc("brainsweep/impetus_rightclick")); - - new BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.IMPETUS_EMPTY), - new VillagerIngredient(VillagerProfession.FLETCHER, null, 2), - HexBlocks.IMPETUS_LOOK.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10) - .unlockedBy("enlightenment", enlightenment) - .save(recipes, modLoc("brainsweep/impetus_look")); - - new BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.IMPETUS_EMPTY), - new VillagerIngredient(VillagerProfession.CLERIC, null, 2), - HexBlocks.IMPETUS_REDSTONE.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10) - .unlockedBy("enlightenment", enlightenment) - .save(recipes, modLoc("brainsweep/impetus_storedplayer")); - - new BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.EMPTY_DIRECTRIX), - new VillagerIngredient(VillagerProfession.MASON, null, 1), - HexBlocks.DIRECTRIX_REDSTONE.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10) - .unlockedBy("enlightenment", enlightenment) - .save(recipes, modLoc("brainsweep/directrix_redstone")); - - new BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.EMPTY_DIRECTRIX), - new VillagerIngredient(VillagerProfession.SHEPHERD, null, 1), - HexBlocks.DIRECTRIX_BOOLEAN.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10) - .unlockedBy("enlightenment", enlightenment) - .save(recipes, modLoc("brainsweep/directrix_boolean")); - - new BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.AKASHIC_LIGATURE), - new VillagerIngredient(VillagerProfession.LIBRARIAN, null, 5), - HexBlocks.AKASHIC_RECORD.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10) - .unlockedBy("enlightenment", enlightenment) - .save(recipes, modLoc("brainsweep/akashic_record")); - - // Temporary tests - new BrainsweepRecipeBuilder(StateIngredientHelper.of(Blocks.AMETHYST_BLOCK), - new EntityTypeIngredient(EntityType.ALLAY), - HexBlocks.QUENCHED_ALLAY.defaultBlockState(), MediaConstants.CRYSTAL_UNIT) - .unlockedBy("enlightenment", enlightenment) - .save(recipes, modLoc("brainsweep/quench_allay")); - - // Create compat - this.conditions.apply(new CreateCrushingRecipeBuilder() - .withInput(Blocks.AMETHYST_CLUSTER) - .duration(150) - .withOutput(Items.AMETHYST_SHARD, 7) - .withOutput(HexItems.AMETHYST_DUST, 5) - .withOutput(0.25f, HexItems.CHARGED_AMETHYST)) - .whenModLoaded("create") - .save(recipes, new ResourceLocation("create", "crushing/amethyst_cluster")); - - this.conditions.apply(new CreateCrushingRecipeBuilder() - .withInput(Blocks.AMETHYST_BLOCK) - .duration(150) - .withOutput(Items.AMETHYST_SHARD, 3) - .withOutput(0.5f, HexItems.AMETHYST_DUST, 4)) - .whenModLoaded("create") - .save(recipes, new ResourceLocation("create", "crushing/amethyst_block")); - - this.conditions.apply(new CreateCrushingRecipeBuilder() - .withInput(Items.AMETHYST_SHARD) - .duration(150) - .withOutput(HexItems.AMETHYST_DUST, 4) - .withOutput(0.5f, HexItems.AMETHYST_DUST)) - .whenModLoaded("create") - .save(recipes, modLoc("compat/create/crushing/amethyst_shard")); - - // FD compat - for (var log : EDIFIED_LOGS) { - this.conditions.apply(new FarmersDelightCuttingRecipeBuilder() - .withInput(log) - .withTool(ingredients.axeStrip()) - .withOutput(HexBlocks.STRIPPED_EDIFIED_LOG) - .withOutput("farmersdelight:tree_bark") - .withSound(SoundEvents.AXE_STRIP)) - .whenModLoaded("farmersdelight") - .save(recipes, modLoc("compat/farmersdelight/cutting/" + BuiltInRegistries.BLOCK.getKey(log).getPath())); - } - - this.conditions.apply(new FarmersDelightCuttingRecipeBuilder() - .withInput(HexBlocks.EDIFIED_WOOD) - .withTool(ingredients.axeStrip()) - .withOutput(HexBlocks.STRIPPED_EDIFIED_WOOD) - .withOutput("farmersdelight:tree_bark") - .withSound(SoundEvents.AXE_STRIP)) - .whenModLoaded("farmersdelight") - .save(recipes, modLoc("compat/farmersdelight/cutting/akashic_wood")); - - this.conditions.apply(new FarmersDelightCuttingRecipeBuilder() - .withInput(HexBlocks.EDIFIED_TRAPDOOR) - .withTool(ingredients.axeDig()) - .withOutput(HexBlocks.EDIFIED_PLANKS)) - .whenModLoaded("farmersdelight") - .save(recipes, modLoc("compat/farmersdelight/cutting/akashic_trapdoor")); - - this.conditions.apply(new FarmersDelightCuttingRecipeBuilder() - .withInput(HexBlocks.EDIFIED_DOOR) - .withTool(ingredients.axeDig()) - .withOutput(HexBlocks.EDIFIED_PLANKS)) - .whenModLoaded("farmersdelight") - .save(recipes, modLoc("compat/farmersdelight/cutting/akashic_door")); - } - - private void staffRecipe(Consumer<FinishedRecipe> recipes, ItemStaff staff, Item plank) { - staffRecipe(recipes, staff, Ingredient.of(plank)); - } - - private void staffRecipe(Consumer<FinishedRecipe> recipes, ItemStaff staff, Ingredient plank) { - ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, staff) - .define('W', plank) - .define('S', Items.STICK) - .define('A', HexItems.CHARGED_AMETHYST) - .pattern(" SA") - .pattern(" WS") - .pattern("S ") - .unlockedBy("has_item", hasItem(HexItems.CHARGED_AMETHYST)) - .save(recipes); - } - - private void gayRecipe(Consumer<FinishedRecipe> recipes, ItemPridePigment.Type type, Ingredient material) { - var colorizer = HexItems.PRIDE_PIGMENTS.get(type); - ShapedRecipeBuilder.shaped(RecipeCategory.MISC, colorizer) - .define('D', HexItems.AMETHYST_DUST) - .define('C', material) - .pattern(" D ") - .pattern("DCD") - .pattern(" D ") - .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)) - .save(recipes); - } - - private void specialRecipe(Consumer<FinishedRecipe> consumer, SimpleCraftingRecipeSerializer<?> serializer) { - var name = BuiltInRegistries.RECIPE_SERIALIZER.getKey(serializer); - SpecialRecipeBuilder.special(serializer).save(consumer, HexAPI.MOD_ID + ":dynamic" + name.getPath()); - } + private final IXplatIngredients ingredients; + private final Function<RecipeBuilder, IXplatConditionsBuilder> conditions; + + private final List<BlockAkashicLog> EDIFIED_LOGS = + List.of( + HexBlocks.EDIFIED_LOG, + HexBlocks.EDIFIED_LOG_AMETHYST, + HexBlocks.EDIFIED_LOG_AVENTURINE, + HexBlocks.EDIFIED_LOG_CITRINE, + HexBlocks.EDIFIED_LOG_PURPLE); + + private final Map<BlockAkashicLog, BlockAkashicLog> EDIFIED_LOG_TO_WOOD = + Map.ofEntries( + Map.entry(HexBlocks.EDIFIED_LOG, HexBlocks.EDIFIED_WOOD), + // These don't exist, idk if they should + // Map.entry(HexBlocks.EDIFIED_LOG_AMETHYST, HexBlocks.EDIFIED_WOOD_AMETHYST), + // Map.entry(HexBlocks.EDIFIED_LOG_AVENTURINE, HexBlocks.EDIFIED_WOOD_AVENTURINE), + // Map.entry(HexBlocks.EDIFIED_LOG_CITRINE, HexBlocks.EDIFIED_WOOD_CITRINE), + // Map.entry(HexBlocks.EDIFIED_LOG_PURPLE, HexBlocks.EDIFIED_WOOD_PURPLE), + Map.entry(HexBlocks.STRIPPED_EDIFIED_LOG, HexBlocks.STRIPPED_EDIFIED_WOOD)); + + public HexplatRecipes( + PackOutput output, + IXplatIngredients ingredients, + Function<RecipeBuilder, IXplatConditionsBuilder> conditions) { + super(output, HexAPI.MOD_ID); + this.ingredients = ingredients; + this.conditions = conditions; + } + + @Override + public void buildRecipes(Consumer<FinishedRecipe> recipes) { + specialRecipe(recipes, SealThingsRecipe.FOCUS_SERIALIZER); + specialRecipe(recipes, SealThingsRecipe.SPELLBOOK_SERIALIZER); + + staffRecipe(recipes, HexItems.STAFF_OAK, Items.OAK_PLANKS); + staffRecipe(recipes, HexItems.STAFF_BIRCH, Items.BIRCH_PLANKS); + staffRecipe(recipes, HexItems.STAFF_SPRUCE, Items.SPRUCE_PLANKS); + staffRecipe(recipes, HexItems.STAFF_JUNGLE, Items.JUNGLE_PLANKS); + staffRecipe(recipes, HexItems.STAFF_DARK_OAK, Items.DARK_OAK_PLANKS); + staffRecipe(recipes, HexItems.STAFF_ACACIA, Items.ACACIA_PLANKS); + staffRecipe(recipes, HexItems.STAFF_CRIMSON, Items.CRIMSON_PLANKS); + staffRecipe(recipes, HexItems.STAFF_WARPED, Items.WARPED_PLANKS); + staffRecipe(recipes, HexItems.STAFF_MANGROVE, Items.MANGROVE_PLANKS); + staffRecipe(recipes, HexItems.STAFF_CHERRY, Items.CHERRY_PLANKS); + staffRecipe(recipes, HexItems.STAFF_BAMBOO, Items.BAMBOO_PLANKS); + staffRecipe(recipes, HexItems.STAFF_EDIFIED, HexBlocks.EDIFIED_PLANKS.asItem()); + staffRecipe(recipes, HexItems.STAFF_QUENCHED, HexItems.QUENCHED_SHARD); + staffRecipe( + recipes, + HexItems.STAFF_MINDSPLICE, + Ingredient.of(HexTags.Items.MINDFLAYED_CIRCLE_COMPONENTS)); + + ShapelessRecipeBuilder.shapeless(RecipeCategory.TOOLS, HexItems.THOUGHT_KNOT) + .requires(HexItems.AMETHYST_DUST) + .requires(Items.STRING) + .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)) + .save(recipes); + ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, HexItems.FOCUS) + .define('G', ingredients.glowstoneDust()) + .define('L', ingredients.leather()) + .define('P', Items.PAPER) + .define('A', HexItems.CHARGED_AMETHYST) + .pattern("GLG") + .pattern("PAP") + .pattern("GLG") + .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)) + .save(recipes); + ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, HexItems.FOCUS) + .define('G', ingredients.glowstoneDust()) + .define('L', ingredients.leather()) + .define('P', Items.PAPER) + .define('A', HexItems.CHARGED_AMETHYST) + .pattern("GPG") + .pattern("LAL") + .pattern("GPG") + .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)) + .save(recipes, modLoc("focus_rotated")); + + ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, HexItems.SPELLBOOK) + .define('N', ingredients.goldNugget()) + .define('B', Items.WRITABLE_BOOK) + .define('A', HexItems.CHARGED_AMETHYST) + .define('F', Items.CHORUS_FRUIT) // i wanna gate this behind the end SOMEHOW + // hey look its my gender ^^ + .pattern("NBA") + .pattern("NFA") + .pattern("NBA") + .unlockedBy("has_focus", hasItem(HexItems.FOCUS)) + .unlockedBy("has_chorus", hasItem(Items.CHORUS_FRUIT)) + .save(recipes); + + ringCornerless( + RecipeCategory.TOOLS, + HexItems.CYPHER, + 1, + ingredients.copperIngot(), + Ingredient.of(HexItems.AMETHYST_DUST)) + .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)) + .save(recipes); + + ringCornerless( + RecipeCategory.TOOLS, + HexItems.TRINKET, + 1, + ingredients.ironIngot(), + Ingredient.of(Items.AMETHYST_SHARD)) + .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, HexItems.ARTIFACT) + .define('F', ingredients.goldIngot()) + .define('A', HexItems.CHARGED_AMETHYST) + // why in god's name does minecraft have two different places for item tags + .define('D', ItemTags.MUSIC_DISCS) + .pattern(" F ") + .pattern("FAF") + .pattern(" D ") + .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)) + .save(recipes); + + ringCornerless( + RecipeCategory.TOOLS, HexItems.SCRYING_LENS, 1, Items.GLASS, HexItems.AMETHYST_DUST) + .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, HexItems.ABACUS) + .define('S', Items.STICK) + .define('A', Items.AMETHYST_SHARD) + .define('W', ItemTags.PLANKS) + .pattern("WAW") + .pattern("SAS") + .pattern("WAW") + .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)) + .save(recipes); + + // Why am I like this + ShapedRecipeBuilder.shaped(RecipeCategory.FOOD, HexItems.SUBMARINE_SANDWICH) + .define('S', Items.STICK) + .define('A', Items.AMETHYST_SHARD) + .define('C', Items.COOKED_BEEF) + .define('B', Items.BREAD) + .pattern(" SA") + .pattern(" C ") + .pattern(" B ") + .unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)) + .save(recipes); + + for (var dye : DyeColor.values()) { + var item = HexItems.DYE_PIGMENTS.get(dye); + ShapedRecipeBuilder.shaped(RecipeCategory.MISC, item) + .define('D', HexItems.AMETHYST_DUST) + .define('C', DyeItem.byColor(dye)) + .pattern(" D ") + .pattern("DCD") + .pattern(" D ") + .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)) + .save(recipes); + } + + gayRecipe(recipes, ItemPridePigment.Type.AGENDER, Ingredient.of(Items.GLASS)); + gayRecipe(recipes, ItemPridePigment.Type.AROACE, Ingredient.of(Items.WHEAT_SEEDS)); + gayRecipe(recipes, ItemPridePigment.Type.AROMANTIC, Ingredient.of(Items.ARROW)); + gayRecipe(recipes, ItemPridePigment.Type.ASEXUAL, Ingredient.of(Items.BREAD)); + gayRecipe(recipes, ItemPridePigment.Type.BISEXUAL, Ingredient.of(Items.WHEAT)); + gayRecipe(recipes, ItemPridePigment.Type.DEMIBOY, Ingredient.of(Items.RAW_IRON)); + gayRecipe(recipes, ItemPridePigment.Type.DEMIGIRL, Ingredient.of(Items.RAW_COPPER)); + gayRecipe(recipes, ItemPridePigment.Type.GAY, Ingredient.of(Items.STONE_BRICK_WALL)); + gayRecipe(recipes, ItemPridePigment.Type.GENDERFLUID, Ingredient.of(Items.WATER_BUCKET)); + gayRecipe(recipes, ItemPridePigment.Type.GENDERQUEER, Ingredient.of(Items.GLASS_BOTTLE)); + gayRecipe(recipes, ItemPridePigment.Type.INTERSEX, Ingredient.of(Items.AZALEA)); + gayRecipe(recipes, ItemPridePigment.Type.LESBIAN, Ingredient.of(Items.HONEYCOMB)); + gayRecipe(recipes, ItemPridePigment.Type.NONBINARY, Ingredient.of(Items.MOSS_BLOCK)); + gayRecipe( + recipes, + ItemPridePigment.Type.PANSEXUAL, + ingredients.whenModIngredient( + Ingredient.of(Items.CARROT), + "farmersdelight", + CompatIngredientValue.of("farmersdelight:skillet"))); + gayRecipe(recipes, ItemPridePigment.Type.PLURAL, Ingredient.of(Items.REPEATER)); + gayRecipe(recipes, ItemPridePigment.Type.TRANSGENDER, Ingredient.of(Items.EGG)); + + ring( + RecipeCategory.MISC, + HexItems.UUID_PIGMENT, + 1, + HexItems.AMETHYST_DUST, + Items.AMETHYST_SHARD) + .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)) + .save(recipes); + ring( + RecipeCategory.MISC, + HexItems.DEFAULT_PIGMENT, + 1, + HexItems.AMETHYST_DUST, + Items.COPPER_INGOT) + .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, HexItems.SCROLL_SMOL) + .define('P', Items.PAPER) + .define('A', HexItems.AMETHYST_DUST) + .pattern(" A") + .pattern("P ") + .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, HexItems.SCROLL_MEDIUM) + .define('P', Items.PAPER) + .define('A', HexItems.AMETHYST_DUST) + .pattern(" A") + .pattern("PP ") + .pattern("PP ") + .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, HexItems.SCROLL_LARGE) + .define('P', Items.PAPER) + .define('A', HexItems.AMETHYST_DUST) + .pattern("PPA") + .pattern("PPP") + .pattern("PPP") + .unlockedBy("has_item", hasItem(HexTags.Items.STAVES)) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, HexItems.SLATE, 6) + .define('S', Items.DEEPSLATE) + .define('A', HexItems.AMETHYST_DUST) + .pattern(" A ") + .pattern("SSS") + .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, HexItems.JEWELER_HAMMER) + .define('I', ingredients.ironIngot()) + .define('N', ingredients.ironNugget()) + .define('A', Items.AMETHYST_SHARD) + .define('S', ingredients.stick()) + .pattern("IAN") + .pattern(" S ") + .pattern(" S ") + .unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)) + .save(recipes); + + ShapelessRecipeBuilder.shapeless( + RecipeCategory.MISC, + HexItems.AMETHYST_DUST, + (int) (MediaConstants.QUENCHED_SHARD_UNIT / MediaConstants.DUST_UNIT) + 1) + .requires(HexItems.QUENCHED_SHARD) + .requires(HexItems.AMETHYST_DUST) + .unlockedBy("has_item", hasItem(HexItems.QUENCHED_SHARD)) + .save(recipes, modLoc("decompose_quenched_shard/dust")); + ShapelessRecipeBuilder.shapeless( + RecipeCategory.MISC, + Items.AMETHYST_SHARD, + (int) (MediaConstants.QUENCHED_SHARD_UNIT / MediaConstants.SHARD_UNIT) + 1) + .requires(HexItems.QUENCHED_SHARD) + .requires(Items.AMETHYST_SHARD) + .unlockedBy("has_item", hasItem(HexItems.QUENCHED_SHARD)) + .save(recipes, modLoc("decompose_quenched_shard/shard")); + ShapelessRecipeBuilder.shapeless( + RecipeCategory.MISC, + HexItems.CHARGED_AMETHYST, + (int) (MediaConstants.QUENCHED_SHARD_UNIT / MediaConstants.CRYSTAL_UNIT) + 1) + .requires(HexItems.QUENCHED_SHARD) + .requires(HexItems.CHARGED_AMETHYST) + .unlockedBy("has_item", hasItem(HexItems.QUENCHED_SHARD)) + .save(recipes, modLoc("decompose_quenched_shard/charged")); + + ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, HexBlocks.SLATE_BLOCK) + .define('S', HexItems.SLATE) + .pattern("S") + .pattern("S") + .unlockedBy("has_item", hasItem(HexItems.SLATE)) + .save(recipes, modLoc("slate_block_from_slates")); + + ringAll( + RecipeCategory.BUILDING_BLOCKS, + HexBlocks.SLATE_BLOCK, + 8, + Blocks.DEEPSLATE, + HexItems.AMETHYST_DUST) + .unlockedBy("has_item", hasItem(HexItems.SLATE)) + .save(recipes); + + packing( + RecipeCategory.BUILDING_BLOCKS, + HexItems.AMETHYST_DUST, + HexBlocks.AMETHYST_DUST_BLOCK.asItem(), + "amethyst_dust", + false, + recipes); + + ringAll( + RecipeCategory.BUILDING_BLOCKS, + HexBlocks.AMETHYST_TILES, + 8, + Blocks.AMETHYST_BLOCK, + HexItems.AMETHYST_DUST) + .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)) + .save(recipes); + + SingleItemRecipeBuilder.stonecutting( + Ingredient.of(Blocks.AMETHYST_BLOCK), + RecipeCategory.BUILDING_BLOCKS, + HexBlocks.AMETHYST_TILES) + .unlockedBy("has_item", hasItem(Blocks.AMETHYST_BLOCK)) + .save(recipes, modLoc("stonecutting/amethyst_tiles")); + + ringAll( + RecipeCategory.BUILDING_BLOCKS, + HexBlocks.SCROLL_PAPER, + 8, + Items.PAPER, + Items.AMETHYST_SHARD) + .unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)) + .save(recipes); + + ShapelessRecipeBuilder.shapeless( + RecipeCategory.BUILDING_BLOCKS, HexBlocks.ANCIENT_SCROLL_PAPER, 8) + .requires(ingredients.dyes().get(DyeColor.BROWN)) + .requires(HexBlocks.SCROLL_PAPER, 8) + .unlockedBy("has_item", hasItem(HexBlocks.SCROLL_PAPER)) + .save(recipes); + + stack( + RecipeCategory.DECORATIONS, + HexBlocks.SCROLL_PAPER_LANTERN, + 1, + HexBlocks.SCROLL_PAPER, + Items.TORCH) + .unlockedBy("has_item", hasItem(HexBlocks.SCROLL_PAPER)) + .save(recipes); + + stack( + RecipeCategory.DECORATIONS, + HexBlocks.ANCIENT_SCROLL_PAPER_LANTERN, + 1, + HexBlocks.ANCIENT_SCROLL_PAPER, + Items.TORCH) + .unlockedBy("has_item", hasItem(HexBlocks.ANCIENT_SCROLL_PAPER)) + .save(recipes); + + ShapelessRecipeBuilder.shapeless( + RecipeCategory.DECORATIONS, HexBlocks.ANCIENT_SCROLL_PAPER_LANTERN, 8) + .requires(ingredients.dyes().get(DyeColor.BROWN)) + .requires(HexBlocks.SCROLL_PAPER_LANTERN, 8) + .unlockedBy("has_item", hasItem(HexBlocks.SCROLL_PAPER_LANTERN)) + .save(recipes, modLoc("ageing_scroll_paper_lantern")); + + stack( + RecipeCategory.DECORATIONS, + HexBlocks.SCONCE, + 4, + Ingredient.of(HexItems.CHARGED_AMETHYST), + ingredients.copperIngot()) + .unlockedBy("has_item", hasItem(HexItems.CHARGED_AMETHYST)) + .save(recipes); + + ShapelessRecipeBuilder.shapeless(RecipeCategory.BUILDING_BLOCKS, HexBlocks.EDIFIED_PLANKS, 4) + .requires(HexTags.Items.EDIFIED_LOGS) + .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_LOGS)) + .save(recipes); + + for (var entry : EDIFIED_LOG_TO_WOOD.entrySet()) { + var log = entry.getKey(); + var wood = entry.getValue(); + ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, wood, 3) + .define('W', log) + .pattern("WW") + .pattern("WW") + .unlockedBy("has_item", hasItem(log)) + .save(recipes); + } + + ring( + RecipeCategory.BUILDING_BLOCKS, + HexBlocks.EDIFIED_PANEL, + 8, + HexTags.Items.EDIFIED_PLANKS, + null) + .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, HexBlocks.EDIFIED_TILE, 6) + .define('W', HexTags.Items.EDIFIED_PLANKS) + .pattern("WW ") + .pattern("W W") + .pattern(" WW") + .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.REDSTONE, HexBlocks.EDIFIED_DOOR, 3) + .define('W', HexTags.Items.EDIFIED_PLANKS) + .pattern("WW") + .pattern("WW") + .pattern("WW") + .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.REDSTONE, HexBlocks.EDIFIED_TRAPDOOR, 2) + .define('W', HexTags.Items.EDIFIED_PLANKS) + .pattern("WWW") + .pattern("WWW") + .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, HexBlocks.EDIFIED_STAIRS, 4) + .define('W', HexTags.Items.EDIFIED_PLANKS) + .pattern("W ") + .pattern("WW ") + .pattern("WWW") + .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, HexBlocks.EDIFIED_FENCE, 3) + .define('W', HexTags.Items.EDIFIED_PLANKS) + .define('S', Items.STICK) + .pattern("WSW") + .pattern("WSW") + .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, HexBlocks.EDIFIED_FENCE_GATE, 1) + .define('W', HexTags.Items.EDIFIED_PLANKS) + .define('S', Items.STICK) + .pattern("SWS") + .pattern("SWS") + .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, HexBlocks.EDIFIED_SLAB, 6) + .define('W', HexTags.Items.EDIFIED_PLANKS) + .pattern("WWW") + .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.REDSTONE, HexBlocks.EDIFIED_PRESSURE_PLATE, 1) + .define('W', HexTags.Items.EDIFIED_PLANKS) + .pattern("WW") + .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)) + .save(recipes); + + ShapelessRecipeBuilder.shapeless(RecipeCategory.REDSTONE, HexBlocks.EDIFIED_BUTTON) + .requires(HexTags.Items.EDIFIED_PLANKS) + .unlockedBy("has_item", hasItem(HexTags.Items.EDIFIED_PLANKS)) + .save(recipes); + + var enlightenment = HexAdvancements.ENLIGHTEN; + ShapedRecipeBuilder.shaped(RecipeCategory.REDSTONE, HexBlocks.IMPETUS_EMPTY) + .define('B', Items.IRON_BARS) + .define('A', HexItems.CHARGED_AMETHYST) + .define('S', HexBlocks.SLATE_BLOCK) + .define('P', Items.PURPUR_BLOCK) + .pattern("PSS") + .pattern("BAB") + .pattern("SSP") + .unlockedBy("enlightenment", enlightenment) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.REDSTONE, HexBlocks.EMPTY_DIRECTRIX) + .define('C', Items.COMPARATOR) + .define('O', Items.OBSERVER) + .define('A', HexItems.CHARGED_AMETHYST) + .define('S', HexBlocks.SLATE_BLOCK) + .pattern("CSS") + .pattern("OAO") + .pattern("SSC") + .unlockedBy("enlightenment", enlightenment) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.REDSTONE, HexBlocks.AKASHIC_BOOKSHELF) + .define('L', HexTags.Items.EDIFIED_LOGS) + .define('P', HexTags.Items.EDIFIED_PLANKS) + .define('C', Items.BOOK) + /*this is the*/ .pattern("LPL") // and what i have for you today is + .pattern("CCC") + .pattern("LPL") + .unlockedBy("enlightenment", enlightenment) + .save(recipes); + + ShapedRecipeBuilder.shaped(RecipeCategory.REDSTONE, HexBlocks.AKASHIC_LIGATURE, 4) + .define('L', HexTags.Items.EDIFIED_LOGS) + .define('P', HexTags.Items.EDIFIED_PLANKS) + .define('1', HexItems.AMETHYST_DUST) + .define('2', Items.AMETHYST_SHARD) + .define('3', HexItems.CHARGED_AMETHYST) + .pattern("LPL") + .pattern("123") + .pattern("LPL") + .unlockedBy("enlightenment", enlightenment) + .save(recipes); + + new BrainsweepRecipeBuilder( + StateIngredientHelper.of(Blocks.AMETHYST_BLOCK), + new VillagerIngredient(null, null, 3), + Blocks.BUDDING_AMETHYST.defaultBlockState(), + MediaConstants.CRYSTAL_UNIT * 10) + .unlockedBy("enlightenment", enlightenment) + .save(recipes, modLoc("brainsweep/budding_amethyst")); + + new BrainsweepRecipeBuilder( + StateIngredientHelper.of(HexBlocks.IMPETUS_EMPTY), + new VillagerIngredient(VillagerProfession.TOOLSMITH, null, 2), + HexBlocks.IMPETUS_RIGHTCLICK.defaultBlockState(), + MediaConstants.CRYSTAL_UNIT * 10) + .unlockedBy("enlightenment", enlightenment) + .save(recipes, modLoc("brainsweep/impetus_rightclick")); + + new BrainsweepRecipeBuilder( + StateIngredientHelper.of(HexBlocks.IMPETUS_EMPTY), + new VillagerIngredient(VillagerProfession.FLETCHER, null, 2), + HexBlocks.IMPETUS_LOOK.defaultBlockState(), + MediaConstants.CRYSTAL_UNIT * 10) + .unlockedBy("enlightenment", enlightenment) + .save(recipes, modLoc("brainsweep/impetus_look")); + + new BrainsweepRecipeBuilder( + StateIngredientHelper.of(HexBlocks.IMPETUS_EMPTY), + new VillagerIngredient(VillagerProfession.CLERIC, null, 2), + HexBlocks.IMPETUS_REDSTONE.defaultBlockState(), + MediaConstants.CRYSTAL_UNIT * 10) + .unlockedBy("enlightenment", enlightenment) + .save(recipes, modLoc("brainsweep/impetus_storedplayer")); + + new BrainsweepRecipeBuilder( + StateIngredientHelper.of(HexBlocks.EMPTY_DIRECTRIX), + new VillagerIngredient(VillagerProfession.MASON, null, 1), + HexBlocks.DIRECTRIX_REDSTONE.defaultBlockState(), + MediaConstants.CRYSTAL_UNIT * 10) + .unlockedBy("enlightenment", enlightenment) + .save(recipes, modLoc("brainsweep/directrix_redstone")); + + new BrainsweepRecipeBuilder( + StateIngredientHelper.of(HexBlocks.EMPTY_DIRECTRIX), + new VillagerIngredient(VillagerProfession.SHEPHERD, null, 1), + HexBlocks.DIRECTRIX_BOOLEAN.defaultBlockState(), + MediaConstants.CRYSTAL_UNIT * 10) + .unlockedBy("enlightenment", enlightenment) + .save(recipes, modLoc("brainsweep/directrix_boolean")); + + new BrainsweepRecipeBuilder( + StateIngredientHelper.of(HexBlocks.AKASHIC_LIGATURE), + new VillagerIngredient(VillagerProfession.LIBRARIAN, null, 5), + HexBlocks.AKASHIC_RECORD.defaultBlockState(), + MediaConstants.CRYSTAL_UNIT * 10) + .unlockedBy("enlightenment", enlightenment) + .save(recipes, modLoc("brainsweep/akashic_record")); + + // Temporary tests + new BrainsweepRecipeBuilder( + StateIngredientHelper.of(Blocks.AMETHYST_BLOCK), + new EntityTypeIngredient(EntityType.ALLAY), + HexBlocks.QUENCHED_ALLAY.defaultBlockState(), + MediaConstants.CRYSTAL_UNIT) + .unlockedBy("enlightenment", enlightenment) + .save(recipes, modLoc("brainsweep/quench_allay")); + + // Create compat + this.conditions + .apply( + new CreateCrushingRecipeBuilder() + .withInput(Blocks.AMETHYST_CLUSTER) + .duration(150) + .withOutput(Items.AMETHYST_SHARD, 7) + .withOutput(HexItems.AMETHYST_DUST, 5) + .withOutput(0.25f, HexItems.CHARGED_AMETHYST)) + .whenModLoaded("create") + .save(recipes, new ResourceLocation("create", "crushing/amethyst_cluster")); + + this.conditions + .apply( + new CreateCrushingRecipeBuilder() + .withInput(Blocks.AMETHYST_BLOCK) + .duration(150) + .withOutput(Items.AMETHYST_SHARD, 3) + .withOutput(0.5f, HexItems.AMETHYST_DUST, 4)) + .whenModLoaded("create") + .save(recipes, new ResourceLocation("create", "crushing/amethyst_block")); + + this.conditions + .apply( + new CreateCrushingRecipeBuilder() + .withInput(Items.AMETHYST_SHARD) + .duration(150) + .withOutput(HexItems.AMETHYST_DUST, 4) + .withOutput(0.5f, HexItems.AMETHYST_DUST)) + .whenModLoaded("create") + .save(recipes, modLoc("compat/create/crushing/amethyst_shard")); + + // FD compat + for (var log : EDIFIED_LOGS) { + this.conditions + .apply( + new FarmersDelightCuttingRecipeBuilder() + .withInput(log) + .withTool(ingredients.axeStrip()) + .withOutput(HexBlocks.STRIPPED_EDIFIED_LOG) + .withOutput("farmersdelight:tree_bark") + .withSound(SoundEvents.AXE_STRIP)) + .whenModLoaded("farmersdelight") + .save( + recipes, + modLoc( + "compat/farmersdelight/cutting/" + + BuiltInRegistries.BLOCK.getKey(log).getPath())); + } + + this.conditions + .apply( + new FarmersDelightCuttingRecipeBuilder() + .withInput(HexBlocks.EDIFIED_WOOD) + .withTool(ingredients.axeStrip()) + .withOutput(HexBlocks.STRIPPED_EDIFIED_WOOD) + .withOutput("farmersdelight:tree_bark") + .withSound(SoundEvents.AXE_STRIP)) + .whenModLoaded("farmersdelight") + .save(recipes, modLoc("compat/farmersdelight/cutting/akashic_wood")); + + this.conditions + .apply( + new FarmersDelightCuttingRecipeBuilder() + .withInput(HexBlocks.EDIFIED_TRAPDOOR) + .withTool(ingredients.axeDig()) + .withOutput(HexBlocks.EDIFIED_PLANKS)) + .whenModLoaded("farmersdelight") + .save(recipes, modLoc("compat/farmersdelight/cutting/akashic_trapdoor")); + + this.conditions + .apply( + new FarmersDelightCuttingRecipeBuilder() + .withInput(HexBlocks.EDIFIED_DOOR) + .withTool(ingredients.axeDig()) + .withOutput(HexBlocks.EDIFIED_PLANKS)) + .whenModLoaded("farmersdelight") + .save(recipes, modLoc("compat/farmersdelight/cutting/akashic_door")); + } + + private void staffRecipe(Consumer<FinishedRecipe> recipes, ItemStaff staff, Item plank) { + staffRecipe(recipes, staff, Ingredient.of(plank)); + } + + private void staffRecipe(Consumer<FinishedRecipe> recipes, ItemStaff staff, Ingredient plank) { + ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, staff) + .define('W', plank) + .define('S', Items.STICK) + .define('A', HexItems.CHARGED_AMETHYST) + .pattern(" SA") + .pattern(" WS") + .pattern("S ") + .unlockedBy("has_item", hasItem(HexItems.CHARGED_AMETHYST)) + .save(recipes); + } + + private void gayRecipe( + Consumer<FinishedRecipe> recipes, ItemPridePigment.Type type, Ingredient material) { + var colorizer = HexItems.PRIDE_PIGMENTS.get(type); + ShapedRecipeBuilder.shaped(RecipeCategory.MISC, colorizer) + .define('D', HexItems.AMETHYST_DUST) + .define('C', material) + .pattern(" D ") + .pattern("DCD") + .pattern(" D ") + .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)) + .save(recipes); + } + + private void specialRecipe( + Consumer<FinishedRecipe> consumer, SimpleCraftingRecipeSerializer<?> serializer) { + var name = BuiltInRegistries.RECIPE_SERIALIZER.getKey(serializer); + SpecialRecipeBuilder.special(serializer) + .save(consumer, HexAPI.MOD_ID + ":dynamic" + name.getPath()); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/BrainsweepRecipeBuilder.java b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/BrainsweepRecipeBuilder.java index 09465dfd03..d656575f6c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/BrainsweepRecipeBuilder.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/BrainsweepRecipeBuilder.java @@ -5,6 +5,7 @@ import at.petrak.hexcasting.common.recipe.ingredient.StateIngredientHelper; import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.BrainsweepeeIngredient; import com.google.gson.JsonObject; +import java.util.function.Consumer; import net.minecraft.advancements.Advancement; import net.minecraft.advancements.AdvancementRewards; import net.minecraft.advancements.CriterionTriggerInstance; @@ -18,8 +19,6 @@ import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.Nullable; -import java.util.function.Consumer; - public class BrainsweepRecipeBuilder implements RecipeBuilder { private final StateIngredient blockIn; private final BrainsweepeeIngredient entityIn; @@ -28,8 +27,8 @@ public class BrainsweepRecipeBuilder implements RecipeBuilder { private final Advancement.Builder advancement; - public BrainsweepRecipeBuilder(StateIngredient blockIn, BrainsweepeeIngredient entityIn, BlockState result, - long mediaCost) { + public BrainsweepRecipeBuilder( + StateIngredient blockIn, BrainsweepeeIngredient entityIn, BlockState result, long mediaCost) { this.blockIn = blockIn; this.entityIn = entityIn; this.result = result; @@ -38,7 +37,8 @@ public BrainsweepRecipeBuilder(StateIngredient blockIn, BrainsweepeeIngredient e } @Override - public RecipeBuilder unlockedBy(String pCriterionName, CriterionTriggerInstance pCriterionTrigger) { + public RecipeBuilder unlockedBy( + String pCriterionName, CriterionTriggerInstance pCriterionTrigger) { this.advancement.addCriterion(pCriterionName, pCriterionTrigger); return this; } @@ -59,20 +59,32 @@ public void save(Consumer<FinishedRecipe> pFinishedRecipeConsumer, ResourceLocat throw new IllegalStateException("No way of obtaining recipe " + pRecipeId); } - this.advancement.parent(new ResourceLocation("recipes/root")) - .addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(pRecipeId)) - .rewards(AdvancementRewards.Builder.recipe(pRecipeId)) - .requirements(RequirementsStrategy.OR); - pFinishedRecipeConsumer.accept(new Result( - pRecipeId, - this.blockIn, this.entityIn, this.mediaCost, this.result, - this.advancement, - new ResourceLocation(pRecipeId.getNamespace(), "recipes/brainsweep/" + pRecipeId.getPath()))); + this.advancement + .parent(new ResourceLocation("recipes/root")) + .addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(pRecipeId)) + .rewards(AdvancementRewards.Builder.recipe(pRecipeId)) + .requirements(RequirementsStrategy.OR); + pFinishedRecipeConsumer.accept( + new Result( + pRecipeId, + this.blockIn, + this.entityIn, + this.mediaCost, + this.result, + this.advancement, + new ResourceLocation( + pRecipeId.getNamespace(), "recipes/brainsweep/" + pRecipeId.getPath()))); } - public record Result(ResourceLocation id, StateIngredient blockIn, BrainsweepeeIngredient villagerIn, - long mediaCost, BlockState result, Advancement.Builder advancement, - ResourceLocation advancementId) implements FinishedRecipe { + public record Result( + ResourceLocation id, + StateIngredient blockIn, + BrainsweepeeIngredient villagerIn, + long mediaCost, + BlockState result, + Advancement.Builder advancement, + ResourceLocation advancementId) + implements FinishedRecipe { @Override public void serializeRecipeData(JsonObject json) { json.add("blockIn", this.blockIn.serialize()); @@ -91,14 +103,12 @@ public RecipeSerializer<?> getType() { return HexRecipeStuffRegistry.BRAINSWEEP; } - @Nullable - @Override + @Nullable @Override public JsonObject serializeAdvancement() { return this.advancement.serializeToJson(); } - @Nullable - @Override + @Nullable @Override public ResourceLocation getAdvancementId() { return this.advancementId; } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/CompatIngredientValue.java b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/CompatIngredientValue.java index 3ff9575318..86e718f6d3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/CompatIngredientValue.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/CompatIngredientValue.java @@ -1,33 +1,31 @@ package at.petrak.hexcasting.datagen.recipe.builders; import com.google.gson.JsonObject; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Ingredient; -import org.jetbrains.annotations.NotNull; - import java.util.Collection; import java.util.Collections; import java.util.stream.Stream; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import org.jetbrains.annotations.NotNull; public class CompatIngredientValue implements Ingredient.Value { - public final String item; + public final String item; - public CompatIngredientValue(String name) { - this.item = name; - } + public CompatIngredientValue(String name) { + this.item = name; + } - public @NotNull Collection<ItemStack> getItems() { - return Collections.emptyList(); - } + public @NotNull Collection<ItemStack> getItems() { + return Collections.emptyList(); + } - public @NotNull JsonObject serialize() { - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("item", item); - return jsonObject; - } + public @NotNull JsonObject serialize() { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("item", item); + return jsonObject; + } - public static Ingredient of(String itemName) { - return new Ingredient(Stream.of(new CompatIngredientValue(itemName))); - } + public static Ingredient of(String itemName) { + return new Ingredient(Stream.of(new CompatIngredientValue(itemName))); + } } - diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/CompatProcessingOutput.java b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/CompatProcessingOutput.java index e4bf7e0c67..24283aacb7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/CompatProcessingOutput.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/CompatProcessingOutput.java @@ -2,17 +2,18 @@ import com.google.gson.JsonObject; -public record CompatProcessingOutput(String name, int count, float chance) implements ProcessingOutput { - @Override - public JsonObject serialize() { - JsonObject json = new JsonObject(); - json.addProperty("item", name); - if (count != 1) { - json.addProperty("count", count); - } - if (chance != 1) { - json.addProperty("chance", chance); - } - return json; - } +public record CompatProcessingOutput(String name, int count, float chance) + implements ProcessingOutput { + @Override + public JsonObject serialize() { + JsonObject json = new JsonObject(); + json.addProperty("item", name); + if (count != 1) { + json.addProperty("count", count); + } + if (chance != 1) { + json.addProperty("chance", chance); + } + return json; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/CreateCrushingRecipeBuilder.java b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/CreateCrushingRecipeBuilder.java index 77743d9a31..3c9a70ac07 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/CreateCrushingRecipeBuilder.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/CreateCrushingRecipeBuilder.java @@ -2,6 +2,9 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; import net.minecraft.advancements.CriterionTriggerInstance; import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.data.recipes.RecipeBuilder; @@ -15,149 +18,146 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - // Largely adapted from the following classes: // https://github.com/Creators-of-Create/Create/blob/82be76d8934af03b4e52cad6a9f74a4175ba7b05/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingOutput.java // https://github.com/Creators-of-Create/Create/blob/82be76d8934af03b4e52cad6a9f74a4175ba7b05/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java // https://github.com/Creators-of-Create/Create/blob/82be76d8934af03b4e52cad6a9f74a4175ba7b05/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingRecipeBuilder.java // https://github.com/Creators-of-Create/Create/blob/82be76d8934af03b4e52cad6a9f74a4175ba7b05/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingRecipeSerializer.java public class CreateCrushingRecipeBuilder implements RecipeBuilder { - private String group = ""; - private Ingredient input; - private final List<ProcessingOutput> results = new ArrayList<>(); - private int processingTime = 100; - - @Override - public @NotNull CreateCrushingRecipeBuilder unlockedBy(@NotNull String name, @NotNull CriterionTriggerInstance trigger) { - return this; - } - - @Override - public @NotNull CreateCrushingRecipeBuilder group(@Nullable String name) { - group = name; - return this; - } - - public CreateCrushingRecipeBuilder duration(int duration) { - this.processingTime = duration; - return this; - } - - public CreateCrushingRecipeBuilder withInput(ItemLike item) { - return withInput(Ingredient.of(item)); - } - - public CreateCrushingRecipeBuilder withInput(ItemStack stack) { - return withInput(Ingredient.of(stack)); - } - - public CreateCrushingRecipeBuilder withInput(Ingredient ingredient) { - this.input = ingredient; - return this; - } - - public CreateCrushingRecipeBuilder withOutput(ItemLike output) { - return withOutput(1f, output, 1); - } - - public CreateCrushingRecipeBuilder withOutput(float chance, ItemLike output) { - return withOutput(chance, output, 1); - } - - public CreateCrushingRecipeBuilder withOutput(ItemLike output, int count) { - return withOutput(1f, output, count); - } - - public CreateCrushingRecipeBuilder withOutput(float chance, ItemLike output, int count) { - return withOutput(new ItemStack(output, count), chance); - } - - public CreateCrushingRecipeBuilder withOutput(ItemStack output, float chance) { - this.results.add(new ItemProcessingOutput(output, chance)); - return this; - } - - public CreateCrushingRecipeBuilder withOutput(String name) { - return withOutput(1f, name, 1); - } - - public CreateCrushingRecipeBuilder withOutput(String name, int count) { - return withOutput(1f, name, count); - } - - public CreateCrushingRecipeBuilder withOutput(float chance, String name) { - return withOutput(chance, name, 1); - } - - public CreateCrushingRecipeBuilder withOutput(float chance, String name, int count) { - this.results.add(new CompatProcessingOutput(name, count, chance)); - return this; - } - - @Override - public @NotNull Item getResult() { - return Items.AIR; // Irrelevant, we implement serialization ourselves - } - - @Override - public void save(@NotNull Consumer<FinishedRecipe> consumer, @NotNull ResourceLocation resourceLocation) { - consumer.accept(new CrushingRecipe(resourceLocation)); - } - - public class CrushingRecipe implements FinishedRecipe { - - private final ResourceLocation id; - - public CrushingRecipe(ResourceLocation id) { - this.id = id; - } - - @Override - public void serializeRecipeData(@NotNull JsonObject json) { - json.addProperty("type", "create:crushing"); - - if (!group.isEmpty()) { - json.addProperty("group", group); - } - - JsonArray jsonIngredients = new JsonArray(); - JsonArray jsonOutputs = new JsonArray(); - - jsonIngredients.add(input.toJson()); - - results.forEach(o -> jsonOutputs.add(o.serialize())); - - json.add("ingredients", jsonIngredients); - json.add("results", jsonOutputs); - - int processingDuration = processingTime; - if (processingDuration > 0) { - json.addProperty("processingTime", processingDuration); - } - } - - @Override - public @NotNull ResourceLocation getId() { - return id; - } - - @Override - public @NotNull RecipeSerializer<?> getType() { - return RecipeSerializer.SHAPELESS_RECIPE; // Irrelevant, we implement serialization ourselves - } - - @Override - public JsonObject serializeAdvancement() { - return null; - } + private String group = ""; + private Ingredient input; + private final List<ProcessingOutput> results = new ArrayList<>(); + private int processingTime = 100; + + @Override + public @NotNull CreateCrushingRecipeBuilder unlockedBy( + @NotNull String name, @NotNull CriterionTriggerInstance trigger) { + return this; + } - @Override - public ResourceLocation getAdvancementId() { - return null; - } - } + @Override + public @NotNull CreateCrushingRecipeBuilder group(@Nullable String name) { + group = name; + return this; + } + + public CreateCrushingRecipeBuilder duration(int duration) { + this.processingTime = duration; + return this; + } + + public CreateCrushingRecipeBuilder withInput(ItemLike item) { + return withInput(Ingredient.of(item)); + } + + public CreateCrushingRecipeBuilder withInput(ItemStack stack) { + return withInput(Ingredient.of(stack)); + } + + public CreateCrushingRecipeBuilder withInput(Ingredient ingredient) { + this.input = ingredient; + return this; + } + + public CreateCrushingRecipeBuilder withOutput(ItemLike output) { + return withOutput(1f, output, 1); + } + + public CreateCrushingRecipeBuilder withOutput(float chance, ItemLike output) { + return withOutput(chance, output, 1); + } + + public CreateCrushingRecipeBuilder withOutput(ItemLike output, int count) { + return withOutput(1f, output, count); + } + + public CreateCrushingRecipeBuilder withOutput(float chance, ItemLike output, int count) { + return withOutput(new ItemStack(output, count), chance); + } + + public CreateCrushingRecipeBuilder withOutput(ItemStack output, float chance) { + this.results.add(new ItemProcessingOutput(output, chance)); + return this; + } + + public CreateCrushingRecipeBuilder withOutput(String name) { + return withOutput(1f, name, 1); + } + + public CreateCrushingRecipeBuilder withOutput(String name, int count) { + return withOutput(1f, name, count); + } + + public CreateCrushingRecipeBuilder withOutput(float chance, String name) { + return withOutput(chance, name, 1); + } + + public CreateCrushingRecipeBuilder withOutput(float chance, String name, int count) { + this.results.add(new CompatProcessingOutput(name, count, chance)); + return this; + } + + @Override + public @NotNull Item getResult() { + return Items.AIR; // Irrelevant, we implement serialization ourselves + } + + @Override + public void save( + @NotNull Consumer<FinishedRecipe> consumer, @NotNull ResourceLocation resourceLocation) { + consumer.accept(new CrushingRecipe(resourceLocation)); + } + + public class CrushingRecipe implements FinishedRecipe { + + private final ResourceLocation id; + + public CrushingRecipe(ResourceLocation id) { + this.id = id; + } + + @Override + public void serializeRecipeData(@NotNull JsonObject json) { + json.addProperty("type", "create:crushing"); + + if (!group.isEmpty()) { + json.addProperty("group", group); + } + + JsonArray jsonIngredients = new JsonArray(); + JsonArray jsonOutputs = new JsonArray(); + + jsonIngredients.add(input.toJson()); + + results.forEach(o -> jsonOutputs.add(o.serialize())); + + json.add("ingredients", jsonIngredients); + json.add("results", jsonOutputs); + + int processingDuration = processingTime; + if (processingDuration > 0) { + json.addProperty("processingTime", processingDuration); + } + } + + @Override + public @NotNull ResourceLocation getId() { + return id; + } + + @Override + public @NotNull RecipeSerializer<?> getType() { + return RecipeSerializer.SHAPELESS_RECIPE; // Irrelevant, we implement serialization ourselves + } + @Override + public JsonObject serializeAdvancement() { + return null; + } + + @Override + public ResourceLocation getAdvancementId() { + return null; + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/FarmersDelightCuttingRecipeBuilder.java b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/FarmersDelightCuttingRecipeBuilder.java index 8fbc4e7be1..c5eaff2f3d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/FarmersDelightCuttingRecipeBuilder.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/FarmersDelightCuttingRecipeBuilder.java @@ -3,8 +3,9 @@ import com.google.common.collect.Lists; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import java.util.List; +import java.util.function.Consumer; import net.minecraft.advancements.CriterionTriggerInstance; -import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.data.recipes.RecipeBuilder; @@ -19,148 +20,146 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; -import java.util.function.Consumer; - public class FarmersDelightCuttingRecipeBuilder implements RecipeBuilder { - private String group = ""; - private final List<ProcessingOutput> outputs = Lists.newArrayList(); - private Ingredient input; - private FarmersDelightToolIngredient toolAction; - private SoundEvent sound; - - @Override - public FarmersDelightCuttingRecipeBuilder unlockedBy(String s, CriterionTriggerInstance criterionTriggerInstance) { - return this; - } - - @Override - public @NotNull FarmersDelightCuttingRecipeBuilder group(@Nullable String name) { - group = name; - return this; - } - - @Override - public Item getResult() { - return Items.AIR; // Irrelevant, we implement serialization ourselves - } - - public FarmersDelightCuttingRecipeBuilder withInput(ItemLike item) { - return withInput(Ingredient.of(item)); - } - - public FarmersDelightCuttingRecipeBuilder withInput(ItemStack stack) { - return withInput(Ingredient.of(stack)); - } - - public FarmersDelightCuttingRecipeBuilder withInput(Ingredient ingredient) { - this.input = ingredient; - return this; - } - - public FarmersDelightCuttingRecipeBuilder withOutput(ItemLike output) { - return withOutput(1f, output, 1); - } - - public FarmersDelightCuttingRecipeBuilder withOutput(float chance, ItemLike output) { - return withOutput(chance, output, 1); - } - - public FarmersDelightCuttingRecipeBuilder withOutput(ItemLike output, int count) { - return withOutput(1f, output, count); - } - - public FarmersDelightCuttingRecipeBuilder withOutput(float chance, ItemLike output, int count) { - return withOutput(new ItemStack(output, count), chance); - } - - public FarmersDelightCuttingRecipeBuilder withOutput(ItemStack output, float chance) { - this.outputs.add(new ItemProcessingOutput(output, chance)); - return this; - } - - public FarmersDelightCuttingRecipeBuilder withOutput(String name) { - return withOutput(1f, name, 1); - } - - public FarmersDelightCuttingRecipeBuilder withOutput(String name, int count) { - return withOutput(1f, name, count); - } - - public FarmersDelightCuttingRecipeBuilder withOutput(float chance, String name) { - return withOutput(chance, name, 1); - } - - public FarmersDelightCuttingRecipeBuilder withOutput(float chance, String name, int count) { - this.outputs.add(new CompatProcessingOutput(name, count, chance)); - return this; - } - - public FarmersDelightCuttingRecipeBuilder withTool(FarmersDelightToolIngredient ingredient) { - this.toolAction = ingredient; - return this; - } - - public FarmersDelightCuttingRecipeBuilder withSound(SoundEvent sound) { - this.sound = sound; - return this; - } - - @Override - public void save(Consumer<FinishedRecipe> consumer, ResourceLocation resourceLocation) { - consumer.accept(new CuttingRecipe(resourceLocation)); - } - - public class CuttingRecipe implements FinishedRecipe { - - private final ResourceLocation id; - - public CuttingRecipe(ResourceLocation id) { - this.id = id; - } - - @Override - public void serializeRecipeData(@NotNull JsonObject json) { - json.addProperty("type", "farmersdelight:cutting"); - - if (!group.isEmpty()) { - json.addProperty("group", group); - } - - JsonArray jsonIngredients = new JsonArray(); - JsonArray jsonOutputs = new JsonArray(); - - jsonIngredients.add(input.toJson()); - - outputs.forEach(o -> jsonOutputs.add(o.serialize())); - - json.add("ingredients", jsonIngredients); - json.add("tool", toolAction.serialize()); - json.add("result", jsonOutputs); - - if (sound != null) { - json.addProperty("sound", BuiltInRegistries.SOUND_EVENT.getKey(sound).toString()); - } - } - - @Override - public @NotNull ResourceLocation getId() { - return id; - } - - @Override - public @NotNull RecipeSerializer<?> getType() { - return RecipeSerializer.SHAPELESS_RECIPE; // Irrelevant, we implement serialization ourselves - } + private String group = ""; + private final List<ProcessingOutput> outputs = Lists.newArrayList(); + private Ingredient input; + private FarmersDelightToolIngredient toolAction; + private SoundEvent sound; + + @Override + public FarmersDelightCuttingRecipeBuilder unlockedBy( + String s, CriterionTriggerInstance criterionTriggerInstance) { + return this; + } + + @Override + public @NotNull FarmersDelightCuttingRecipeBuilder group(@Nullable String name) { + group = name; + return this; + } + + @Override + public Item getResult() { + return Items.AIR; // Irrelevant, we implement serialization ourselves + } + + public FarmersDelightCuttingRecipeBuilder withInput(ItemLike item) { + return withInput(Ingredient.of(item)); + } + + public FarmersDelightCuttingRecipeBuilder withInput(ItemStack stack) { + return withInput(Ingredient.of(stack)); + } + + public FarmersDelightCuttingRecipeBuilder withInput(Ingredient ingredient) { + this.input = ingredient; + return this; + } + + public FarmersDelightCuttingRecipeBuilder withOutput(ItemLike output) { + return withOutput(1f, output, 1); + } + + public FarmersDelightCuttingRecipeBuilder withOutput(float chance, ItemLike output) { + return withOutput(chance, output, 1); + } + + public FarmersDelightCuttingRecipeBuilder withOutput(ItemLike output, int count) { + return withOutput(1f, output, count); + } + + public FarmersDelightCuttingRecipeBuilder withOutput(float chance, ItemLike output, int count) { + return withOutput(new ItemStack(output, count), chance); + } + + public FarmersDelightCuttingRecipeBuilder withOutput(ItemStack output, float chance) { + this.outputs.add(new ItemProcessingOutput(output, chance)); + return this; + } + + public FarmersDelightCuttingRecipeBuilder withOutput(String name) { + return withOutput(1f, name, 1); + } + + public FarmersDelightCuttingRecipeBuilder withOutput(String name, int count) { + return withOutput(1f, name, count); + } + + public FarmersDelightCuttingRecipeBuilder withOutput(float chance, String name) { + return withOutput(chance, name, 1); + } + + public FarmersDelightCuttingRecipeBuilder withOutput(float chance, String name, int count) { + this.outputs.add(new CompatProcessingOutput(name, count, chance)); + return this; + } + + public FarmersDelightCuttingRecipeBuilder withTool(FarmersDelightToolIngredient ingredient) { + this.toolAction = ingredient; + return this; + } + + public FarmersDelightCuttingRecipeBuilder withSound(SoundEvent sound) { + this.sound = sound; + return this; + } + + @Override + public void save(Consumer<FinishedRecipe> consumer, ResourceLocation resourceLocation) { + consumer.accept(new CuttingRecipe(resourceLocation)); + } + + public class CuttingRecipe implements FinishedRecipe { + + private final ResourceLocation id; + + public CuttingRecipe(ResourceLocation id) { + this.id = id; + } + + @Override + public void serializeRecipeData(@NotNull JsonObject json) { + json.addProperty("type", "farmersdelight:cutting"); + + if (!group.isEmpty()) { + json.addProperty("group", group); + } + + JsonArray jsonIngredients = new JsonArray(); + JsonArray jsonOutputs = new JsonArray(); + + jsonIngredients.add(input.toJson()); + + outputs.forEach(o -> jsonOutputs.add(o.serialize())); + + json.add("ingredients", jsonIngredients); + json.add("tool", toolAction.serialize()); + json.add("result", jsonOutputs); + + if (sound != null) { + json.addProperty("sound", BuiltInRegistries.SOUND_EVENT.getKey(sound).toString()); + } + } + + @Override + public @NotNull ResourceLocation getId() { + return id; + } + + @Override + public @NotNull RecipeSerializer<?> getType() { + return RecipeSerializer.SHAPELESS_RECIPE; // Irrelevant, we implement serialization ourselves + } - @Override - public JsonObject serializeAdvancement() { - return null; - } + @Override + public JsonObject serializeAdvancement() { + return null; + } - @Override - public ResourceLocation getAdvancementId() { - return null; - } - } + @Override + public ResourceLocation getAdvancementId() { + return null; + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/FarmersDelightToolIngredient.java b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/FarmersDelightToolIngredient.java index 246d4e0275..0c77dcb00e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/FarmersDelightToolIngredient.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/FarmersDelightToolIngredient.java @@ -3,5 +3,5 @@ import com.google.gson.JsonObject; public interface FarmersDelightToolIngredient { - JsonObject serialize(); + JsonObject serialize(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/ItemProcessingOutput.java b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/ItemProcessingOutput.java index 245c3d607b..481b7dd5a0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/ItemProcessingOutput.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/ItemProcessingOutput.java @@ -2,27 +2,26 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; public record ItemProcessingOutput(ItemStack stack, float chance) implements ProcessingOutput { - @Override - public JsonObject serialize() { - JsonObject json = new JsonObject(); - ResourceLocation resourceLocation = BuiltInRegistries.ITEM.getKey(stack.getItem()); - json.addProperty("item", resourceLocation.toString()); - int count = stack.getCount(); - if (count != 1) { - json.addProperty("count", count); - } - if (stack.hasTag()) { - json.add("nbt", JsonParser.parseString(stack.getTag().toString())); - } - if (chance != 1) { - json.addProperty("chance", chance); - } - return json; - } + @Override + public JsonObject serialize() { + JsonObject json = new JsonObject(); + ResourceLocation resourceLocation = BuiltInRegistries.ITEM.getKey(stack.getItem()); + json.addProperty("item", resourceLocation.toString()); + int count = stack.getCount(); + if (count != 1) { + json.addProperty("count", count); + } + if (stack.hasTag()) { + json.add("nbt", JsonParser.parseString(stack.getTag().toString())); + } + if (chance != 1) { + json.addProperty("chance", chance); + } + return json; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/ProcessingOutput.java b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/ProcessingOutput.java index 6a0c5701ff..f25cf0e1ab 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/ProcessingOutput.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/recipe/builders/ProcessingOutput.java @@ -3,5 +3,5 @@ import com.google.gson.JsonObject; public interface ProcessingOutput { - JsonObject serialize(); + JsonObject serialize(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexActionTagProvider.java b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexActionTagProvider.java index 4b083c5731..a39b6a9360 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexActionTagProvider.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexActionTagProvider.java @@ -1,9 +1,12 @@ package at.petrak.hexcasting.datagen.tag; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.casting.ActionRegistryEntry; import at.petrak.hexcasting.api.mod.HexTags; import at.petrak.hexcasting.xplat.IXplatAbstractions; import at.petrak.hexcasting.xplat.Platform; +import java.util.concurrent.CompletableFuture; import net.minecraft.core.HolderLookup; import net.minecraft.data.PackOutput; import net.minecraft.data.tags.TagsProvider; @@ -11,42 +14,53 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; -import java.util.concurrent.CompletableFuture; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class HexActionTagProvider extends TagsProvider<ActionRegistryEntry> { - public HexActionTagProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> provider) { - super(output, IXplatAbstractions.INSTANCE.getActionRegistry().key(), provider); - } + public HexActionTagProvider( + PackOutput output, CompletableFuture<HolderLookup.Provider> provider) { + super(output, IXplatAbstractions.INSTANCE.getActionRegistry().key(), provider); + } - @Override - protected void addTags(HolderLookup.Provider provider) { - // In-game almost all great spells are always per-world - for (var normalGreat : new String[]{ - "lightning", "flight", "create_lava", "teleport/great", "sentinel/create/great", - "dispel_rain", "summon_rain", "brainsweep", "craft/battery", - "potion/regeneration", "potion/night_vision", "potion/absorption", "potion/haste", "potion/strength" - }) { - var loc = modLoc(normalGreat); - var key = ResourceKey.create(IXplatAbstractions.INSTANCE.getActionRegistry().key(), loc); - tag(ersatzActionTag(HexTags.Actions.REQUIRES_ENLIGHTENMENT)).add(key); - tag(ersatzActionTag(HexTags.Actions.CAN_START_ENLIGHTEN)).add(key); - tag(ersatzActionTag(HexTags.Actions.PER_WORLD_PATTERN)).add(key); - } - // deciding that akashic write can be just a normal spell (as a treat) - } + @Override + protected void addTags(HolderLookup.Provider provider) { + // In-game almost all great spells are always per-world + for (var normalGreat : + new String[] { + "lightning", + "flight", + "create_lava", + "teleport/great", + "sentinel/create/great", + "dispel_rain", + "summon_rain", + "brainsweep", + "craft/battery", + "potion/regeneration", + "potion/night_vision", + "potion/absorption", + "potion/haste", + "potion/strength" + }) { + var loc = modLoc(normalGreat); + var key = ResourceKey.create(IXplatAbstractions.INSTANCE.getActionRegistry().key(), loc); + tag(ersatzActionTag(HexTags.Actions.REQUIRES_ENLIGHTENMENT)).add(key); + tag(ersatzActionTag(HexTags.Actions.CAN_START_ENLIGHTEN)).add(key); + tag(ersatzActionTag(HexTags.Actions.PER_WORLD_PATTERN)).add(key); + } + // deciding that akashic write can be just a normal spell (as a treat) + } - private static TagKey<ActionRegistryEntry> ersatzActionTag(TagKey<ActionRegistryEntry> real) { - if (IXplatAbstractions.INSTANCE.platform() == Platform.FABRIC) { - // Vanilla (and Fabric) has a bug here where it *writes* hexcasting action tags to `.../tags/action` - // instead of `.../tags/hexcasting/action`. - // So we pull this bullshit - var fakeKey = ResourceKey.<ActionRegistryEntry>createRegistryKey( - new ResourceLocation("foobar", "hexcasting/tags/action")); - return TagKey.create(fakeKey, real.location()); - } else { - return real; - } - } + private static TagKey<ActionRegistryEntry> ersatzActionTag(TagKey<ActionRegistryEntry> real) { + if (IXplatAbstractions.INSTANCE.platform() == Platform.FABRIC) { + // Vanilla (and Fabric) has a bug here where it *writes* hexcasting action tags to + // `.../tags/action` + // instead of `.../tags/hexcasting/action`. + // So we pull this bullshit + var fakeKey = + ResourceKey.<ActionRegistryEntry>createRegistryKey( + new ResourceLocation("foobar", "hexcasting/tags/action")); + return TagKey.create(fakeKey, real.location()); + } else { + return real; + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexBlockTagProvider.java b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexBlockTagProvider.java index dffbb06364..e78bb0e5a2 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexBlockTagProvider.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexBlockTagProvider.java @@ -4,6 +4,7 @@ import at.petrak.hexcasting.common.lib.HexBlocks; import at.petrak.hexcasting.xplat.IXplatTags; import at.petrak.paucal.api.datagen.PaucalBlockTagProvider; +import java.util.concurrent.CompletableFuture; import net.minecraft.core.HolderLookup; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.PackOutput; @@ -11,129 +12,177 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; -import java.util.concurrent.CompletableFuture; - public class HexBlockTagProvider extends PaucalBlockTagProvider { - public final IXplatTags xtags; - - public HexBlockTagProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, - IXplatTags xtags) { - super(output, lookupProvider); - this.xtags = xtags; - } - - @Override - protected void addTags(HolderLookup.Provider provider) { - add(tag(HexTags.Blocks.IMPETI), - HexBlocks.IMPETUS_LOOK, HexBlocks.IMPETUS_RIGHTCLICK, HexBlocks.IMPETUS_REDSTONE); - add(tag(HexTags.Blocks.DIRECTRICES), - HexBlocks.DIRECTRIX_REDSTONE, HexBlocks.DIRECTRIX_BOOLEAN); - tag(HexTags.Blocks.MINDFLAYED_CIRCLE_COMPONENTS) - .addTag(HexTags.Blocks.IMPETI) - .addTag(HexTags.Blocks.DIRECTRICES); - - add(tag(BlockTags.MINEABLE_WITH_PICKAXE), - HexBlocks.SLATE_BLOCK, HexBlocks.SLATE_TILES, HexBlocks.SLATE_BRICKS, - HexBlocks.SLATE_BRICKS_SMALL, HexBlocks.SLATE_PILLAR, HexBlocks.SLATE, - HexBlocks.EMPTY_DIRECTRIX, HexBlocks.DIRECTRIX_REDSTONE, HexBlocks.DIRECTRIX_BOOLEAN, - HexBlocks.IMPETUS_EMPTY, - HexBlocks.IMPETUS_RIGHTCLICK, HexBlocks.IMPETUS_LOOK, HexBlocks.IMPETUS_REDSTONE, - HexBlocks.AMETHYST_TILES, HexBlocks.AMETHYST_BRICKS, HexBlocks.AMETHYST_BRICKS_SMALL, - HexBlocks.AMETHYST_PILLAR, HexBlocks.SLATE_AMETHYST_TILES, HexBlocks.SLATE_AMETHYST_BRICKS, - HexBlocks.SLATE_AMETHYST_BRICKS_SMALL, HexBlocks.SLATE_AMETHYST_PILLAR, HexBlocks.SCONCE, - HexBlocks.QUENCHED_ALLAY, HexBlocks.QUENCHED_ALLAY_TILES, HexBlocks.QUENCHED_ALLAY_BRICKS, - HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL); - - add(tag(BlockTags.MINEABLE_WITH_SHOVEL), - HexBlocks.AMETHYST_DUST_BLOCK); - - add(tag(BlockTags.MINEABLE_WITH_AXE), - HexBlocks.AKASHIC_RECORD, HexBlocks.AKASHIC_BOOKSHELF, HexBlocks.AKASHIC_LIGATURE, - HexBlocks.EDIFIED_LOG, HexBlocks.EDIFIED_LOG_AMETHYST, - HexBlocks.EDIFIED_LOG_AVENTURINE, HexBlocks.EDIFIED_LOG_CITRINE, - HexBlocks.EDIFIED_LOG_PURPLE, HexBlocks.STRIPPED_EDIFIED_LOG, - HexBlocks.EDIFIED_WOOD, HexBlocks.STRIPPED_EDIFIED_WOOD, - HexBlocks.EDIFIED_PLANKS, HexBlocks.EDIFIED_PANEL, HexBlocks.EDIFIED_TILE, - HexBlocks.EDIFIED_DOOR, HexBlocks.EDIFIED_TRAPDOOR, HexBlocks.EDIFIED_SLAB, - HexBlocks.EDIFIED_BUTTON, HexBlocks.EDIFIED_STAIRS, HexBlocks.EDIFIED_FENCE, HexBlocks.EDIFIED_FENCE_GATE); - - add(tag(BlockTags.MINEABLE_WITH_HOE), - HexBlocks.AMETHYST_EDIFIED_LEAVES, HexBlocks.AVENTURINE_EDIFIED_LEAVES, - HexBlocks.CITRINE_EDIFIED_LEAVES); - - add(tag(BlockTags.CRYSTAL_SOUND_BLOCKS), - HexBlocks.CONJURED_LIGHT, HexBlocks.CONJURED_BLOCK, HexBlocks.AMETHYST_TILES, - HexBlocks.SCONCE); - - add(tag(HexTags.Blocks.EDIFIED_LOGS), - HexBlocks.EDIFIED_LOG, HexBlocks.EDIFIED_LOG_AMETHYST, - HexBlocks.EDIFIED_LOG_AVENTURINE, HexBlocks.EDIFIED_LOG_CITRINE, - HexBlocks.EDIFIED_LOG_PURPLE, HexBlocks.STRIPPED_EDIFIED_LOG, - HexBlocks.EDIFIED_WOOD, HexBlocks.STRIPPED_EDIFIED_WOOD); - add(tag(BlockTags.LOGS), - HexBlocks.EDIFIED_LOG, HexBlocks.EDIFIED_LOG_AMETHYST, - HexBlocks.EDIFIED_LOG_AVENTURINE, HexBlocks.EDIFIED_LOG_CITRINE, - HexBlocks.EDIFIED_LOG_PURPLE, HexBlocks.STRIPPED_EDIFIED_LOG, - HexBlocks.EDIFIED_WOOD, HexBlocks.STRIPPED_EDIFIED_WOOD); - add(tag(BlockTags.LOGS_THAT_BURN), - HexBlocks.EDIFIED_LOG, HexBlocks.EDIFIED_LOG_AMETHYST, - HexBlocks.EDIFIED_LOG_AVENTURINE, HexBlocks.EDIFIED_LOG_CITRINE, - HexBlocks.EDIFIED_LOG_PURPLE, HexBlocks.STRIPPED_EDIFIED_LOG, - HexBlocks.EDIFIED_WOOD, HexBlocks.STRIPPED_EDIFIED_WOOD); - add(tag(BlockTags.LEAVES), - HexBlocks.AMETHYST_EDIFIED_LEAVES, HexBlocks.AVENTURINE_EDIFIED_LEAVES, - HexBlocks.CITRINE_EDIFIED_LEAVES); - - add(tag(BlockTags.PLANKS), - HexBlocks.EDIFIED_PLANKS, HexBlocks.EDIFIED_PANEL, HexBlocks.EDIFIED_TILE); - add(tag(HexTags.Blocks.EDIFIED_PLANKS), - HexBlocks.EDIFIED_PLANKS, HexBlocks.EDIFIED_PANEL, HexBlocks.EDIFIED_TILE); - add(tag(BlockTags.SLABS), - HexBlocks.EDIFIED_SLAB); - add(tag(BlockTags.WOODEN_SLABS), - HexBlocks.EDIFIED_SLAB); - add(tag(BlockTags.STAIRS), - HexBlocks.EDIFIED_STAIRS); - add(tag(BlockTags.FENCES), - HexBlocks.EDIFIED_FENCE); - add(tag(BlockTags.WOODEN_FENCES), - HexBlocks.EDIFIED_FENCE); - add(tag(BlockTags.FENCE_GATES), - HexBlocks.EDIFIED_FENCE_GATE); - add(tag(BlockTags.UNSTABLE_BOTTOM_CENTER), - HexBlocks.EDIFIED_FENCE_GATE); - - - add(tag(BlockTags.WOODEN_FENCES), - HexBlocks.EDIFIED_FENCE); - add(tag(BlockTags.WOODEN_STAIRS), - HexBlocks.EDIFIED_STAIRS); - add(tag(BlockTags.DOORS), - HexBlocks.EDIFIED_DOOR); - add(tag(BlockTags.WOODEN_DOORS), - HexBlocks.EDIFIED_DOOR); - add(tag(BlockTags.TRAPDOORS), - HexBlocks.EDIFIED_TRAPDOOR); - add(tag(BlockTags.WOODEN_TRAPDOORS), - HexBlocks.EDIFIED_TRAPDOOR); - add(tag(BlockTags.PRESSURE_PLATES), - HexBlocks.EDIFIED_PRESSURE_PLATE); - add(tag(BlockTags.WOODEN_PRESSURE_PLATES), - HexBlocks.EDIFIED_PRESSURE_PLATE); - add(tag(BlockTags.BUTTONS), - HexBlocks.EDIFIED_BUTTON); - add(tag(BlockTags.WOODEN_BUTTONS), - HexBlocks.EDIFIED_BUTTON); - - add(tag(HexTags.Blocks.WATER_PLANTS), - Blocks.KELP, Blocks.KELP_PLANT, Blocks.SEAGRASS, Blocks.TALL_SEAGRASS); - add(tag(HexTags.Blocks.CHEAP_TO_BREAK_BLOCK), - HexBlocks.CONJURED_BLOCK, HexBlocks.CONJURED_LIGHT); - } - - void add(TagAppender<Block> appender, Block... blocks) { - for (Block block : blocks) { - appender.add(BuiltInRegistries.BLOCK.getResourceKey(block).orElseThrow()); - } - } + public final IXplatTags xtags; + + public HexBlockTagProvider( + PackOutput output, + CompletableFuture<HolderLookup.Provider> lookupProvider, + IXplatTags xtags) { + super(output, lookupProvider); + this.xtags = xtags; + } + + @Override + protected void addTags(HolderLookup.Provider provider) { + add( + tag(HexTags.Blocks.IMPETI), + HexBlocks.IMPETUS_LOOK, + HexBlocks.IMPETUS_RIGHTCLICK, + HexBlocks.IMPETUS_REDSTONE); + add(tag(HexTags.Blocks.DIRECTRICES), HexBlocks.DIRECTRIX_REDSTONE, HexBlocks.DIRECTRIX_BOOLEAN); + tag(HexTags.Blocks.MINDFLAYED_CIRCLE_COMPONENTS) + .addTag(HexTags.Blocks.IMPETI) + .addTag(HexTags.Blocks.DIRECTRICES); + + add( + tag(BlockTags.MINEABLE_WITH_PICKAXE), + HexBlocks.SLATE_BLOCK, + HexBlocks.SLATE_TILES, + HexBlocks.SLATE_BRICKS, + HexBlocks.SLATE_BRICKS_SMALL, + HexBlocks.SLATE_PILLAR, + HexBlocks.SLATE, + HexBlocks.EMPTY_DIRECTRIX, + HexBlocks.DIRECTRIX_REDSTONE, + HexBlocks.DIRECTRIX_BOOLEAN, + HexBlocks.IMPETUS_EMPTY, + HexBlocks.IMPETUS_RIGHTCLICK, + HexBlocks.IMPETUS_LOOK, + HexBlocks.IMPETUS_REDSTONE, + HexBlocks.AMETHYST_TILES, + HexBlocks.AMETHYST_BRICKS, + HexBlocks.AMETHYST_BRICKS_SMALL, + HexBlocks.AMETHYST_PILLAR, + HexBlocks.SLATE_AMETHYST_TILES, + HexBlocks.SLATE_AMETHYST_BRICKS, + HexBlocks.SLATE_AMETHYST_BRICKS_SMALL, + HexBlocks.SLATE_AMETHYST_PILLAR, + HexBlocks.SCONCE, + HexBlocks.QUENCHED_ALLAY, + HexBlocks.QUENCHED_ALLAY_TILES, + HexBlocks.QUENCHED_ALLAY_BRICKS, + HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL); + + add(tag(BlockTags.MINEABLE_WITH_SHOVEL), HexBlocks.AMETHYST_DUST_BLOCK); + + add( + tag(BlockTags.MINEABLE_WITH_AXE), + HexBlocks.AKASHIC_RECORD, + HexBlocks.AKASHIC_BOOKSHELF, + HexBlocks.AKASHIC_LIGATURE, + HexBlocks.EDIFIED_LOG, + HexBlocks.EDIFIED_LOG_AMETHYST, + HexBlocks.EDIFIED_LOG_AVENTURINE, + HexBlocks.EDIFIED_LOG_CITRINE, + HexBlocks.EDIFIED_LOG_PURPLE, + HexBlocks.STRIPPED_EDIFIED_LOG, + HexBlocks.EDIFIED_WOOD, + HexBlocks.STRIPPED_EDIFIED_WOOD, + HexBlocks.EDIFIED_PLANKS, + HexBlocks.EDIFIED_PANEL, + HexBlocks.EDIFIED_TILE, + HexBlocks.EDIFIED_DOOR, + HexBlocks.EDIFIED_TRAPDOOR, + HexBlocks.EDIFIED_SLAB, + HexBlocks.EDIFIED_BUTTON, + HexBlocks.EDIFIED_STAIRS, + HexBlocks.EDIFIED_FENCE, + HexBlocks.EDIFIED_FENCE_GATE); + + add( + tag(BlockTags.MINEABLE_WITH_HOE), + HexBlocks.AMETHYST_EDIFIED_LEAVES, + HexBlocks.AVENTURINE_EDIFIED_LEAVES, + HexBlocks.CITRINE_EDIFIED_LEAVES); + + add( + tag(BlockTags.CRYSTAL_SOUND_BLOCKS), + HexBlocks.CONJURED_LIGHT, + HexBlocks.CONJURED_BLOCK, + HexBlocks.AMETHYST_TILES, + HexBlocks.SCONCE); + + add( + tag(HexTags.Blocks.EDIFIED_LOGS), + HexBlocks.EDIFIED_LOG, + HexBlocks.EDIFIED_LOG_AMETHYST, + HexBlocks.EDIFIED_LOG_AVENTURINE, + HexBlocks.EDIFIED_LOG_CITRINE, + HexBlocks.EDIFIED_LOG_PURPLE, + HexBlocks.STRIPPED_EDIFIED_LOG, + HexBlocks.EDIFIED_WOOD, + HexBlocks.STRIPPED_EDIFIED_WOOD); + add( + tag(BlockTags.LOGS), + HexBlocks.EDIFIED_LOG, + HexBlocks.EDIFIED_LOG_AMETHYST, + HexBlocks.EDIFIED_LOG_AVENTURINE, + HexBlocks.EDIFIED_LOG_CITRINE, + HexBlocks.EDIFIED_LOG_PURPLE, + HexBlocks.STRIPPED_EDIFIED_LOG, + HexBlocks.EDIFIED_WOOD, + HexBlocks.STRIPPED_EDIFIED_WOOD); + add( + tag(BlockTags.LOGS_THAT_BURN), + HexBlocks.EDIFIED_LOG, + HexBlocks.EDIFIED_LOG_AMETHYST, + HexBlocks.EDIFIED_LOG_AVENTURINE, + HexBlocks.EDIFIED_LOG_CITRINE, + HexBlocks.EDIFIED_LOG_PURPLE, + HexBlocks.STRIPPED_EDIFIED_LOG, + HexBlocks.EDIFIED_WOOD, + HexBlocks.STRIPPED_EDIFIED_WOOD); + add( + tag(BlockTags.LEAVES), + HexBlocks.AMETHYST_EDIFIED_LEAVES, + HexBlocks.AVENTURINE_EDIFIED_LEAVES, + HexBlocks.CITRINE_EDIFIED_LEAVES); + + add( + tag(BlockTags.PLANKS), + HexBlocks.EDIFIED_PLANKS, + HexBlocks.EDIFIED_PANEL, + HexBlocks.EDIFIED_TILE); + add( + tag(HexTags.Blocks.EDIFIED_PLANKS), + HexBlocks.EDIFIED_PLANKS, + HexBlocks.EDIFIED_PANEL, + HexBlocks.EDIFIED_TILE); + add(tag(BlockTags.SLABS), HexBlocks.EDIFIED_SLAB); + add(tag(BlockTags.WOODEN_SLABS), HexBlocks.EDIFIED_SLAB); + add(tag(BlockTags.STAIRS), HexBlocks.EDIFIED_STAIRS); + add(tag(BlockTags.FENCES), HexBlocks.EDIFIED_FENCE); + add(tag(BlockTags.WOODEN_FENCES), HexBlocks.EDIFIED_FENCE); + add(tag(BlockTags.FENCE_GATES), HexBlocks.EDIFIED_FENCE_GATE); + add(tag(BlockTags.UNSTABLE_BOTTOM_CENTER), HexBlocks.EDIFIED_FENCE_GATE); + + add(tag(BlockTags.WOODEN_FENCES), HexBlocks.EDIFIED_FENCE); + add(tag(BlockTags.WOODEN_STAIRS), HexBlocks.EDIFIED_STAIRS); + add(tag(BlockTags.DOORS), HexBlocks.EDIFIED_DOOR); + add(tag(BlockTags.WOODEN_DOORS), HexBlocks.EDIFIED_DOOR); + add(tag(BlockTags.TRAPDOORS), HexBlocks.EDIFIED_TRAPDOOR); + add(tag(BlockTags.WOODEN_TRAPDOORS), HexBlocks.EDIFIED_TRAPDOOR); + add(tag(BlockTags.PRESSURE_PLATES), HexBlocks.EDIFIED_PRESSURE_PLATE); + add(tag(BlockTags.WOODEN_PRESSURE_PLATES), HexBlocks.EDIFIED_PRESSURE_PLATE); + add(tag(BlockTags.BUTTONS), HexBlocks.EDIFIED_BUTTON); + add(tag(BlockTags.WOODEN_BUTTONS), HexBlocks.EDIFIED_BUTTON); + + add( + tag(HexTags.Blocks.WATER_PLANTS), + Blocks.KELP, + Blocks.KELP_PLANT, + Blocks.SEAGRASS, + Blocks.TALL_SEAGRASS); + add( + tag(HexTags.Blocks.CHEAP_TO_BREAK_BLOCK), + HexBlocks.CONJURED_BLOCK, + HexBlocks.CONJURED_LIGHT); + } + + void add(TagAppender<Block> appender, Block... blocks) { + for (Block block : blocks) { + appender.add(BuiltInRegistries.BLOCK.getResourceKey(block).orElseThrow()); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java index 16e7020d08..7e1e916d3a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java @@ -1,6 +1,7 @@ package at.petrak.hexcasting.datagen.tag; import at.petrak.hexcasting.common.lib.HexDamageTypes; +import java.util.concurrent.CompletableFuture; import net.minecraft.core.HolderLookup; import net.minecraft.data.PackOutput; import net.minecraft.data.tags.DamageTypeTagsProvider; @@ -10,26 +11,25 @@ import net.minecraft.world.damagesource.DamageType; import org.jetbrains.annotations.NotNull; -import java.util.concurrent.CompletableFuture; - public class HexDamageTypeTagProvider extends DamageTypeTagsProvider { - public HexDamageTypeTagProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> provider) { - super(output, provider); - } + public HexDamageTypeTagProvider( + PackOutput output, CompletableFuture<HolderLookup.Provider> provider) { + super(output, provider); + } - @Override - protected void addTags(@NotNull HolderLookup.Provider provider) { - add(HexDamageTypes.OVERCAST, - DamageTypeTags.BYPASSES_ARMOR, - DamageTypeTags.BYPASSES_EFFECTS, - DamageTypeTags.BYPASSES_SHIELD - ); - } + @Override + protected void addTags(@NotNull HolderLookup.Provider provider) { + add( + HexDamageTypes.OVERCAST, + DamageTypeTags.BYPASSES_ARMOR, + DamageTypeTags.BYPASSES_EFFECTS, + DamageTypeTags.BYPASSES_SHIELD); + } - @SafeVarargs - private void add(ResourceKey<DamageType> damageType, TagKey<DamageType>... tags) { - for (var tag : tags) { - this.tag(tag).add(damageType); - } - } + @SafeVarargs + private void add(ResourceKey<DamageType> damageType, TagKey<DamageType>... tags) { + for (var tag : tags) { + this.tag(tag).add(damageType); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexItemTagProvider.java b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexItemTagProvider.java index 520df8a48c..a0c946fadd 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexItemTagProvider.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexItemTagProvider.java @@ -5,9 +5,9 @@ import at.petrak.hexcasting.common.lib.HexItems; import at.petrak.hexcasting.xplat.IXplatTags; import at.petrak.paucal.api.datagen.PaucalItemTagProvider; +import java.util.concurrent.CompletableFuture; import net.minecraft.core.HolderLookup; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.data.DataGenerator; import net.minecraft.data.PackOutput; import net.minecraft.data.tags.TagsProvider; import net.minecraft.tags.BlockTags; @@ -16,65 +16,74 @@ import net.minecraft.world.item.Items; import net.minecraft.world.level.block.Block; -import java.util.concurrent.CompletableFuture; - public class HexItemTagProvider extends PaucalItemTagProvider { - private final IXplatTags xtags; - - public HexItemTagProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> lookup, TagsProvider<Block> pBlockTagsProvider, IXplatTags xtags) { - super(output, lookup, HexAPI.MOD_ID, pBlockTagsProvider); - this.xtags = xtags; - } - + private final IXplatTags xtags; + public HexItemTagProvider( + PackOutput output, + CompletableFuture<HolderLookup.Provider> lookup, + TagsProvider<Block> pBlockTagsProvider, + IXplatTags xtags) { + super(output, lookup, HexAPI.MOD_ID, pBlockTagsProvider); + this.xtags = xtags; + } - @Override - protected void addTags(HolderLookup.Provider provider) { - add(tag(xtags.gems()), - HexItems.CHARGED_AMETHYST); - add(tag(xtags.amethystDust()), - HexItems.AMETHYST_DUST); + @Override + protected void addTags(HolderLookup.Provider provider) { + add(tag(xtags.gems()), HexItems.CHARGED_AMETHYST); + add(tag(xtags.amethystDust()), HexItems.AMETHYST_DUST); - add(tag(HexTags.Items.STAVES), - HexItems.STAFF_EDIFIED, - HexItems.STAFF_OAK, HexItems.STAFF_SPRUCE, HexItems.STAFF_BIRCH, - HexItems.STAFF_JUNGLE, HexItems.STAFF_ACACIA, HexItems.STAFF_DARK_OAK, - HexItems.STAFF_CRIMSON, HexItems.STAFF_WARPED, HexItems.STAFF_MANGROVE, - HexItems.STAFF_CHERRY,HexItems.STAFF_BAMBOO, - HexItems.STAFF_QUENCHED, HexItems.STAFF_MINDSPLICE); + add( + tag(HexTags.Items.STAVES), + HexItems.STAFF_EDIFIED, + HexItems.STAFF_OAK, + HexItems.STAFF_SPRUCE, + HexItems.STAFF_BIRCH, + HexItems.STAFF_JUNGLE, + HexItems.STAFF_ACACIA, + HexItems.STAFF_DARK_OAK, + HexItems.STAFF_CRIMSON, + HexItems.STAFF_WARPED, + HexItems.STAFF_MANGROVE, + HexItems.STAFF_CHERRY, + HexItems.STAFF_BAMBOO, + HexItems.STAFF_QUENCHED, + HexItems.STAFF_MINDSPLICE); - add(tag(HexTags.Items.PHIAL_BASE), - Items.GLASS_BOTTLE); - add(tag(HexTags.Items.GRANTS_ROOT_ADVANCEMENT), - HexItems.AMETHYST_DUST, Items.AMETHYST_SHARD, - HexItems.CHARGED_AMETHYST, HexItems.CREATIVE_UNLOCKER); - add(tag(HexTags.Items.SEAL_MATERIALS), - Items.HONEYCOMB); + add(tag(HexTags.Items.PHIAL_BASE), Items.GLASS_BOTTLE); + add( + tag(HexTags.Items.GRANTS_ROOT_ADVANCEMENT), + HexItems.AMETHYST_DUST, + Items.AMETHYST_SHARD, + HexItems.CHARGED_AMETHYST, + HexItems.CREATIVE_UNLOCKER); + add(tag(HexTags.Items.SEAL_MATERIALS), Items.HONEYCOMB); - this.copy(HexTags.Blocks.EDIFIED_LOGS, HexTags.Items.EDIFIED_LOGS); - this.copy(HexTags.Blocks.EDIFIED_PLANKS, HexTags.Items.EDIFIED_PLANKS); - this.copy(HexTags.Blocks.IMPETI, HexTags.Items.IMPETI); - this.copy(HexTags.Blocks.DIRECTRICES, HexTags.Items.DIRECTRICES); - this.copy(HexTags.Blocks.MINDFLAYED_CIRCLE_COMPONENTS, HexTags.Items.MINDFLAYED_CIRCLE_COMPONENTS); - this.copy(BlockTags.LOGS_THAT_BURN, ItemTags.LOGS_THAT_BURN); - this.copy(BlockTags.LOGS, ItemTags.LOGS); - this.copy(BlockTags.PLANKS, ItemTags.PLANKS); - this.copy(BlockTags.SLABS, ItemTags.SLABS); - this.copy(BlockTags.WOODEN_SLABS, ItemTags.WOODEN_SLABS); - this.copy(BlockTags.DOORS, ItemTags.DOORS); - this.copy(BlockTags.WOODEN_DOORS, ItemTags.WOODEN_DOORS); - this.copy(BlockTags.TRAPDOORS, ItemTags.TRAPDOORS); - this.copy(BlockTags.WOODEN_TRAPDOORS, ItemTags.WOODEN_TRAPDOORS); - this.copy(BlockTags.LEAVES, ItemTags.LEAVES); - // Apparently, there's no "Pressure Plates" item tag. - this.copy(BlockTags.WOODEN_PRESSURE_PLATES, ItemTags.WOODEN_PRESSURE_PLATES); - this.copy(BlockTags.BUTTONS, ItemTags.BUTTONS); - this.copy(BlockTags.WOODEN_BUTTONS, ItemTags.WOODEN_BUTTONS); - } + this.copy(HexTags.Blocks.EDIFIED_LOGS, HexTags.Items.EDIFIED_LOGS); + this.copy(HexTags.Blocks.EDIFIED_PLANKS, HexTags.Items.EDIFIED_PLANKS); + this.copy(HexTags.Blocks.IMPETI, HexTags.Items.IMPETI); + this.copy(HexTags.Blocks.DIRECTRICES, HexTags.Items.DIRECTRICES); + this.copy( + HexTags.Blocks.MINDFLAYED_CIRCLE_COMPONENTS, HexTags.Items.MINDFLAYED_CIRCLE_COMPONENTS); + this.copy(BlockTags.LOGS_THAT_BURN, ItemTags.LOGS_THAT_BURN); + this.copy(BlockTags.LOGS, ItemTags.LOGS); + this.copy(BlockTags.PLANKS, ItemTags.PLANKS); + this.copy(BlockTags.SLABS, ItemTags.SLABS); + this.copy(BlockTags.WOODEN_SLABS, ItemTags.WOODEN_SLABS); + this.copy(BlockTags.DOORS, ItemTags.DOORS); + this.copy(BlockTags.WOODEN_DOORS, ItemTags.WOODEN_DOORS); + this.copy(BlockTags.TRAPDOORS, ItemTags.TRAPDOORS); + this.copy(BlockTags.WOODEN_TRAPDOORS, ItemTags.WOODEN_TRAPDOORS); + this.copy(BlockTags.LEAVES, ItemTags.LEAVES); + // Apparently, there's no "Pressure Plates" item tag. + this.copy(BlockTags.WOODEN_PRESSURE_PLATES, ItemTags.WOODEN_PRESSURE_PLATES); + this.copy(BlockTags.BUTTONS, ItemTags.BUTTONS); + this.copy(BlockTags.WOODEN_BUTTONS, ItemTags.WOODEN_BUTTONS); + } - void add(TagAppender<Item> appender, Item... items) { - for (Item item : items) { - appender.add(BuiltInRegistries.ITEM.getResourceKey(item).orElseThrow()); - } - } + void add(TagAppender<Item> appender, Item... items) { + for (Item item : items) { + appender.add(BuiltInRegistries.ITEM.getResourceKey(item).orElseThrow()); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/HexInterop.java b/Common/src/main/java/at/petrak/hexcasting/interop/HexInterop.java index 6ecbc2d40f..98b974e24d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/HexInterop.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/HexInterop.java @@ -6,74 +6,73 @@ import at.petrak.hexcasting.xplat.IClientXplatAbstractions; import at.petrak.hexcasting.xplat.IXplatAbstractions; import at.petrak.hexcasting.xplat.Platform; -import vazkii.patchouli.api.PatchouliAPI; - import java.util.List; +import vazkii.patchouli.api.PatchouliAPI; public class HexInterop { - public static final String PATCHOULI_ANY_INTEROP_FLAG = "hexcasting:any_interop"; - - public static final String PEHKUI_ID = "pehkui"; - - public static final class Forge { - public static final String CURIOS_API_ID = "curios"; - } - - public static final class Fabric { - public static final String TRINKETS_API_ID = "trinkets"; - } - - public static void init() { - initPatchouli(); - - IXplatAbstractions xplat = IXplatAbstractions.INSTANCE; - if (xplat.isModPresent(PEHKUI_ID)) { - PehkuiInterop.init(); - } - - xplat.initPlatformSpecific(); - - InlineHex.init(); - } - - public static void clientInit() { - IClientXplatAbstractions.INSTANCE.initPlatformSpecific(); - InlineHexClient.init(); - } - - private static void initPatchouli() { - var integrations = List.of(PEHKUI_ID); - - var anyInterop = false; - for (var id : integrations) { - if (IXplatAbstractions.INSTANCE.isModPresent(id)) { - anyInterop = true; - break; - } - } - - if (!anyInterop) { - List<String> platformSpecificIntegrations; - - Platform platform = IXplatAbstractions.INSTANCE.platform(); - if (platform == Platform.FORGE) { - platformSpecificIntegrations = List.of(); - } else if (platform == Platform.FABRIC) { - platformSpecificIntegrations = List.of(); - } else { - throw new UnsupportedOperationException(); - } - - for (var id : platformSpecificIntegrations) { - if (IXplatAbstractions.INSTANCE.isModPresent(id)) { - anyInterop = true; - break; - } - } - } - - if (anyInterop) { - PatchouliAPI.get().setConfigFlag(PATCHOULI_ANY_INTEROP_FLAG, true); - } - } + public static final String PATCHOULI_ANY_INTEROP_FLAG = "hexcasting:any_interop"; + + public static final String PEHKUI_ID = "pehkui"; + + public static final class Forge { + public static final String CURIOS_API_ID = "curios"; + } + + public static final class Fabric { + public static final String TRINKETS_API_ID = "trinkets"; + } + + public static void init() { + initPatchouli(); + + IXplatAbstractions xplat = IXplatAbstractions.INSTANCE; + if (xplat.isModPresent(PEHKUI_ID)) { + PehkuiInterop.init(); + } + + xplat.initPlatformSpecific(); + + InlineHex.init(); + } + + public static void clientInit() { + IClientXplatAbstractions.INSTANCE.initPlatformSpecific(); + InlineHexClient.init(); + } + + private static void initPatchouli() { + var integrations = List.of(PEHKUI_ID); + + var anyInterop = false; + for (var id : integrations) { + if (IXplatAbstractions.INSTANCE.isModPresent(id)) { + anyInterop = true; + break; + } + } + + if (!anyInterop) { + List<String> platformSpecificIntegrations; + + Platform platform = IXplatAbstractions.INSTANCE.platform(); + if (platform == Platform.FORGE) { + platformSpecificIntegrations = List.of(); + } else if (platform == Platform.FABRIC) { + platformSpecificIntegrations = List.of(); + } else { + throw new UnsupportedOperationException(); + } + + for (var id : platformSpecificIntegrations) { + if (IXplatAbstractions.INSTANCE.isModPresent(id)) { + anyInterop = true; + break; + } + } + } + + if (anyInterop) { + PatchouliAPI.get().setConfigFlag(PATCHOULI_ANY_INTEROP_FLAG, true); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/inline/HexPatternMatcher.java b/Common/src/main/java/at/petrak/hexcasting/interop/inline/HexPatternMatcher.java index 55af9756e8..d6f13fe3f7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/inline/HexPatternMatcher.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/inline/HexPatternMatcher.java @@ -8,98 +8,98 @@ import com.samsthenerd.inline.api.matching.MatchContext; import com.samsthenerd.inline.api.matching.MatcherInfo; import com.samsthenerd.inline.api.matching.RegexMatcher; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.MatchResult; +import java.util.regex.Pattern; +import javax.annotation.Nullable; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Style; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Tuple; import org.jetbrains.annotations.NotNull; -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.MatchResult; -import java.util.regex.Pattern; - public class HexPatternMatcher implements RegexMatcher { - private static final ResourceLocation patternMatcherID = HexAPI.modLoc("pattern"); - private static final MatcherInfo patternMatcherInfo = MatcherInfo.fromId(patternMatcherID); + private static final ResourceLocation patternMatcherID = HexAPI.modLoc("pattern"); + private static final MatcherInfo patternMatcherInfo = MatcherInfo.fromId(patternMatcherID); - // thx kyra <3 - private static final Pattern PATTERN_PATTERN_REGEX = Pattern.compile("(?<escaped>\\\\?)(?:HexPattern)?[<(\\[{]\\s*(?<direction>[a-zA-Z_-]+)(?:\\s*(?<sizemod>[,!+:; ])\\s*(?<pattern>[aqwedsAQWEDS]+)?)\\s*[>)\\]}]", Pattern.CASE_INSENSITIVE); + // thx kyra <3 + private static final Pattern PATTERN_PATTERN_REGEX = + Pattern.compile( + "(?<escaped>\\\\?)(?:HexPattern)?[<(\\[{]\\s*(?<direction>[a-zA-Z_-]+)(?:\\s*(?<sizemod>[,!+:; ])\\s*(?<pattern>[aqwedsAQWEDS]+)?)\\s*[>)\\]}]", + Pattern.CASE_INSENSITIVE); - public static HexPatternMatcher INSTANCE = new HexPatternMatcher(); + public static HexPatternMatcher INSTANCE = new HexPatternMatcher(); - public Pattern getRegex(){ - return PATTERN_PATTERN_REGEX; - } + public Pattern getRegex() { + return PATTERN_PATTERN_REGEX; + } - @Override - @NotNull - public Tuple<InlineMatch, Integer> getMatchAndGroup(MatchResult regexMatch, MatchContext ctx) { - String escaped = regexMatch.group(1); - String dirString = regexMatch.group(2).toLowerCase().strip().replace("_", ""); - String sizeModString = regexMatch.group(3); - String angleSigs = regexMatch.group(4); - if(escaped == null){ - return new Tuple<>(new InlineMatch.TextMatch(Component.literal("")), 1); - } - // need to convert dirString to a HexDir - HexDir dir = dirMap.get(dirString); - if(dir == null) - return new Tuple<>(null, 0); - HexPattern pat; - if(angleSigs == null){ - angleSigs = ""; - } - try{ - pat = HexPattern.fromAngles(angleSigs.toLowerCase(), dir); - InlinePatternData patData = new InlinePatternData(pat); - Style patDataStyle = patData.getExtraStyle(); - if(sizeModString != null && sizeModString.equals("+")) - patDataStyle = InlineAPI.INSTANCE.withSizeModifier(patDataStyle, 2); - if(sizeModString != null && sizeModString.equals("!")) - patDataStyle = InlineAPI.INSTANCE.withSizeModifier(patDataStyle, 1.5); - return new Tuple<>(new InlineMatch.DataMatch(patData,patDataStyle ), 0); - } catch (Exception e){ - return new Tuple<>(null, 0); - } - } + @Override + @NotNull public Tuple<InlineMatch, Integer> getMatchAndGroup(MatchResult regexMatch, MatchContext ctx) { + String escaped = regexMatch.group(1); + String dirString = regexMatch.group(2).toLowerCase().strip().replace("_", ""); + String sizeModString = regexMatch.group(3); + String angleSigs = regexMatch.group(4); + if (escaped == null) { + return new Tuple<>(new InlineMatch.TextMatch(Component.literal("")), 1); + } + // need to convert dirString to a HexDir + HexDir dir = dirMap.get(dirString); + if (dir == null) return new Tuple<>(null, 0); + HexPattern pat; + if (angleSigs == null) { + angleSigs = ""; + } + try { + pat = HexPattern.fromAngles(angleSigs.toLowerCase(), dir); + InlinePatternData patData = new InlinePatternData(pat); + Style patDataStyle = patData.getExtraStyle(); + if (sizeModString != null && sizeModString.equals("+")) + patDataStyle = InlineAPI.INSTANCE.withSizeModifier(patDataStyle, 2); + if (sizeModString != null && sizeModString.equals("!")) + patDataStyle = InlineAPI.INSTANCE.withSizeModifier(patDataStyle, 1.5); + return new Tuple<>(new InlineMatch.DataMatch(patData, patDataStyle), 0); + } catch (Exception e) { + return new Tuple<>(null, 0); + } + } - // not really used since we're doing escaping - @Override - @Nullable - public InlineMatch getMatch(MatchResult mr, MatchContext ctx){ - return null; // nop - } + // not really used since we're doing escaping + @Override + @Nullable public InlineMatch getMatch(MatchResult mr, MatchContext ctx) { + return null; // nop + } - public MatcherInfo getInfo(){ - return patternMatcherInfo; - } + public MatcherInfo getInfo() { + return patternMatcherInfo; + } - /** - * Get the ID for this matcher - * @return matcher's ID - */ - public ResourceLocation getId(){ - return patternMatcherID; - } + /** + * Get the ID for this matcher + * + * @return matcher's ID + */ + public ResourceLocation getId() { + return patternMatcherID; + } - private static final Map<String, HexDir> dirMap = new HashMap<>(); + private static final Map<String, HexDir> dirMap = new HashMap<>(); - static { - dirMap.put("northwest", HexDir.NORTH_WEST); - dirMap.put("west", HexDir.WEST); - dirMap.put("southwest", HexDir.SOUTH_WEST); - dirMap.put("southeast", HexDir.SOUTH_EAST); - dirMap.put("east", HexDir.EAST); - dirMap.put("northeast", HexDir.NORTH_EAST); - dirMap.put("nw", HexDir.NORTH_WEST); + static { + dirMap.put("northwest", HexDir.NORTH_WEST); + dirMap.put("west", HexDir.WEST); + dirMap.put("southwest", HexDir.SOUTH_WEST); + dirMap.put("southeast", HexDir.SOUTH_EAST); + dirMap.put("east", HexDir.EAST); + dirMap.put("northeast", HexDir.NORTH_EAST); + dirMap.put("nw", HexDir.NORTH_WEST); - dirMap.put("w", HexDir.WEST); - dirMap.put("sw", HexDir.SOUTH_WEST); - dirMap.put("se", HexDir.SOUTH_EAST); - dirMap.put("e", HexDir.EAST); - dirMap.put("ne", HexDir.NORTH_EAST); - } + dirMap.put("w", HexDir.WEST); + dirMap.put("sw", HexDir.SOUTH_WEST); + dirMap.put("se", HexDir.SOUTH_EAST); + dirMap.put("e", HexDir.EAST); + dirMap.put("ne", HexDir.NORTH_EAST); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlineHex.java b/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlineHex.java index fa9ce27a93..b48e754d05 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlineHex.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlineHex.java @@ -3,7 +3,7 @@ import com.samsthenerd.inline.api.InlineAPI; public class InlineHex { - public static void init(){ - InlineAPI.INSTANCE.addDataType(InlinePatternData.InlinePatternDataType.INSTANCE); - } + public static void init() { + InlineAPI.INSTANCE.addDataType(InlinePatternData.InlinePatternDataType.INSTANCE); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlineHexClient.java b/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlineHexClient.java index aa61b7e193..03d61d378e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlineHexClient.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlineHexClient.java @@ -4,8 +4,8 @@ public class InlineHexClient { - public static void init(){ - InlineClientAPI.INSTANCE.addMatcher(HexPatternMatcher.INSTANCE); - InlineClientAPI.INSTANCE.addRenderer(InlinePatternRenderer.INSTANCE); - } + public static void init() { + InlineClientAPI.INSTANCE.addMatcher(HexPatternMatcher.INSTANCE); + InlineClientAPI.INSTANCE.addRenderer(InlinePatternRenderer.INSTANCE); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlinePatternData.java b/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlinePatternData.java index 5dc2dba2ff..4058e9bbc8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlinePatternData.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlinePatternData.java @@ -17,73 +17,71 @@ import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.NotNull; -public class InlinePatternData implements InlineData<InlinePatternData>{ +public class InlinePatternData implements InlineData<InlinePatternData> { - public static final ResourceLocation rendererId = HexAPI.modLoc("pattern"); + public static final ResourceLocation rendererId = HexAPI.modLoc("pattern"); - @NotNull - public final HexPattern pattern; + @NotNull public final HexPattern pattern; - public InlinePatternData(@NotNull HexPattern pattern){ - this.pattern = pattern; - } + public InlinePatternData(@NotNull HexPattern pattern) { + this.pattern = pattern; + } - @Override - public InlinePatternDataType getType(){ - return InlinePatternDataType.INSTANCE; - } + @Override + public InlinePatternDataType getType() { + return InlinePatternDataType.INSTANCE; + } - @Override - public ResourceLocation getRendererId(){ - return rendererId; - } + @Override + public ResourceLocation getRendererId() { + return rendererId; + } - @Override - public Style getExtraStyle() { - ItemStack scrollStack = new ItemStack(HexItems.SCROLL_MEDIUM); - HexItems.SCROLL_MEDIUM.writeDatum(scrollStack, new PatternIota(pattern)); - scrollStack.setHoverName(getPatternName(pattern).copy().withStyle(ChatFormatting.WHITE)); - HoverEvent he = new HoverEvent(HoverEvent.Action.SHOW_ITEM, new HoverEvent.ItemStackInfo(scrollStack)); - ClickEvent ce = new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, pattern.toString()); - return Style.EMPTY.withHoverEvent(he).withClickEvent(ce); - } + @Override + public Style getExtraStyle() { + ItemStack scrollStack = new ItemStack(HexItems.SCROLL_MEDIUM); + HexItems.SCROLL_MEDIUM.writeDatum(scrollStack, new PatternIota(pattern)); + scrollStack.setHoverName(getPatternName(pattern).copy().withStyle(ChatFormatting.WHITE)); + HoverEvent he = + new HoverEvent(HoverEvent.Action.SHOW_ITEM, new HoverEvent.ItemStackInfo(scrollStack)); + ClickEvent ce = new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, pattern.toString()); + return Style.EMPTY.withHoverEvent(he).withClickEvent(ce); + } - public static Component getPatternName(HexPattern pattern){ - try { - PatternShapeMatch shapeMatch = PatternRegistryManifest.matchPattern(pattern, null, false); - if(shapeMatch instanceof PatternShapeMatch.Normal normMatch){ - return HexAPI.instance().getActionI18n(normMatch.key, false); - } - // TODO: this doesn't actually ever hit because it errors out with server castinv env stuff first :( - if(shapeMatch instanceof PatternShapeMatch.Special specialMatch){ - return HexAPI.instance().getSpecialHandlerI18n(specialMatch.key); - } - } catch (Exception e){ - // nop - } - return PatternIota.displayNonInline(pattern); - } + public static Component getPatternName(HexPattern pattern) { + try { + PatternShapeMatch shapeMatch = PatternRegistryManifest.matchPattern(pattern, null, false); + if (shapeMatch instanceof PatternShapeMatch.Normal normMatch) { + return HexAPI.instance().getActionI18n(normMatch.key, false); + } + // TODO: this doesn't actually ever hit because it errors out with server castinv env stuff + // first :( + if (shapeMatch instanceof PatternShapeMatch.Special specialMatch) { + return HexAPI.instance().getSpecialHandlerI18n(specialMatch.key); + } + } catch (Exception e) { + // nop + } + return PatternIota.displayNonInline(pattern); + } - @Override - public Component asText(boolean withExtra) { - return Component.literal(pattern.toString()).withStyle(asStyle(withExtra)); - } + @Override + public Component asText(boolean withExtra) { + return Component.literal(pattern.toString()).withStyle(asStyle(withExtra)); + } - public static class InlinePatternDataType implements InlineDataType<InlinePatternData> { - private static final ResourceLocation ID = new ResourceLocation(HexAPI.MOD_ID, "pattern"); - public static final InlinePatternDataType INSTANCE = new InlinePatternDataType(); + public static class InlinePatternDataType implements InlineDataType<InlinePatternData> { + private static final ResourceLocation ID = new ResourceLocation(HexAPI.MOD_ID, "pattern"); + public static final InlinePatternDataType INSTANCE = new InlinePatternDataType(); - @Override - public ResourceLocation getId(){ - return ID; - } + @Override + public ResourceLocation getId() { + return ID; + } - @Override - public Codec<InlinePatternData> getCodec(){ - return HexPattern.CODEC.xmap( - InlinePatternData::new, - data -> data.pattern - ); - } - } + @Override + public Codec<InlinePatternData> getCodec() { + return HexPattern.CODEC.xmap(InlinePatternData::new, data -> data.pattern); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlinePatternRenderer.java b/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlinePatternRenderer.java index eb7b798487..92684d0139 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlinePatternRenderer.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/inline/InlinePatternRenderer.java @@ -10,73 +10,106 @@ public class InlinePatternRenderer implements InlineRenderer<InlinePatternData> { - public static final InlinePatternRenderer INSTANCE = new InlinePatternRenderer(); + public static final InlinePatternRenderer INSTANCE = new InlinePatternRenderer(); - public ResourceLocation getId(){ - return InlinePatternData.rendererId; - } + public ResourceLocation getId() { + return InlinePatternData.rendererId; + } - public static final PatternSettings INLINE_SETTINGS = new PatternSettings("inline", - new PatternSettings.PositionSettings(1.0, 9.0, 0, 0.5, - PatternSettings.AxisAlignment.CENTER, PatternSettings.AxisAlignment.CENTER_FIT, 4.0, 0, 0), - PatternSettings.StrokeSettings.fromStroke(1.0), - new PatternSettings.ZappySettings(10, 0, 0, 0, - PatternSettings.ZappySettings.READABLE_OFFSET, 0.7f) - ){ - @Override - public double getOuterWidth(double scale){ - if(scale >= 1) return 1; - if(scale >= 0.75) return 0.75; - if(scale >= 0.5) return 0.5; - return 0.25; - } - }; + public static final PatternSettings INLINE_SETTINGS = + new PatternSettings( + "inline", + new PatternSettings.PositionSettings( + 1.0, + 9.0, + 0, + 0.5, + PatternSettings.AxisAlignment.CENTER, + PatternSettings.AxisAlignment.CENTER_FIT, + 4.0, + 0, + 0), + PatternSettings.StrokeSettings.fromStroke(1.0), + new PatternSettings.ZappySettings( + 10, 0, 0, 0, PatternSettings.ZappySettings.READABLE_OFFSET, 0.7f)) { + @Override + public double getOuterWidth(double scale) { + if (scale >= 1) return 1; + if (scale >= 0.75) return 0.75; + if (scale >= 0.5) return 0.5; + return 0.25; + } + }; - public static final PatternSettings INLINE_SETTINGS_GLOWY = new PatternSettings("inlineglowy", - new PatternSettings.PositionSettings(1.0, 11.0, 0, 0.5, - PatternSettings.AxisAlignment.CENTER, PatternSettings.AxisAlignment.CENTER_FIT, 4.0, 0, 0), - new PatternSettings.StrokeSettings(1, 3, 0.8 * 1 * 2.0 / 5.0, 0.4 * 1 * 2.0 / 5.0), - INLINE_SETTINGS.zapSets - ){ - @Override - public double getInnerWidth(double scale){ - if(scale >= 1) return 1; - if(scale >= 0.75) return 0.75; - if(scale >= 0.5) return 0.5; - return 0.25; - } - }; + public static final PatternSettings INLINE_SETTINGS_GLOWY = + new PatternSettings( + "inlineglowy", + new PatternSettings.PositionSettings( + 1.0, + 11.0, + 0, + 0.5, + PatternSettings.AxisAlignment.CENTER, + PatternSettings.AxisAlignment.CENTER_FIT, + 4.0, + 0, + 0), + new PatternSettings.StrokeSettings(1, 3, 0.8 * 1 * 2.0 / 5.0, 0.4 * 1 * 2.0 / 5.0), + INLINE_SETTINGS.zapSets) { + @Override + public double getInnerWidth(double scale) { + if (scale >= 1) return 1; + if (scale >= 0.75) return 0.75; + if (scale >= 0.5) return 0.5; + return 0.25; + } + }; - @Override - public GlowHandling getGlowPreference(InlinePatternData forData) { - return new GlowHandling.None(); - } + @Override + public GlowHandling getGlowPreference(InlinePatternData forData) { + return new GlowHandling.None(); + } - public static final int INLINE_TEXTURE_RES = 16; // 128px so it looks good and pretty on up close signs and whatnot + public static final int INLINE_TEXTURE_RES = + 16; // 128px so it looks good and pretty on up close signs and whatnot - public int render(InlinePatternData data, GuiGraphics drawContext, int index, Style style, int codepoint, TextRenderingContext trContext){ - if(trContext.isGlowy()) return charWidth(data, style, codepoint); - int glowyParentColor = ((InlineStyle) style).getComponent(InlineStyle.GLOWY_PARENT_COMP); - boolean isGlowy = glowyParentColor != -1; - drawContext.pose().pushPose(); - drawContext.pose().translate(isGlowy ? -1f : 0, isGlowy ? -1.5f : -0.5f, 0f); - int color = trContext.usableColor(); - PatternRenderer.renderPattern(data.pattern, drawContext.pose(), new PatternRenderer.WorldlyBits(drawContext.bufferSource(), trContext.light(), null), - isGlowy ? INLINE_SETTINGS_GLOWY : INLINE_SETTINGS, - isGlowy ? new PatternColors(color, 0xFF_000000 | glowyParentColor) : PatternColors.singleStroke(color), - 0, INLINE_TEXTURE_RES); + public int render( + InlinePatternData data, + GuiGraphics drawContext, + int index, + Style style, + int codepoint, + TextRenderingContext trContext) { + if (trContext.isGlowy()) return charWidth(data, style, codepoint); + int glowyParentColor = ((InlineStyle) style).getComponent(InlineStyle.GLOWY_PARENT_COMP); + boolean isGlowy = glowyParentColor != -1; + drawContext.pose().pushPose(); + drawContext.pose().translate(isGlowy ? -1f : 0, isGlowy ? -1.5f : -0.5f, 0f); + int color = trContext.usableColor(); + PatternRenderer.renderPattern( + data.pattern, + drawContext.pose(), + new PatternRenderer.WorldlyBits(drawContext.bufferSource(), trContext.light(), null), + isGlowy ? INLINE_SETTINGS_GLOWY : INLINE_SETTINGS, + isGlowy + ? new PatternColors(color, 0xFF_000000 | glowyParentColor) + : PatternColors.singleStroke(color), + 0, + INLINE_TEXTURE_RES); - drawContext.pose().popPose(); - return charWidth(data, style, codepoint); - } + drawContext.pose().popPose(); + return charWidth(data, style, codepoint); + } - public int charWidth(InlinePatternData data, Style style, int codepoint){ + public int charWidth(InlinePatternData data, Style style, int codepoint) { - HexPatternPoints staticPoints = HexPatternPoints.getStaticPoints(HexPatternLike.of(data.pattern), INLINE_SETTINGS, 0); + HexPatternPoints staticPoints = + HexPatternPoints.getStaticPoints(HexPatternLike.of(data.pattern), INLINE_SETTINGS, 0); - double baseScale = 4.0 / 1.5; - double baseHeight = staticPoints.rangeY * baseScale; + double baseScale = 4.0 / 1.5; + double baseHeight = staticPoints.rangeY * baseScale; - return (int)Math.ceil(Math.min(baseHeight, 8.0) * staticPoints.rangeX / staticPoints.rangeY) + 1; // (+2 for padding) - } + return (int) Math.ceil(Math.min(baseHeight, 8.0) * staticPoints.rangeX / staticPoints.rangeY) + + 1; // (+2 for padding) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/AbstractPatternComponent.java b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/AbstractPatternComponent.java index 997bb09411..0854cd8884 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/AbstractPatternComponent.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/AbstractPatternComponent.java @@ -5,86 +5,95 @@ import at.petrak.hexcasting.client.render.PatternRenderer; import at.petrak.hexcasting.client.render.PatternSettings; import com.mojang.blaze3d.vertex.PoseStack; +import java.util.List; +import java.util.function.UnaryOperator; import net.minecraft.client.gui.GuiGraphics; import vazkii.patchouli.api.IComponentRenderContext; import vazkii.patchouli.api.ICustomComponent; import vazkii.patchouli.api.IVariable; -import java.util.List; -import java.util.function.UnaryOperator; - -/** - * Page that has a hex pattern on it - */ -abstract public class AbstractPatternComponent implements ICustomComponent { - protected transient int x, y; - protected transient float hexSize; - - private transient List<HexPattern> patterns; - - /** - * Pass -1, -1 to center it. - */ - @Override - public void build(int x, int y, int pagenum) { - this.x = x == -1 ? 116 / 2 : x; - this.y = y == -1 ? 70 : y; - } - - public abstract List<HexPattern> getPatterns(UnaryOperator<IVariable> lookup); - - public abstract boolean showStrokeOrder(); - - @Override - public void render(GuiGraphics graphics, IComponentRenderContext context, float pticks, int mouseX, int mouseY) { - PoseStack ps = graphics.pose(); - // want to position x: [0, 116], y: [16, 80] - ps.pushPose(); - - int cols = (int)Math.ceil(Math.sqrt(patterns.size())); - int rows = (int)Math.ceil(patterns.size()/(double)cols); - - double cellW = 116 / (double)cols; - double cellH = 64 / (double)rows; - - PatternSettings patSets = new PatternSettings("book" + patterns.size() + (showStrokeOrder() ? "" : "r"), - new PatternSettings.PositionSettings(cellW, cellH, 2, 2, - PatternSettings.AxisAlignment.CENTER_FIT, PatternSettings.AxisAlignment.CENTER_FIT, 16, 0, 0), - PatternSettings.StrokeSettings.fromStroke(4), - showStrokeOrder() ? PatternSettings.ZappySettings.READABLE : PatternSettings.ZappySettings.STATIC - ); - - PatternColors patCols = PatternColors.DIMMED_COLOR.withDots(false, true); - - if(showStrokeOrder()){ - patCols = PatternRenderer.shouldDoStrokeGradient() ? PatternColors.DEFAULT_GRADIENT_COLOR.withDots(true, true) - : PatternColors.READABLE_GRID_SCROLL_COLORS; - } - - for(int p = 0; p < patterns.size(); p++){ - - int r = p / cols; - int c = p % cols; - HexPattern pattern = patterns.get(p); - - ps.pushPose(); - ps.translate(cellW * c, cellH * r + 16, 100); - - PatternRenderer.renderPattern(pattern, graphics.pose(), patSets, patCols, 0, 4); - ps.popPose(); - } - ps.popPose(); - } - - @Override - public void onVariablesAvailable(UnaryOperator<IVariable> lookup) { - this.patterns = this.getPatterns(lookup); - } - - // used for deserialization from patchi - protected static class RawPattern { - protected String startdir; - protected String signature; - protected int q, r; - } +/** Page that has a hex pattern on it */ +public abstract class AbstractPatternComponent implements ICustomComponent { + protected transient int x, y; + protected transient float hexSize; + + private transient List<HexPattern> patterns; + + /** Pass -1, -1 to center it. */ + @Override + public void build(int x, int y, int pagenum) { + this.x = x == -1 ? 116 / 2 : x; + this.y = y == -1 ? 70 : y; + } + + public abstract List<HexPattern> getPatterns(UnaryOperator<IVariable> lookup); + + public abstract boolean showStrokeOrder(); + + @Override + public void render( + GuiGraphics graphics, IComponentRenderContext context, float pticks, int mouseX, int mouseY) { + PoseStack ps = graphics.pose(); + // want to position x: [0, 116], y: [16, 80] + ps.pushPose(); + + int cols = (int) Math.ceil(Math.sqrt(patterns.size())); + int rows = (int) Math.ceil(patterns.size() / (double) cols); + + double cellW = 116 / (double) cols; + double cellH = 64 / (double) rows; + + PatternSettings patSets = + new PatternSettings( + "book" + patterns.size() + (showStrokeOrder() ? "" : "r"), + new PatternSettings.PositionSettings( + cellW, + cellH, + 2, + 2, + PatternSettings.AxisAlignment.CENTER_FIT, + PatternSettings.AxisAlignment.CENTER_FIT, + 16, + 0, + 0), + PatternSettings.StrokeSettings.fromStroke(4), + showStrokeOrder() + ? PatternSettings.ZappySettings.READABLE + : PatternSettings.ZappySettings.STATIC); + + PatternColors patCols = PatternColors.DIMMED_COLOR.withDots(false, true); + + if (showStrokeOrder()) { + patCols = + PatternRenderer.shouldDoStrokeGradient() + ? PatternColors.DEFAULT_GRADIENT_COLOR.withDots(true, true) + : PatternColors.READABLE_GRID_SCROLL_COLORS; + } + + for (int p = 0; p < patterns.size(); p++) { + + int r = p / cols; + int c = p % cols; + HexPattern pattern = patterns.get(p); + + ps.pushPose(); + ps.translate(cellW * c, cellH * r + 16, 100); + + PatternRenderer.renderPattern(pattern, graphics.pose(), patSets, patCols, 0, 4); + ps.popPose(); + } + ps.popPose(); + } + + @Override + public void onVariablesAvailable(UnaryOperator<IVariable> lookup) { + this.patterns = this.getPatterns(lookup); + } + + // used for deserialization from patchi + protected static class RawPattern { + protected String startdir; + protected String signature; + protected int q, r; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/BrainsweepProcessor.java b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/BrainsweepProcessor.java index ada9cc4165..7caf8d89c4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/BrainsweepProcessor.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/BrainsweepProcessor.java @@ -3,7 +3,6 @@ import at.petrak.hexcasting.common.recipe.BrainsweepRecipe; import at.petrak.hexcasting.common.recipe.HexRecipeStuffRegistry; import net.minecraft.client.Minecraft; -import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; @@ -16,8 +15,7 @@ public class BrainsweepProcessor implements IComponentProcessor { private BrainsweepRecipe recipe; - @Nullable - private String exampleEntityString; + @Nullable private String exampleEntityString; @Override public void setup(Level level, IVariableProvider vars) { @@ -71,11 +69,10 @@ public IVariable process(Level level, String key) { } case "entityTooltip" -> { Minecraft mc = Minecraft.getInstance(); - return IVariable.wrapList(this.recipe.entityIn() - .getTooltip(mc.options.advancedItemTooltips) - .stream() - .map(IVariable::from) - .toList()); + return IVariable.wrapList( + this.recipe.entityIn().getTooltip(mc.options.advancedItemTooltips).stream() + .map(IVariable::from) + .toList()); } default -> { return null; diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/CustomComponentTooltip.java b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/CustomComponentTooltip.java index 13972ce372..f30f9ce999 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/CustomComponentTooltip.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/CustomComponentTooltip.java @@ -1,47 +1,46 @@ package at.petrak.hexcasting.interop.patchouli; import com.google.gson.annotations.SerializedName; -import com.mojang.blaze3d.vertex.PoseStack; +import java.util.ArrayList; +import java.util.List; +import java.util.function.UnaryOperator; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; import vazkii.patchouli.api.IComponentRenderContext; import vazkii.patchouli.api.ICustomComponent; import vazkii.patchouli.api.IVariable; -import java.util.ArrayList; -import java.util.List; -import java.util.function.UnaryOperator; - public class CustomComponentTooltip implements ICustomComponent { - int width, height; - - @SerializedName("tooltip") - IVariable tooltipReference; - - transient IVariable tooltipVar; - transient List<Component> tooltip; - - transient int x, y; - - @Override - public void build(int componentX, int componentY, int pageNum) { - x = componentX; - y = componentY; - tooltip = new ArrayList<>(); - for (IVariable s : tooltipVar.asListOrSingleton()) { - tooltip.add(s.as(Component.class)); - } - } - - @Override - public void render(GuiGraphics graphics, IComponentRenderContext context, float pticks, int mouseX, int mouseY) { - if (context.isAreaHovered(mouseX, mouseY, x, y, width, height)) { - context.setHoverTooltipComponents(tooltip); - } - } - - @Override - public void onVariablesAvailable(UnaryOperator<IVariable> lookup) { - tooltipVar = lookup.apply(tooltipReference); - } + int width, height; + + @SerializedName("tooltip") + IVariable tooltipReference; + + transient IVariable tooltipVar; + transient List<Component> tooltip; + + transient int x, y; + + @Override + public void build(int componentX, int componentY, int pageNum) { + x = componentX; + y = componentY; + tooltip = new ArrayList<>(); + for (IVariable s : tooltipVar.asListOrSingleton()) { + tooltip.add(s.as(Component.class)); + } + } + + @Override + public void render( + GuiGraphics graphics, IComponentRenderContext context, float pticks, int mouseX, int mouseY) { + if (context.isAreaHovered(mouseX, mouseY, x, y, width, height)) { + context.setHoverTooltipComponents(tooltip); + } + } + + @Override + public void onVariablesAvailable(UnaryOperator<IVariable> lookup) { + tooltipVar = lookup.apply(tooltipReference); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/LookupPatternComponent.java b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/LookupPatternComponent.java index 632c7abf79..1e32aa87e5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/LookupPatternComponent.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/LookupPatternComponent.java @@ -4,43 +4,44 @@ import at.petrak.hexcasting.api.mod.HexTags; import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.google.gson.annotations.SerializedName; +import java.util.List; +import java.util.function.UnaryOperator; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import vazkii.patchouli.api.IVariable; -import java.util.List; -import java.util.function.UnaryOperator; - -/** - * Grab the pattern from the registry - */ +/** Grab the pattern from the registry */ public class LookupPatternComponent extends AbstractPatternComponent { - @SerializedName("op_id") - public String opNameRaw; - - protected ResourceLocation opName; - protected boolean strokeOrder; - - @Override - public List<HexPattern> getPatterns(UnaryOperator<IVariable> lookup) { - var key = ResourceKey.create(IXplatAbstractions.INSTANCE.getActionRegistry().key(), this.opName); - var entry = IXplatAbstractions.INSTANCE.getActionRegistry().get(key); - - this.strokeOrder = - !IXplatAbstractions.INSTANCE.getActionRegistry().getHolderOrThrow(key).is(HexTags.Actions.PER_WORLD_PATTERN); - return List.of(entry.prototype()); - } - - @Override - public boolean showStrokeOrder() { - return this.strokeOrder; - } - - @Override - public void onVariablesAvailable(UnaryOperator<IVariable> lookup) { - var opName = lookup.apply(IVariable.wrap(this.opNameRaw)).asString(); - this.opName = ResourceLocation.tryParse(opName); - - super.onVariablesAvailable(lookup); - } + @SerializedName("op_id") + public String opNameRaw; + + protected ResourceLocation opName; + protected boolean strokeOrder; + + @Override + public List<HexPattern> getPatterns(UnaryOperator<IVariable> lookup) { + var key = + ResourceKey.create(IXplatAbstractions.INSTANCE.getActionRegistry().key(), this.opName); + var entry = IXplatAbstractions.INSTANCE.getActionRegistry().get(key); + + this.strokeOrder = + !IXplatAbstractions.INSTANCE + .getActionRegistry() + .getHolderOrThrow(key) + .is(HexTags.Actions.PER_WORLD_PATTERN); + return List.of(entry.prototype()); + } + + @Override + public boolean showStrokeOrder() { + return this.strokeOrder; + } + + @Override + public void onVariablesAvailable(UnaryOperator<IVariable> lookup) { + var opName = lookup.apply(IVariable.wrap(this.opNameRaw)).asString(); + this.opName = ResourceLocation.tryParse(opName); + + super.onVariablesAvailable(lookup); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/ManualPatternComponent.java b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/ManualPatternComponent.java index 06f77903ba..e0576f3b3a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/ManualPatternComponent.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/ManualPatternComponent.java @@ -5,50 +5,48 @@ import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.annotations.SerializedName; -import vazkii.patchouli.api.IVariable; - import java.util.ArrayList; import java.util.List; import java.util.function.UnaryOperator; +import vazkii.patchouli.api.IVariable; -/** - * Provide the pattern(s) manually - */ +/** Provide the pattern(s) manually */ public class ManualPatternComponent extends AbstractPatternComponent { - @SerializedName("patterns") - public String patternsRaw; - @SerializedName("stroke_order") - public String strokeOrderRaw; - - protected transient boolean strokeOrder; - - @Override - public List<HexPattern> getPatterns(UnaryOperator<IVariable> lookup) { - this.strokeOrder = lookup.apply(IVariable.wrap(this.strokeOrderRaw)).asBoolean(true); - var patsRaw = lookup.apply(IVariable.wrap(patternsRaw)).asListOrSingleton(); - - var out = new ArrayList<HexPattern>(); - for (var ivar : patsRaw) { - JsonElement json = ivar.unwrap(); - RawPattern raw = new Gson().fromJson(json, RawPattern.class); - - var dir = HexDir.fromString(raw.startdir); - var pat = HexPattern.fromAngles(raw.signature, dir); - out.add(pat); - } - - return out; - } - - @Override - public boolean showStrokeOrder() { - return this.strokeOrder; - } - - @Override - public void onVariablesAvailable(UnaryOperator<IVariable> lookup) { - this.strokeOrder = IVariable.wrap(this.strokeOrderRaw).asBoolean(true); - - super.onVariablesAvailable(lookup); - } + @SerializedName("patterns") + public String patternsRaw; + + @SerializedName("stroke_order") + public String strokeOrderRaw; + + protected transient boolean strokeOrder; + + @Override + public List<HexPattern> getPatterns(UnaryOperator<IVariable> lookup) { + this.strokeOrder = lookup.apply(IVariable.wrap(this.strokeOrderRaw)).asBoolean(true); + var patsRaw = lookup.apply(IVariable.wrap(patternsRaw)).asListOrSingleton(); + + var out = new ArrayList<HexPattern>(); + for (var ivar : patsRaw) { + JsonElement json = ivar.unwrap(); + RawPattern raw = new Gson().fromJson(json, RawPattern.class); + + var dir = HexDir.fromString(raw.startdir); + var pat = HexPattern.fromAngles(raw.signature, dir); + out.add(pat); + } + + return out; + } + + @Override + public boolean showStrokeOrder() { + return this.strokeOrder; + } + + @Override + public void onVariablesAvailable(UnaryOperator<IVariable> lookup) { + this.strokeOrder = IVariable.wrap(this.strokeOrderRaw).asBoolean(true); + + super.onVariablesAvailable(lookup); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/MultiCraftingProcessor.java b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/MultiCraftingProcessor.java index 055128b7a5..d53d3fe876 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/MultiCraftingProcessor.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/MultiCraftingProcessor.java @@ -9,6 +9,9 @@ package at.petrak.hexcasting.interop.patchouli; import at.petrak.hexcasting.api.HexAPI; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; import net.minecraft.core.NonNullList; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.crafting.CraftingRecipe; @@ -20,80 +23,81 @@ import vazkii.patchouli.api.IVariable; import vazkii.patchouli.api.IVariableProvider; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - public class MultiCraftingProcessor implements IComponentProcessor { - private List<CraftingRecipe> recipes; - private boolean shapeless = true; - private int longestIngredientSize = 0; - private boolean hasCustomHeading; + private List<CraftingRecipe> recipes; + private boolean shapeless = true; + private int longestIngredientSize = 0; + private boolean hasCustomHeading; - @Override - public void setup(Level level, IVariableProvider vars) { - List<String> names = vars.get("recipes").asStream().map(IVariable::asString).collect(Collectors.toList()); - this.recipes = new ArrayList<>(); - for (String name : names) { - CraftingRecipe recipe = PatchouliUtils.getRecipe(RecipeType.CRAFTING, new ResourceLocation(name)); - if (recipe != null) { - recipes.add(recipe); - if (shapeless) { - shapeless = !(recipe instanceof ShapedRecipe); - } - for (Ingredient ingredient : recipe.getIngredients()) { - int size = ingredient.getItems().length; - if (longestIngredientSize < size) { - longestIngredientSize = size; - } - } - } else { - HexAPI.LOGGER.warn("Missing crafting recipe " + name); - } - } - this.hasCustomHeading = vars.has("heading"); - } + @Override + public void setup(Level level, IVariableProvider vars) { + List<String> names = + vars.get("recipes").asStream().map(IVariable::asString).collect(Collectors.toList()); + this.recipes = new ArrayList<>(); + for (String name : names) { + CraftingRecipe recipe = + PatchouliUtils.getRecipe(RecipeType.CRAFTING, new ResourceLocation(name)); + if (recipe != null) { + recipes.add(recipe); + if (shapeless) { + shapeless = !(recipe instanceof ShapedRecipe); + } + for (Ingredient ingredient : recipe.getIngredients()) { + int size = ingredient.getItems().length; + if (longestIngredientSize < size) { + longestIngredientSize = size; + } + } + } else { + HexAPI.LOGGER.warn("Missing crafting recipe " + name); + } + } + this.hasCustomHeading = vars.has("heading"); + } - @Override - public IVariable process(Level level, String key) { - if (recipes.isEmpty()) { - return null; - } - if (key.equals("heading")) { - if (!hasCustomHeading) { - return IVariable.from(recipes.get(0).getResultItem(level.registryAccess()).getHoverName()); - } - return null; - } - if (key.startsWith("input")) { - int index = Integer.parseInt(key.substring(5)) - 1; - int shapedX = index % 3; - int shapedY = index / 3; - List<Ingredient> ingredients = new ArrayList<>(); - for (CraftingRecipe recipe : recipes) { - if (recipe instanceof ShapedRecipe shaped) { - if (shaped.getWidth() < shapedX + 1) { - ingredients.add(Ingredient.EMPTY); - } else { - int realIndex = index - (shapedY * (3 - shaped.getWidth())); - NonNullList<Ingredient> list = recipe.getIngredients(); - ingredients.add(list.size() > realIndex ? list.get(realIndex) : Ingredient.EMPTY); - } + @Override + public IVariable process(Level level, String key) { + if (recipes.isEmpty()) { + return null; + } + if (key.equals("heading")) { + if (!hasCustomHeading) { + return IVariable.from(recipes.get(0).getResultItem(level.registryAccess()).getHoverName()); + } + return null; + } + if (key.startsWith("input")) { + int index = Integer.parseInt(key.substring(5)) - 1; + int shapedX = index % 3; + int shapedY = index / 3; + List<Ingredient> ingredients = new ArrayList<>(); + for (CraftingRecipe recipe : recipes) { + if (recipe instanceof ShapedRecipe shaped) { + if (shaped.getWidth() < shapedX + 1) { + ingredients.add(Ingredient.EMPTY); + } else { + int realIndex = index - (shapedY * (3 - shaped.getWidth())); + NonNullList<Ingredient> list = recipe.getIngredients(); + ingredients.add(list.size() > realIndex ? list.get(realIndex) : Ingredient.EMPTY); + } - } else { - NonNullList<Ingredient> list = recipe.getIngredients(); - ingredients.add(list.size() > index ? list.get(index) : Ingredient.EMPTY); - } - } - return PatchouliUtils.interweaveIngredients(ingredients, longestIngredientSize); - } - if (key.equals("output")) { - return IVariable.wrapList( - recipes.stream().map(recipe -> recipe.getResultItem(level.registryAccess())).map(IVariable::from).collect(Collectors.toList())); - } - if (key.equals("shapeless")) { - return IVariable.wrap(shapeless); - } - return null; - } + } else { + NonNullList<Ingredient> list = recipe.getIngredients(); + ingredients.add(list.size() > index ? list.get(index) : Ingredient.EMPTY); + } + } + return PatchouliUtils.interweaveIngredients(ingredients, longestIngredientSize); + } + if (key.equals("output")) { + return IVariable.wrapList( + recipes.stream() + .map(recipe -> recipe.getResultItem(level.registryAccess())) + .map(IVariable::from) + .collect(Collectors.toList())); + } + if (key.equals("shapeless")) { + return IVariable.wrap(shapeless); + } + return null; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/PatchouliUtils.java b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/PatchouliUtils.java index 574b296e1b..87270e3a8e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/PatchouliUtils.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/PatchouliUtils.java @@ -1,5 +1,9 @@ package at.petrak.hexcasting.interop.patchouli; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; import net.minecraft.client.Minecraft; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.Container; @@ -9,68 +13,62 @@ import net.minecraft.world.item.crafting.RecipeType; import vazkii.patchouli.api.IVariable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - /** - * > no this is a "literally copy these files/parts of file into your mod" - * > we should put this in patchy but lol - * > lazy - * -- Hubry Vazcord + * > no this is a "literally copy these files/parts of file into your mod" > we should put this in + * patchy but lol > lazy -- Hubry Vazcord */ public class PatchouliUtils { - @SuppressWarnings("unchecked") - public static <T extends Recipe<C>, C extends Container> T getRecipe(RecipeType<T> type, ResourceLocation id) { - // PageDoubleRecipeRegistry - if (Minecraft.getInstance().level == null) { - return null; - } else { - var manager = Minecraft.getInstance().level.getRecipeManager(); - return (T) manager.byKey(id) - .filter((recipe) -> recipe.getType() == type).orElse(null); - } - } + @SuppressWarnings("unchecked") + public static <T extends Recipe<C>, C extends Container> T getRecipe( + RecipeType<T> type, ResourceLocation id) { + // PageDoubleRecipeRegistry + if (Minecraft.getInstance().level == null) { + return null; + } else { + var manager = Minecraft.getInstance().level.getRecipeManager(); + return (T) manager.byKey(id).filter((recipe) -> recipe.getType() == type).orElse(null); + } + } - /** - * Combines the ingredients, returning the first matching stack of each, then the second stack of each, etc. - * looping back ingredients that run out of matched stacks, until the ingredients reach the length - * of the longest ingredient in the recipe set. - * - * @param ingredients List of ingredients in the specific slot - * @param longestIngredientSize Longest ingredient in the entire recipe - * @return Serialized Patchouli ingredient string - */ - public static IVariable interweaveIngredients(List<Ingredient> ingredients, int longestIngredientSize) { - if (ingredients.size() == 1) { - return IVariable.wrapList(Arrays.stream(ingredients.get(0).getItems()).map(IVariable::from).collect( - Collectors.toList())); - } + /** + * Combines the ingredients, returning the first matching stack of each, then the second stack of + * each, etc. looping back ingredients that run out of matched stacks, until the ingredients reach + * the length of the longest ingredient in the recipe set. + * + * @param ingredients List of ingredients in the specific slot + * @param longestIngredientSize Longest ingredient in the entire recipe + * @return Serialized Patchouli ingredient string + */ + public static IVariable interweaveIngredients( + List<Ingredient> ingredients, int longestIngredientSize) { + if (ingredients.size() == 1) { + return IVariable.wrapList( + Arrays.stream(ingredients.get(0).getItems()) + .map(IVariable::from) + .collect(Collectors.toList())); + } - ItemStack[] empty = {ItemStack.EMPTY}; - List<ItemStack[]> stacks = new ArrayList<>(); - for (Ingredient ingredient : ingredients) { - if (ingredient != null && !ingredient.isEmpty()) { - stacks.add(ingredient.getItems()); - } else { - stacks.add(empty); - } - } - List<IVariable> list = new ArrayList<>(stacks.size() * longestIngredientSize); - for (int i = 0; i < longestIngredientSize; i++) { - for (ItemStack[] stack : stacks) { - list.add(IVariable.from(stack[i % stack.length])); - } - } - return IVariable.wrapList(list); - } + ItemStack[] empty = {ItemStack.EMPTY}; + List<ItemStack[]> stacks = new ArrayList<>(); + for (Ingredient ingredient : ingredients) { + if (ingredient != null && !ingredient.isEmpty()) { + stacks.add(ingredient.getItems()); + } else { + stacks.add(empty); + } + } + List<IVariable> list = new ArrayList<>(stacks.size() * longestIngredientSize); + for (int i = 0; i < longestIngredientSize; i++) { + for (ItemStack[] stack : stacks) { + list.add(IVariable.from(stack[i % stack.length])); + } + } + return IVariable.wrapList(list); + } - /** - * Overload of the method above that uses the provided list's longest ingredient size. - */ - public static IVariable interweaveIngredients(List<Ingredient> ingredients) { - return interweaveIngredients(ingredients, - ingredients.stream().mapToInt(ingr -> ingr.getItems().length).max().orElse(1)); - } + /** Overload of the method above that uses the provided list's longest ingredient size. */ + public static IVariable interweaveIngredients(List<Ingredient> ingredients) { + return interweaveIngredients( + ingredients, ingredients.stream().mapToInt(ingr -> ingr.getItems().length).max().orElse(1)); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/PatternProcessor.java b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/PatternProcessor.java index 94e9e258b8..e8edd13cdb 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/PatternProcessor.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/patchouli/PatternProcessor.java @@ -7,28 +7,27 @@ import vazkii.patchouli.api.IVariableProvider; public class PatternProcessor implements IComponentProcessor { - private String translationKey; + private String translationKey; - @Override - public void setup(Level level, IVariableProvider vars) { - if (vars.has("header")) - translationKey = vars.get("header").asString(); - else { - IVariable key = vars.get("op_id"); - String opName = key.asString(); + @Override + public void setup(Level level, IVariableProvider vars) { + if (vars.has("header")) translationKey = vars.get("header").asString(); + else { + IVariable key = vars.get("op_id"); + String opName = key.asString(); - String prefix = "hexcasting.action."; - boolean hasOverride = I18n.exists(prefix + "book." + opName); - translationKey = prefix + (hasOverride ? "book." : "") + opName; - } - } + String prefix = "hexcasting.action."; + boolean hasOverride = I18n.exists(prefix + "book." + opName); + translationKey = prefix + (hasOverride ? "book." : "") + opName; + } + } - @Override - public IVariable process(Level level, String key) { - if (key.equals("translation_key")) { - return IVariable.wrap(translationKey); - } + @Override + public IVariable process(Level level, String key) { + if (key.equals("translation_key")) { + return IVariable.wrap(translationKey); + } - return null; - } + return null; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpGetScale.kt b/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpGetScale.kt index d1a9868c51..27ca5da5ae 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpGetScale.kt +++ b/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpGetScale.kt @@ -8,11 +8,11 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.xplat.IXplatAbstractions object OpGetScale : ConstMediaAction { - override val argc = 1 + override val argc = 1 - override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { - val target = args.getEntity(0, argc) - env.assertEntityInRange(target) - return IXplatAbstractions.INSTANCE.pehkuiApi.getScale(target).toDouble().asActionResult - } + override fun execute(args: List<Iota>, env: CastingEnvironment): List<Iota> { + val target = args.getEntity(0, argc) + env.assertEntityInRange(target) + return IXplatAbstractions.INSTANCE.pehkuiApi.getScale(target).toDouble().asActionResult + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpSetScale.kt b/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpSetScale.kt index 9c171c5784..e8ceabfcce 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpSetScale.kt +++ b/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpSetScale.kt @@ -11,26 +11,23 @@ import at.petrak.hexcasting.xplat.IXplatAbstractions import net.minecraft.world.entity.Entity object OpSetScale : SpellAction { - override val argc = 2 + override val argc = 2 - override fun execute( - args: List<Iota>, - env: CastingEnvironment - ): SpellAction.Result { - val target = args.getEntity(0, argc) - val scale = args.getDoubleBetween(1, 1.0 / 32.0, 8.0, argc) - env.assertEntityInRange(target) + override fun execute(args: List<Iota>, env: CastingEnvironment): SpellAction.Result { + val target = args.getEntity(0, argc) + val scale = args.getDoubleBetween(1, 1.0 / 32.0, 8.0, argc) + env.assertEntityInRange(target) - return SpellAction.Result( - Spell(target, scale), - 50_000, - listOf(ParticleSpray.burst(target.position(), scale, 40)) - ) - } + return SpellAction.Result( + Spell(target, scale), + 50_000, + listOf(ParticleSpray.burst(target.position(), scale, 40)) + ) + } - private data class Spell(val target: Entity, val scale: Double) : RenderedSpell { - override fun cast(env: CastingEnvironment) { - IXplatAbstractions.INSTANCE.pehkuiApi.setScale(target, scale.toFloat()) - } - } -} \ No newline at end of file + private data class Spell(val target: Entity, val scale: Double) : RenderedSpell { + override fun cast(env: CastingEnvironment) { + IXplatAbstractions.INSTANCE.pehkuiApi.setScale(target, scale.toFloat()) + } + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/PehkuiInterop.java b/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/PehkuiInterop.java index 8f89517e1e..c00dd1efea 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/PehkuiInterop.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/PehkuiInterop.java @@ -5,20 +5,18 @@ import net.minecraft.world.entity.Entity; public class PehkuiInterop { - public static void init() { - // for future work - } + public static void init() { + // for future work + } - public static boolean isActive() { - return IXplatAbstractions.INSTANCE.isModPresent(HexInterop.PEHKUI_ID); - } + public static boolean isActive() { + return IXplatAbstractions.INSTANCE.isModPresent(HexInterop.PEHKUI_ID); + } - /** - * Pehkui doesn't publish an API jar so we do this BS - */ - public interface ApiAbstraction { - float getScale(Entity e); + /** Pehkui doesn't publish an API jar so we do this BS */ + public interface ApiAbstraction { + float getScale(Entity e); - void setScale(Entity e, float scale); - } + void setScale(Entity e, float scale); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/utils/PatternDrawingUtil.java b/Common/src/main/java/at/petrak/hexcasting/interop/utils/PatternDrawingUtil.java index 0829937b58..a95901c5cb 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/utils/PatternDrawingUtil.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/utils/PatternDrawingUtil.java @@ -6,123 +6,142 @@ import at.petrak.hexcasting.client.render.RenderLib; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.datafixers.util.Pair; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.util.FastColor; import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec2; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; - public final class PatternDrawingUtil { - public static void drawPattern(GuiGraphics graphics, int x, int y, List<PatternEntry> patterns, List<Vec2> dots, - boolean strokeOrder, int outer, int innerLight, int innerDark, - int dotColor) { - var poseStack = graphics.pose(); - poseStack.pushPose(); - poseStack.translate(x, y, 1); - var mat = poseStack.last().pose(); - var prevShader = RenderSystem.getShader(); - RenderSystem.setShader(GameRenderer::getPositionColorShader); -// RenderSystem.disableDepthTest(); - RenderSystem.disableCull(); - RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); - - // mark center -// RenderLib.drawSpot(mat, Vec2.ZERO, 0f, 0f, 0f, 1f); - - for (var pat : patterns) { - RenderLib.drawLineSeq(mat, pat.zappyPoints(), 5f, 0, outer, outer); - RenderLib.drawLineSeq(mat, pat.zappyPoints(), 2f, 0, - strokeOrder ? innerDark : innerLight, innerLight); - - if (strokeOrder) { - RenderLib.drawSpot(mat, pat.zappyPoints().get(0), 2.5f, 1f, 0.1f, 0.15f, 0.6f); - } - } - - float dotR = FastColor.ARGB32.red(dotColor) / 255f; - float dotG = FastColor.ARGB32.green(dotColor) / 255f; - float dotB = FastColor.ARGB32.blue(dotColor) / 255f; - float dotA = FastColor.ARGB32.alpha(dotColor) / 255f; - - for (var dot : dots) { - RenderLib.drawSpot(mat, dot, 1.5f, dotR, dotG, dotB, dotA); - } - - RenderSystem.defaultBlendFunc(); - RenderSystem.setShader(() -> prevShader); - - RenderSystem.enableCull(); - - poseStack.popPose(); - } - - public static PatternRenderingData loadPatterns(List<Pair<HexPattern, HexCoord>> patterns, - float readabilityOffset, float lastLineLenProp) { - var patternEntries = new ArrayList<PatternEntry>(patterns.size()); - - var fakeScale = 1; - var seenFakePoints = new ArrayList<Vec2>(); - var seenCoords = new HashSet<HexCoord>(); - for (var pair : patterns) { - var pattern = pair.getFirst(); - var origin = pair.getSecond(); - for (var pos : pattern.positions(origin)) { - var px = HexUtils.coordToPx(pos, fakeScale, Vec2.ZERO); - seenFakePoints.add(px); - } - - // And while we're looping add the (COORD ONLY) things internally - patternEntries.add(new PatternEntry(pattern, origin, new ArrayList<>())); - seenCoords.addAll(pattern.positions(origin)); - } - var fakeCom = HexUtils.findCenter(seenFakePoints); - - var maxDx = -1f; - var maxDy = -1f; - for (var dot : seenFakePoints) { - var dx = Mth.abs(dot.x - fakeCom.x); - if (dx > maxDx) { - maxDx = dx; - } - var dy = Mth.abs(dot.y - fakeCom.y); - if (dy > maxDy) { - maxDy = dy; - } - } - var hexSize = Math.min(12, Math.min(120 / 2.5f / maxDx, 70 / 2.5f / maxDy)); - - var seenRealPoints = new ArrayList<Vec2>(); - for (var pat : patternEntries) { - for (var pos : pat.pattern().positions(pat.origin())) { - var px = HexUtils.coordToPx(pos, hexSize, Vec2.ZERO); - seenRealPoints.add(px); - } - } - var realCom = HexUtils.findCenter(seenRealPoints); - - // and NOW for real! - for (int i = 0; i < patternEntries.size(); i++) { - PatternEntry pat = patternEntries.get(i); - var localOrigin = HexUtils.coordToPx(pat.origin(), hexSize, realCom.negated()); - var points = pat.pattern().toLines(hexSize, localOrigin); - pat.zappyPoints() - .addAll(RenderLib.makeZappy(points, RenderLib.findDupIndices(pat.pattern().positions()), 10, 0.8f, 0f, - 0f, readabilityOffset, lastLineLenProp, i)); - } - - var pathfinderDots = seenCoords.stream() - .map(coord -> HexUtils.coordToPx(coord, hexSize, realCom.negated())).toList(); - - return new PatternRenderingData(patternEntries, pathfinderDots, hexSize); - } - - public record PatternRenderingData(List<PatternEntry> patterns, List<Vec2> pathfinderDots, float hexSize) { - // NO-OP - } + public static void drawPattern( + GuiGraphics graphics, + int x, + int y, + List<PatternEntry> patterns, + List<Vec2> dots, + boolean strokeOrder, + int outer, + int innerLight, + int innerDark, + int dotColor) { + var poseStack = graphics.pose(); + poseStack.pushPose(); + poseStack.translate(x, y, 1); + var mat = poseStack.last().pose(); + var prevShader = RenderSystem.getShader(); + RenderSystem.setShader(GameRenderer::getPositionColorShader); + // RenderSystem.disableDepthTest(); + RenderSystem.disableCull(); + RenderSystem.blendFunc( + GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + + // mark center + // RenderLib.drawSpot(mat, Vec2.ZERO, 0f, 0f, 0f, 1f); + + for (var pat : patterns) { + RenderLib.drawLineSeq(mat, pat.zappyPoints(), 5f, 0, outer, outer); + RenderLib.drawLineSeq( + mat, pat.zappyPoints(), 2f, 0, strokeOrder ? innerDark : innerLight, innerLight); + + if (strokeOrder) { + RenderLib.drawSpot(mat, pat.zappyPoints().get(0), 2.5f, 1f, 0.1f, 0.15f, 0.6f); + } + } + + float dotR = FastColor.ARGB32.red(dotColor) / 255f; + float dotG = FastColor.ARGB32.green(dotColor) / 255f; + float dotB = FastColor.ARGB32.blue(dotColor) / 255f; + float dotA = FastColor.ARGB32.alpha(dotColor) / 255f; + + for (var dot : dots) { + RenderLib.drawSpot(mat, dot, 1.5f, dotR, dotG, dotB, dotA); + } + + RenderSystem.defaultBlendFunc(); + RenderSystem.setShader(() -> prevShader); + + RenderSystem.enableCull(); + + poseStack.popPose(); + } + + public static PatternRenderingData loadPatterns( + List<Pair<HexPattern, HexCoord>> patterns, float readabilityOffset, float lastLineLenProp) { + var patternEntries = new ArrayList<PatternEntry>(patterns.size()); + + var fakeScale = 1; + var seenFakePoints = new ArrayList<Vec2>(); + var seenCoords = new HashSet<HexCoord>(); + for (var pair : patterns) { + var pattern = pair.getFirst(); + var origin = pair.getSecond(); + for (var pos : pattern.positions(origin)) { + var px = HexUtils.coordToPx(pos, fakeScale, Vec2.ZERO); + seenFakePoints.add(px); + } + + // And while we're looping add the (COORD ONLY) things internally + patternEntries.add(new PatternEntry(pattern, origin, new ArrayList<>())); + seenCoords.addAll(pattern.positions(origin)); + } + var fakeCom = HexUtils.findCenter(seenFakePoints); + + var maxDx = -1f; + var maxDy = -1f; + for (var dot : seenFakePoints) { + var dx = Mth.abs(dot.x - fakeCom.x); + if (dx > maxDx) { + maxDx = dx; + } + var dy = Mth.abs(dot.y - fakeCom.y); + if (dy > maxDy) { + maxDy = dy; + } + } + var hexSize = Math.min(12, Math.min(120 / 2.5f / maxDx, 70 / 2.5f / maxDy)); + + var seenRealPoints = new ArrayList<Vec2>(); + for (var pat : patternEntries) { + for (var pos : pat.pattern().positions(pat.origin())) { + var px = HexUtils.coordToPx(pos, hexSize, Vec2.ZERO); + seenRealPoints.add(px); + } + } + var realCom = HexUtils.findCenter(seenRealPoints); + + // and NOW for real! + for (int i = 0; i < patternEntries.size(); i++) { + PatternEntry pat = patternEntries.get(i); + var localOrigin = HexUtils.coordToPx(pat.origin(), hexSize, realCom.negated()); + var points = pat.pattern().toLines(hexSize, localOrigin); + pat.zappyPoints() + .addAll( + RenderLib.makeZappy( + points, + RenderLib.findDupIndices(pat.pattern().positions()), + 10, + 0.8f, + 0f, + 0f, + readabilityOffset, + lastLineLenProp, + i)); + } + + var pathfinderDots = + seenCoords.stream() + .map(coord -> HexUtils.coordToPx(coord, hexSize, realCom.negated())) + .toList(); + + return new PatternRenderingData(patternEntries, pathfinderDots, hexSize); + } + + public record PatternRenderingData( + List<PatternEntry> patterns, List<Vec2> pathfinderDots, float hexSize) { + // NO-OP + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/utils/PatternEntry.java b/Common/src/main/java/at/petrak/hexcasting/interop/utils/PatternEntry.java index b2c717d126..ad15beb871 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/utils/PatternEntry.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/utils/PatternEntry.java @@ -2,10 +2,9 @@ import at.petrak.hexcasting.api.casting.math.HexCoord; import at.petrak.hexcasting.api.casting.math.HexPattern; -import net.minecraft.world.phys.Vec2; - import java.util.List; +import net.minecraft.world.phys.Vec2; public record PatternEntry(HexPattern pattern, HexCoord origin, List<Vec2> zappyPoints) { - // NO-OP + // NO-OP } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/utils/PhialRecipeStackBuilder.java b/Common/src/main/java/at/petrak/hexcasting/interop/utils/PhialRecipeStackBuilder.java index 42ccb38dec..035f1a6000 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/utils/PhialRecipeStackBuilder.java +++ b/Common/src/main/java/at/petrak/hexcasting/interop/utils/PhialRecipeStackBuilder.java @@ -7,64 +7,62 @@ import at.petrak.hexcasting.common.lib.HexItems; import com.google.common.collect.Lists; import com.mojang.datafixers.util.Pair; +import java.util.List; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import java.util.List; - public class PhialRecipeStackBuilder { - private static ItemStack makeBattery(long unit, int size) { - return ItemMediaBattery.withMedia(new ItemStack(HexItems.BATTERY), unit * size, unit * size); - } - - public static Pair<List<ItemStack>, List<ItemStack>> createStacks() { - List<ItemStack> inputItems = Lists.newArrayList(); - List<ItemStack> outputItems = Lists.newArrayList(); + private static ItemStack makeBattery(long unit, int size) { + return ItemMediaBattery.withMedia(new ItemStack(HexItems.BATTERY), unit * size, unit * size); + } - long dust = HexConfig.common().dustMediaAmount(); - long shard = HexConfig.common().shardMediaAmount(); - long charged = HexConfig.common().chargedCrystalMediaAmount(); - long quenchedShard = MediaConstants.QUENCHED_SHARD_UNIT; - long quenchedBlock = MediaConstants.QUENCHED_BLOCK_UNIT; + public static Pair<List<ItemStack>, List<ItemStack>> createStacks() { + List<ItemStack> inputItems = Lists.newArrayList(); + List<ItemStack> outputItems = Lists.newArrayList(); + long dust = HexConfig.common().dustMediaAmount(); + long shard = HexConfig.common().shardMediaAmount(); + long charged = HexConfig.common().chargedCrystalMediaAmount(); + long quenchedShard = MediaConstants.QUENCHED_SHARD_UNIT; + long quenchedBlock = MediaConstants.QUENCHED_BLOCK_UNIT; - if (dust > 0) { - inputItems.add(new ItemStack(HexItems.AMETHYST_DUST, 1)); - outputItems.add(makeBattery(dust, 1)); - inputItems.add(new ItemStack(HexItems.AMETHYST_DUST, 64)); - outputItems.add(makeBattery(dust, 64)); - } + if (dust > 0) { + inputItems.add(new ItemStack(HexItems.AMETHYST_DUST, 1)); + outputItems.add(makeBattery(dust, 1)); + inputItems.add(new ItemStack(HexItems.AMETHYST_DUST, 64)); + outputItems.add(makeBattery(dust, 64)); + } - if (shard > 0) { - inputItems.add(new ItemStack(Items.AMETHYST_SHARD, 1)); - outputItems.add(makeBattery(shard, 1)); - inputItems.add(new ItemStack(Items.AMETHYST_SHARD, 64)); - outputItems.add(makeBattery(shard, 64)); - } + if (shard > 0) { + inputItems.add(new ItemStack(Items.AMETHYST_SHARD, 1)); + outputItems.add(makeBattery(shard, 1)); + inputItems.add(new ItemStack(Items.AMETHYST_SHARD, 64)); + outputItems.add(makeBattery(shard, 64)); + } - if (charged > 0) { - inputItems.add(new ItemStack(HexItems.CHARGED_AMETHYST, 1)); - outputItems.add(makeBattery(charged, 1)); - inputItems.add(new ItemStack(HexItems.CHARGED_AMETHYST, 64)); - outputItems.add(makeBattery(charged, 64)); - } + if (charged > 0) { + inputItems.add(new ItemStack(HexItems.CHARGED_AMETHYST, 1)); + outputItems.add(makeBattery(charged, 1)); + inputItems.add(new ItemStack(HexItems.CHARGED_AMETHYST, 64)); + outputItems.add(makeBattery(charged, 64)); + } - inputItems.add(new ItemStack(HexItems.QUENCHED_SHARD, 1)); - outputItems.add(makeBattery(quenchedShard, 1)); - inputItems.add(new ItemStack(HexItems.QUENCHED_SHARD, 64)); - outputItems.add(makeBattery(quenchedShard, 64)); + inputItems.add(new ItemStack(HexItems.QUENCHED_SHARD, 1)); + outputItems.add(makeBattery(quenchedShard, 1)); + inputItems.add(new ItemStack(HexItems.QUENCHED_SHARD, 64)); + outputItems.add(makeBattery(quenchedShard, 64)); - inputItems.add(new ItemStack(HexBlocks.QUENCHED_ALLAY, 1)); - outputItems.add(makeBattery(quenchedBlock, 1)); - inputItems.add(new ItemStack(HexBlocks.QUENCHED_ALLAY, 64)); - outputItems.add(makeBattery(quenchedBlock, 64)); + inputItems.add(new ItemStack(HexBlocks.QUENCHED_ALLAY, 1)); + outputItems.add(makeBattery(quenchedBlock, 1)); + inputItems.add(new ItemStack(HexBlocks.QUENCHED_ALLAY, 64)); + outputItems.add(makeBattery(quenchedBlock, 64)); - return new Pair<>(inputItems, outputItems); - } + return new Pair<>(inputItems, outputItems); + } - public static boolean shouldAddRecipe() { - return HexConfig.common().dustMediaAmount() > 0 || - HexConfig.common().shardMediaAmount() > 0 || - HexConfig.common().chargedCrystalMediaAmount() > 0; - } + public static boolean shouldAddRecipe() { + return HexConfig.common().dustMediaAmount() > 0 + || HexConfig.common().shardMediaAmount() > 0 + || HexConfig.common().chargedCrystalMediaAmount() > 0; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/ktxt/AccessorWrappers.kt b/Common/src/main/java/at/petrak/hexcasting/ktxt/AccessorWrappers.kt index c14653190c..9aca0c016d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/ktxt/AccessorWrappers.kt +++ b/Common/src/main/java/at/petrak/hexcasting/ktxt/AccessorWrappers.kt @@ -1,4 +1,5 @@ @file:JvmName("AccessorWrappers") + package at.petrak.hexcasting.ktxt import at.petrak.hexcasting.mixin.accessor.AccessorEntity @@ -18,23 +19,36 @@ import net.minecraft.world.level.Level import net.minecraft.world.phys.BlockHitResult var LivingEntity.lastHurt: Float - get() = (this as AccessorLivingEntity).`hex$getLastHurt`() - set(value) = (this as AccessorLivingEntity).`hex$setLastHurt`(value) + get() = (this as AccessorLivingEntity).`hex$getLastHurt`() + set(value) = (this as AccessorLivingEntity).`hex$setLastHurt`(value) + +fun LivingEntity.playHurtSound(source: DamageSource) = + (this as AccessorLivingEntity).`hex$playHurtSound`(source) + +fun LivingEntity.checkTotemDeathProtection(source: DamageSource) = + (this as AccessorLivingEntity).`hex$checkTotemDeathProtection`(source) -fun LivingEntity.playHurtSound(source: DamageSource) = (this as AccessorLivingEntity).`hex$playHurtSound`(source) -fun LivingEntity.checkTotemDeathProtection(source: DamageSource) = (this as AccessorLivingEntity).`hex$checkTotemDeathProtection`(source) -val LivingEntity.deathSoundAccessor: SoundEvent? get() = (this as AccessorLivingEntity).`hex$getDeathSound`() -val LivingEntity.soundVolumeAccessor get() = (this as AccessorLivingEntity).`hex$getSoundVolume`() +val LivingEntity.deathSoundAccessor: SoundEvent? + get() = (this as AccessorLivingEntity).`hex$getDeathSound`() +val LivingEntity.soundVolumeAccessor + get() = (this as AccessorLivingEntity).`hex$getSoundVolume`() -fun LivingEntity.setHurtWithStamp(source: DamageSource, stamp: Long) = (this as AccessorLivingEntity).apply { - `hex$setLastDamageSource`(source) - `hex$setLastDamageStamp`(stamp) -} +fun LivingEntity.setHurtWithStamp(source: DamageSource, stamp: Long) = + (this as AccessorLivingEntity).apply { + `hex$setLastDamageSource`(source) + `hex$setLastDamageStamp`(stamp) + } fun Entity.markHurt() = (this as AccessorEntity).`hex$markHurt`() -fun Villager.tellWitnessesThatIWasMurdered(murderer: Entity) = (this as AccessorVillager).`hex$tellWitnessesThatIWasMurdered`(murderer) +fun Villager.tellWitnessesThatIWasMurdered(murderer: Entity) = + (this as AccessorVillager).`hex$tellWitnessesThatIWasMurdered`(murderer) @Suppress("FunctionName") -fun UseOnContext(level: Level, player: Player?, hand: InteractionHand, stack: ItemStack, hitResult: BlockHitResult): UseOnContext = - AccessorUseOnContext.`hex$new`(level, player, hand, stack, hitResult) +fun UseOnContext( + level: Level, + player: Player?, + hand: InteractionHand, + stack: ItemStack, + hitResult: BlockHitResult +): UseOnContext = AccessorUseOnContext.`hex$new`(level, player, hand, stack, hitResult) diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/MixinAbstractVillager.java b/Common/src/main/java/at/petrak/hexcasting/mixin/MixinAbstractVillager.java index 344e60efcb..abcb3de164 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/MixinAbstractVillager.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/MixinAbstractVillager.java @@ -11,11 +11,11 @@ // Prevents the villager from having any offers if it's brainswept @Mixin(AbstractVillager.class) public class MixinAbstractVillager { - @Inject(method = "getOffers", at = @At("HEAD"), cancellable = true) - private void nixOffers(CallbackInfoReturnable<MerchantOffers> cir) { - var self = (AbstractVillager) (Object) this; - if (IXplatAbstractions.INSTANCE.isBrainswept(self)) { - cir.setReturnValue(new MerchantOffers()); - } - } + @Inject(method = "getOffers", at = @At("HEAD"), cancellable = true) + private void nixOffers(CallbackInfoReturnable<MerchantOffers> cir) { + var self = (AbstractVillager) (Object) this; + if (IXplatAbstractions.INSTANCE.isBrainswept(self)) { + cir.setReturnValue(new MerchantOffers()); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/MixinLivingEntity.java b/Common/src/main/java/at/petrak/hexcasting/mixin/MixinLivingEntity.java index c3dbc47b81..743449bfa6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/MixinLivingEntity.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/MixinLivingEntity.java @@ -12,13 +12,13 @@ // Nuke the brain at the source @Mixin(LivingEntity.class) public abstract class MixinLivingEntity { - @Inject(method = "getBrain", at = @At("RETURN")) - private void removeBrain(CallbackInfoReturnable<Brain<?>> cir) { - var self = (LivingEntity) (Object) this; - if (self instanceof Mob mob && IXplatAbstractions.INSTANCE.isBrainswept(mob)) { - var brain = cir.getReturnValue(); - brain.removeAllBehaviors(); - cir.setReturnValue(brain); - } - } + @Inject(method = "getBrain", at = @At("RETURN")) + private void removeBrain(CallbackInfoReturnable<Brain<?>> cir) { + var self = (LivingEntity) (Object) this; + if (self instanceof Mob mob && IXplatAbstractions.INSTANCE.isBrainswept(mob)) { + var brain = cir.getReturnValue(); + brain.removeAllBehaviors(); + cir.setReturnValue(brain); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/MixinMob.java b/Common/src/main/java/at/petrak/hexcasting/mixin/MixinMob.java index 9404606e8c..bb1c242e86 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/MixinMob.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/MixinMob.java @@ -10,19 +10,19 @@ // Prevents brainswept mobs from having an AI tick @Mixin(Mob.class) public class MixinMob { - @Inject(method = "serverAiStep", at = @At("HEAD"), cancellable = true) - private void onRegisterBrainGoals(CallbackInfo ci) { - var self = (Mob) (Object) this; - if (IXplatAbstractions.INSTANCE.isBrainswept(self)) { - ci.cancel(); - } - } + @Inject(method = "serverAiStep", at = @At("HEAD"), cancellable = true) + private void onRegisterBrainGoals(CallbackInfo ci) { + var self = (Mob) (Object) this; + if (IXplatAbstractions.INSTANCE.isBrainswept(self)) { + ci.cancel(); + } + } - @Inject(method = "playAmbientSound", at = @At("HEAD"), cancellable = true) - protected void onPlayAmbientSound(CallbackInfo ci) { - var self = (Mob) (Object) this; - if (IXplatAbstractions.INSTANCE.isBrainswept(self)) { - ci.cancel(); - } - } + @Inject(method = "playAmbientSound", at = @At("HEAD"), cancellable = true) + protected void onPlayAmbientSound(CallbackInfo ci) { + var self = (Mob) (Object) this; + if (IXplatAbstractions.INSTANCE.isBrainswept(self)) { + ci.cancel(); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/MixinRaider.java b/Common/src/main/java/at/petrak/hexcasting/mixin/MixinRaider.java index cb1d92eda8..dce8fe7835 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/MixinRaider.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/MixinRaider.java @@ -9,10 +9,12 @@ // Prevents the witch from joining a raid @Mixin(Raider.class) public class MixinRaider { - @Redirect(method = "aiStep", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/raid/Raider;isAlive" + - "()Z")) - private boolean isAliveForAiPurposes(Raider instance) { - var self = (Raider) (Object) this; - return self.isAlive() && !IXplatAbstractions.INSTANCE.isBrainswept(self); - } + @Redirect( + method = "aiStep", + at = + @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/raid/Raider;isAlive" + "()Z")) + private boolean isAliveForAiPurposes(Raider instance) { + var self = (Raider) (Object) this; + return self.isAlive() && !IXplatAbstractions.INSTANCE.isBrainswept(self); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/MixinVillager.java b/Common/src/main/java/at/petrak/hexcasting/mixin/MixinVillager.java index 4f577f7246..fa80fea4ea 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/MixinVillager.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/MixinVillager.java @@ -11,19 +11,19 @@ // Prevents the villager from any of its brain goals @Mixin(Villager.class) public class MixinVillager { - @Inject(method = "canBreed", at = @At("HEAD"), cancellable = true) - private void preventBreeding(CallbackInfoReturnable<Boolean> cir) { - var self = (Villager) (Object) this; - if (IXplatAbstractions.INSTANCE.isBrainswept(self)) { - cir.setReturnValue(false); - } - } + @Inject(method = "canBreed", at = @At("HEAD"), cancellable = true) + private void preventBreeding(CallbackInfoReturnable<Boolean> cir) { + var self = (Villager) (Object) this; + if (IXplatAbstractions.INSTANCE.isBrainswept(self)) { + cir.setReturnValue(false); + } + } - @Inject(method = "setUnhappy", at = @At("HEAD"), cancellable = true) - private void preventUnhappiness(CallbackInfo ci) { - var self = (Villager) (Object) this; - if (IXplatAbstractions.INSTANCE.isBrainswept(self)) { - ci.cancel(); - } - } + @Inject(method = "setUnhappy", at = @At("HEAD"), cancellable = true) + private void preventUnhappiness(CallbackInfo ci) { + var self = (Villager) (Object) this; + if (IXplatAbstractions.INSTANCE.isBrainswept(self)) { + ci.cancel(); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/MixinWitch.java b/Common/src/main/java/at/petrak/hexcasting/mixin/MixinWitch.java index fe23cebeb8..0eead5a180 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/MixinWitch.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/MixinWitch.java @@ -9,10 +9,14 @@ // Prevents the witch from drinking potions @Mixin(Witch.class) public class MixinWitch { - @Redirect(method = "aiStep", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/Witch;" + - "isAlive()Z")) - private boolean isAliveForAiPurposes(Witch instance) { - var self = (Witch) (Object) this; - return self.isAlive() && !IXplatAbstractions.INSTANCE.isBrainswept(self); - } + @Redirect( + method = "aiStep", + at = + @At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/monster/Witch;" + "isAlive()Z")) + private boolean isAliveForAiPurposes(Witch instance) { + var self = (Witch) (Object) this; + return self.isAlive() && !IXplatAbstractions.INSTANCE.isBrainswept(self); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorAbstractArrow.java b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorAbstractArrow.java index b956033d3b..50e504e4db 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorAbstractArrow.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorAbstractArrow.java @@ -6,6 +6,6 @@ @Mixin(AbstractArrow.class) public interface AccessorAbstractArrow { - @Accessor("inGround") - boolean hex$isInGround(); + @Accessor("inGround") + boolean hex$isInGround(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorEntity.java b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorEntity.java index 691669853b..b83d91d9f9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorEntity.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorEntity.java @@ -6,6 +6,6 @@ @Mixin(Entity.class) public interface AccessorEntity { - @Invoker("markHurt") - void hex$markHurt(); + @Invoker("markHurt") + void hex$markHurt(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorLivingEntity.java b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorLivingEntity.java index fde107fc87..1cbe05174d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorLivingEntity.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorLivingEntity.java @@ -9,27 +9,27 @@ @Mixin(LivingEntity.class) public interface AccessorLivingEntity { - @Accessor("lastHurt") - float hex$getLastHurt(); + @Accessor("lastHurt") + float hex$getLastHurt(); - @Accessor("lastHurt") - void hex$setLastHurt(float lastHurt); + @Accessor("lastHurt") + void hex$setLastHurt(float lastHurt); - @Invoker("playHurtSound") - void hex$playHurtSound(DamageSource source); + @Invoker("playHurtSound") + void hex$playHurtSound(DamageSource source); - @Invoker("checkTotemDeathProtection") - boolean hex$checkTotemDeathProtection(DamageSource source); + @Invoker("checkTotemDeathProtection") + boolean hex$checkTotemDeathProtection(DamageSource source); - @Invoker("getDeathSound") - SoundEvent hex$getDeathSound(); + @Invoker("getDeathSound") + SoundEvent hex$getDeathSound(); - @Invoker("getSoundVolume") - float hex$getSoundVolume(); + @Invoker("getSoundVolume") + float hex$getSoundVolume(); - @Accessor("lastDamageSource") - void hex$setLastDamageSource(DamageSource source); + @Accessor("lastDamageSource") + void hex$setLastDamageSource(DamageSource source); - @Accessor("lastDamageStamp") - void hex$setLastDamageStamp(long stamp); + @Accessor("lastDamageStamp") + void hex$setLastDamageStamp(long stamp); } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorLootTable.java b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorLootTable.java index d2be3c734d..922513fa0c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorLootTable.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorLootTable.java @@ -1,5 +1,6 @@ package at.petrak.hexcasting.mixin.accessor; +import java.util.function.BiFunction; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootTable; @@ -8,18 +9,16 @@ import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.gen.Accessor; -import java.util.function.BiFunction; - @Mixin(LootTable.class) public interface AccessorLootTable { - @Accessor("functions") - LootItemFunction[] hex$getFunctions(); + @Accessor("functions") + LootItemFunction[] hex$getFunctions(); - @Accessor("functions") - @Mutable - void hex$setFunctions(LootItemFunction[] lifs); + @Accessor("functions") + @Mutable + void hex$setFunctions(LootItemFunction[] lifs); - @Accessor("compositeFunction") - @Mutable - void hex$setCompositeFunction(BiFunction<ItemStack, LootContext, ItemStack> bf); + @Accessor("compositeFunction") + @Mutable + void hex$setCompositeFunction(BiFunction<ItemStack, LootContext, ItemStack> bf); } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorPotionBrewing.java b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorPotionBrewing.java index 88fe176a12..5e86fb7584 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorPotionBrewing.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorPotionBrewing.java @@ -8,7 +8,6 @@ @Mixin(PotionBrewing.class) public interface AccessorPotionBrewing { - @Invoker("addMix") - static void addMix(Potion p_43514_, Item p_43515_, Potion p_43516_) { - } + @Invoker("addMix") + static void addMix(Potion p_43514_, Item p_43515_, Potion p_43516_) {} } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorUseOnContext.java b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorUseOnContext.java index 1cf59b94a9..8af45feb18 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorUseOnContext.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorUseOnContext.java @@ -1,5 +1,6 @@ package at.petrak.hexcasting.mixin.accessor; +import javax.annotation.Nullable; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; @@ -9,13 +10,11 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; -import javax.annotation.Nullable; - @Mixin(UseOnContext.class) public interface AccessorUseOnContext { - @Invoker("<init>") - static UseOnContext hex$new(Level $$0, @Nullable Player $$1, InteractionHand $$2, ItemStack $$3, - BlockHitResult $$4) { - throw new IllegalStateException(); - } + @Invoker("<init>") + static UseOnContext hex$new( + Level $$0, @Nullable Player $$1, InteractionHand $$2, ItemStack $$3, BlockHitResult $$4) { + throw new IllegalStateException(); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorVillager.java b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorVillager.java index dc03602412..997e58fcde 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorVillager.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/AccessorVillager.java @@ -7,9 +7,9 @@ @Mixin(Villager.class) public interface AccessorVillager { - @Invoker("tellWitnessesThatIWasMurdered") - void hex$tellWitnessesThatIWasMurdered(Entity murderer); + @Invoker("tellWitnessesThatIWasMurdered") + void hex$tellWitnessesThatIWasMurdered(Entity murderer); - @Invoker("releaseAllPois") - void hex$releaseAllPois(); + @Invoker("releaseAllPois") + void hex$releaseAllPois(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/CriteriaTriggersAccessor.java b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/CriteriaTriggersAccessor.java index 5aaf071208..b3b621e224 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/CriteriaTriggersAccessor.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/CriteriaTriggersAccessor.java @@ -7,8 +7,8 @@ @Mixin(CriteriaTriggers.class) public interface CriteriaTriggersAccessor { - @Invoker("register") - static <T extends CriterionTrigger<?>> T hex$register(T trigger) { - throw new UnsupportedOperationException(); - } + @Invoker("register") + static <T extends CriterionTrigger<?>> T hex$register(T trigger) { + throw new UnsupportedOperationException(); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorBlockEntityRenderDispatcher.java b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorBlockEntityRenderDispatcher.java index 52294d04f6..e812e7fccd 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorBlockEntityRenderDispatcher.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorBlockEntityRenderDispatcher.java @@ -1,14 +1,13 @@ package at.petrak.hexcasting.mixin.accessor.client; +import java.util.function.Supplier; import net.minecraft.client.renderer.block.BlockRenderDispatcher; import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import java.util.function.Supplier; - @Mixin(BlockEntityRenderDispatcher.class) public interface AccessorBlockEntityRenderDispatcher { - @Accessor("blockRenderDispatcher") - Supplier<BlockRenderDispatcher> hex$getBlockRenderDispatcher(); + @Accessor("blockRenderDispatcher") + Supplier<BlockRenderDispatcher> hex$getBlockRenderDispatcher(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorCompositeRenderType.java b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorCompositeRenderType.java index c7965fd588..f23f5087e1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorCompositeRenderType.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorCompositeRenderType.java @@ -6,6 +6,6 @@ @Mixin(RenderType.CompositeRenderType.class) public interface AccessorCompositeRenderType { - @Invoker("state") - RenderType.CompositeState hex$state(); + @Invoker("state") + RenderType.CompositeState hex$state(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorEmptyTextureStateShard.java b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorEmptyTextureStateShard.java index 2ee90b1593..201d406ea3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorEmptyTextureStateShard.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorEmptyTextureStateShard.java @@ -1,14 +1,13 @@ package at.petrak.hexcasting.mixin.accessor.client; +import java.util.Optional; import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.resources.ResourceLocation; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; -import java.util.Optional; - @Mixin(RenderStateShard.EmptyTextureStateShard.class) public interface AccessorEmptyTextureStateShard { - @Invoker("cutoutTexture") - Optional<ResourceLocation> hex$cutoutTexture(); + @Invoker("cutoutTexture") + Optional<ResourceLocation> hex$cutoutTexture(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorMouseHandler.java b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorMouseHandler.java index 54343bb81c..d663d1328f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorMouseHandler.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorMouseHandler.java @@ -6,9 +6,9 @@ @Mixin(MouseHandler.class) public interface AccessorMouseHandler { - @Accessor("accumulatedScroll") - double hex$getAccumulatedScroll(); + @Accessor("accumulatedScroll") + double hex$getAccumulatedScroll(); - @Accessor("accumulatedScroll") - void hex$setAccumulatedScroll(double scroll); + @Accessor("accumulatedScroll") + void hex$setAccumulatedScroll(double scroll); } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorRenderStateShard.java b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorRenderStateShard.java index 653ce5fb62..7ce5031825 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorRenderStateShard.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorRenderStateShard.java @@ -6,6 +6,6 @@ @Mixin(RenderStateShard.class) public interface AccessorRenderStateShard { - @Accessor("name") - String hex$name(); + @Accessor("name") + String hex$name(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorRenderType.java b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorRenderType.java index 5908725e0a..b5d867a549 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorRenderType.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/accessor/client/AccessorRenderType.java @@ -8,10 +8,15 @@ // https://github.com/VazkiiMods/Botania/blob/13b7bcd9cbb6b1a418b0afe455662d29b46f1a7f/Xplat/src/main/java/vazkii/botania/mixin/client/AccessorRenderType.java @Mixin(RenderType.class) public interface AccessorRenderType { - @Invoker("create") - static RenderType.CompositeRenderType hex$create(String string, VertexFormat vertexFormat, - VertexFormat.Mode mode, int bufSize, boolean hasCrumbling, boolean sortOnUpload, - RenderType.CompositeState compositeState) { - throw new IllegalStateException(); - } + @Invoker("create") + static RenderType.CompositeRenderType hex$create( + String string, + VertexFormat vertexFormat, + VertexFormat.Mode mode, + int bufSize, + boolean hasCrumbling, + boolean sortOnUpload, + RenderType.CompositeState compositeState) { + throw new IllegalStateException(); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/client/MixinClientLevel.java b/Common/src/main/java/at/petrak/hexcasting/mixin/client/MixinClientLevel.java index 240232f2d4..bbe30f58d1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/client/MixinClientLevel.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/client/MixinClientLevel.java @@ -20,32 +20,50 @@ @Mixin(ClientLevel.class) public abstract class MixinClientLevel { - @Inject(method = "doAnimateTick", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/Block;animateTick" + - "(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;" + - "Lnet/minecraft/core/BlockPos;Lnet/minecraft/util/RandomSource;)V"), - locals = LocalCapture.CAPTURE_FAILSOFT) - public void addBuddingAmethystParticles(int $$0, int $$1, int $$2, int $$3, RandomSource rand, Block $$5, - BlockPos.MutableBlockPos pos, CallbackInfo ci, int trueX, int trueY, int trueZ, BlockState state) { - ClientLevel self = ((ClientLevel) (Object) this); + @Inject( + method = "doAnimateTick", + at = + @At( + value = "INVOKE", + target = + "Lnet/minecraft/world/level/block/Block;animateTick" + + "(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;" + + "Lnet/minecraft/core/BlockPos;Lnet/minecraft/util/RandomSource;)V"), + locals = LocalCapture.CAPTURE_FAILSOFT) + public void addBuddingAmethystParticles( + int $$0, + int $$1, + int $$2, + int $$3, + RandomSource rand, + Block $$5, + BlockPos.MutableBlockPos pos, + CallbackInfo ci, + int trueX, + int trueY, + int trueZ, + BlockState state) { + ClientLevel self = ((ClientLevel) (Object) this); - if (state.is(Blocks.BUDDING_AMETHYST)) { - ParticleOptions options = new ConjureParticleOptions(0x8932b8); - Vec3 center = Vec3.atCenterOf(pos); - for (Direction direction : Direction.values()) { - int dX = direction.getStepX(); - int dY = direction.getStepY(); - int dZ = direction.getStepZ(); - - int count = rand.nextInt(10) / 5; - for (int i = 0; i < count; i++) { - double pX = center.x + (dX == 0 ? Mth.nextDouble(rand, -0.5D, 0.5D) : (double) dX * 0.55D); - double pY = center.y + (dY == 0 ? Mth.nextDouble(rand, -0.5D, 0.5D) : (double) dY * 0.55D); - double pZ = center.z + (dZ == 0 ? Mth.nextDouble(rand, -0.5D, 0.5D) : (double) dZ * 0.55D); - self.addParticle(options, pX, pY, pZ, 0, 0, 0); - } - } - } - } + if (state.is(Blocks.BUDDING_AMETHYST)) { + ParticleOptions options = new ConjureParticleOptions(0x8932b8); + Vec3 center = Vec3.atCenterOf(pos); + for (Direction direction : Direction.values()) { + int dX = direction.getStepX(); + int dY = direction.getStepY(); + int dZ = direction.getStepZ(); + int count = rand.nextInt(10) / 5; + for (int i = 0; i < count; i++) { + double pX = + center.x + (dX == 0 ? Mth.nextDouble(rand, -0.5D, 0.5D) : (double) dX * 0.55D); + double pY = + center.y + (dY == 0 ? Mth.nextDouble(rand, -0.5D, 0.5D) : (double) dY * 0.55D); + double pZ = + center.z + (dZ == 0 ? Mth.nextDouble(rand, -0.5D, 0.5D) : (double) dZ * 0.55D); + self.addParticle(options, pX, pY, pZ, 0, 0, 0); + } + } + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/client/MixinPlayerRenderer.java b/Common/src/main/java/at/petrak/hexcasting/mixin/client/MixinPlayerRenderer.java index eb46c8522d..47eb26b749 100644 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/client/MixinPlayerRenderer.java +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/client/MixinPlayerRenderer.java @@ -12,9 +12,18 @@ @Mixin(PlayerRenderer.class) public abstract class MixinPlayerRenderer { - @Inject(method = "render(Lnet/minecraft/client/player/AbstractClientPlayer;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", - at = @At("HEAD")) - public void hex$onRender(AbstractClientPlayer player, float $$1, float pticks, PoseStack ps, MultiBufferSource bufferSource, int $$5, CallbackInfo ci) { - ClientRenderHelper.renderCastingStack(ps, player, pticks); - } + @Inject( + method = + "render(Lnet/minecraft/client/player/AbstractClientPlayer;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", + at = @At("HEAD")) + public void hex$onRender( + AbstractClientPlayer player, + float $$1, + float pticks, + PoseStack ps, + MultiBufferSource bufferSource, + int $$5, + CallbackInfo ci) { + ClientRenderHelper.renderCastingStack(ps, player, pticks); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/server/ScrungledPatternsSave.java b/Common/src/main/java/at/petrak/hexcasting/server/ScrungledPatternsSave.java index 2407d3571a..f62e9e6651 100644 --- a/Common/src/main/java/at/petrak/hexcasting/server/ScrungledPatternsSave.java +++ b/Common/src/main/java/at/petrak/hexcasting/server/ScrungledPatternsSave.java @@ -7,6 +7,8 @@ import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.mojang.datafixers.util.Pair; +import java.util.HashMap; +import java.util.Map; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; @@ -14,113 +16,111 @@ import net.minecraft.world.level.saveddata.SavedData; import org.jetbrains.annotations.Nullable; -import java.util.HashMap; -import java.util.Map; - /** - * Maps angle sigs to resource locations and their preferred start dir so we can look them up in the main registry - * Save this on the world in case the random algorithm changes. + * Maps angle sigs to resource locations and their preferred start dir so we can look them up in the + * main registry Save this on the world in case the random algorithm changes. */ public class ScrungledPatternsSave extends SavedData { - public static final String DATA_VERSION = "0.1.0"; - public static final String TAG_SAVED_DATA = "hexcasting.per-world-patterns." + DATA_VERSION; - private static final String TAG_DIR = "startDir"; - private static final String TAG_KEY = "key"; - - /** - * Maps scrungled signatures to their keys. - */ - private final Map<String, PerWorldEntry> lookup; - - /** - * Reverse-maps resource keys to their signature; you can use that in {@code lookup}. - * <p> - * This way we can look up things if we know their resource key, for commands and such - */ - private final Map<ResourceKey<ActionRegistryEntry>, String> reverseLookup; - - private ScrungledPatternsSave(Map<String, PerWorldEntry> lookup) { - this.lookup = lookup; - this.reverseLookup = new HashMap<>(); - this.lookup.forEach((sig, entry) -> { - this.reverseLookup.put(entry.key, sig); - }); - } - - @Nullable - public PerWorldEntry lookup(String signature) { - return this.lookup.get(signature); - } - - @Nullable - public Pair<String, PerWorldEntry> lookupReverse(ResourceKey<ActionRegistryEntry> key) { - var sig = this.reverseLookup.get(key); - if (sig == null) return null; - - return Pair.of(sig, this.lookup.get(sig)); - } - - @Override - public CompoundTag save(CompoundTag tag) { - // We don't save the reverse lookup cause we can reconstruct it when loading. - this.lookup.forEach((sig, entry) -> { - var inner = new CompoundTag(); - inner.putByte(TAG_DIR, (byte) entry.canonicalStartDir.ordinal()); - inner.putString(TAG_KEY, entry.key().location().toString()); - tag.put(sig, inner); - }); - return tag; - } - - private static ScrungledPatternsSave load(CompoundTag tag) { - var registryKey = IXplatAbstractions.INSTANCE.getActionRegistry().key(); - - var map = new HashMap<String, PerWorldEntry>(); - for (var sig : tag.getAllKeys()) { - var inner = tag.getCompound(sig); - - var rawDir = inner.getByte(TAG_DIR); - var rawKey = inner.getString(TAG_KEY); - - var dir = HexDir.values()[rawDir]; - var key = ResourceKey.create(registryKey, new ResourceLocation(rawKey)); - - map.put(sig, new PerWorldEntry(key, dir)); - } - - return new ScrungledPatternsSave(map); - } - - public static ScrungledPatternsSave createFromScratch(long seed) { - var map = new HashMap<String, PerWorldEntry>(); - - var registry = IXplatAbstractions.INSTANCE.getActionRegistry(); - - // TODO: this version of the code doesn't have overlap protection - // this means if some hilarious funny person makes a great spell that has the same shape as a normal spell - // there might be overlap. - // I'm going to file that under "don't do that" - // (the number literal phial incident won't happen though because we check for special handlers first now) - for (var key : registry.registryKeySet()) { - var entry = registry.get(key); - if (HexUtils.isOfTag(registry, key, HexTags.Actions.PER_WORLD_PATTERN)) { - var scrungledPat = EulerPathFinder.findAltDrawing(entry.prototype(), seed); - map.put(scrungledPat.anglesSignature(), new PerWorldEntry(key, scrungledPat.getStartDir())); - } - } - - var out = new ScrungledPatternsSave(map); - out.setDirty(); - return out; - } - - public static ScrungledPatternsSave open(ServerLevel overworld) { - return overworld.getDataStorage().computeIfAbsent( - ScrungledPatternsSave::load, - () -> ScrungledPatternsSave.createFromScratch(overworld.getSeed()), - TAG_SAVED_DATA); - } - - public record PerWorldEntry(ResourceKey<ActionRegistryEntry> key, HexDir canonicalStartDir) { - } + public static final String DATA_VERSION = "0.1.0"; + public static final String TAG_SAVED_DATA = "hexcasting.per-world-patterns." + DATA_VERSION; + private static final String TAG_DIR = "startDir"; + private static final String TAG_KEY = "key"; + + /** Maps scrungled signatures to their keys. */ + private final Map<String, PerWorldEntry> lookup; + + /** + * Reverse-maps resource keys to their signature; you can use that in {@code lookup}. + * + * <p>This way we can look up things if we know their resource key, for commands and such + */ + private final Map<ResourceKey<ActionRegistryEntry>, String> reverseLookup; + + private ScrungledPatternsSave(Map<String, PerWorldEntry> lookup) { + this.lookup = lookup; + this.reverseLookup = new HashMap<>(); + this.lookup.forEach( + (sig, entry) -> { + this.reverseLookup.put(entry.key, sig); + }); + } + + @Nullable public PerWorldEntry lookup(String signature) { + return this.lookup.get(signature); + } + + @Nullable public Pair<String, PerWorldEntry> lookupReverse(ResourceKey<ActionRegistryEntry> key) { + var sig = this.reverseLookup.get(key); + if (sig == null) return null; + + return Pair.of(sig, this.lookup.get(sig)); + } + + @Override + public CompoundTag save(CompoundTag tag) { + // We don't save the reverse lookup cause we can reconstruct it when loading. + this.lookup.forEach( + (sig, entry) -> { + var inner = new CompoundTag(); + inner.putByte(TAG_DIR, (byte) entry.canonicalStartDir.ordinal()); + inner.putString(TAG_KEY, entry.key().location().toString()); + tag.put(sig, inner); + }); + return tag; + } + + private static ScrungledPatternsSave load(CompoundTag tag) { + var registryKey = IXplatAbstractions.INSTANCE.getActionRegistry().key(); + + var map = new HashMap<String, PerWorldEntry>(); + for (var sig : tag.getAllKeys()) { + var inner = tag.getCompound(sig); + + var rawDir = inner.getByte(TAG_DIR); + var rawKey = inner.getString(TAG_KEY); + + var dir = HexDir.values()[rawDir]; + var key = ResourceKey.create(registryKey, new ResourceLocation(rawKey)); + + map.put(sig, new PerWorldEntry(key, dir)); + } + + return new ScrungledPatternsSave(map); + } + + public static ScrungledPatternsSave createFromScratch(long seed) { + var map = new HashMap<String, PerWorldEntry>(); + + var registry = IXplatAbstractions.INSTANCE.getActionRegistry(); + + // TODO: this version of the code doesn't have overlap protection + // this means if some hilarious funny person makes a great spell that has the same shape as a + // normal spell + // there might be overlap. + // I'm going to file that under "don't do that" + // (the number literal phial incident won't happen though because we check for special handlers + // first now) + for (var key : registry.registryKeySet()) { + var entry = registry.get(key); + if (HexUtils.isOfTag(registry, key, HexTags.Actions.PER_WORLD_PATTERN)) { + var scrungledPat = EulerPathFinder.findAltDrawing(entry.prototype(), seed); + map.put(scrungledPat.anglesSignature(), new PerWorldEntry(key, scrungledPat.getStartDir())); + } + } + + var out = new ScrungledPatternsSave(map); + out.setDirty(); + return out; + } + + public static ScrungledPatternsSave open(ServerLevel overworld) { + return overworld + .getDataStorage() + .computeIfAbsent( + ScrungledPatternsSave::load, + () -> ScrungledPatternsSave.createFromScratch(overworld.getSeed()), + TAG_SAVED_DATA); + } + + public record PerWorldEntry(ResourceKey<ActionRegistryEntry> key, HexDir canonicalStartDir) {} } diff --git a/Common/src/main/java/at/petrak/hexcasting/xplat/IClientXplatAbstractions.java b/Common/src/main/java/at/petrak/hexcasting/xplat/IClientXplatAbstractions.java index 81806255b3..e5674a40b8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/xplat/IClientXplatAbstractions.java +++ b/Common/src/main/java/at/petrak/hexcasting/xplat/IClientXplatAbstractions.java @@ -3,6 +3,8 @@ import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.client.ClientCastingStack; import at.petrak.hexcasting.common.msgs.IMessage; +import java.util.ServiceLoader; +import java.util.stream.Collectors; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.client.renderer.item.ItemPropertyFunction; @@ -15,41 +17,43 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.phys.AABB; -import java.util.ServiceLoader; -import java.util.stream.Collectors; - public interface IClientXplatAbstractions { - void sendPacketToServer(IMessage packet); + void sendPacketToServer(IMessage packet); - void setRenderLayer(Block block, RenderType type); + void setRenderLayer(Block block, RenderType type); - void initPlatformSpecific(); + void initPlatformSpecific(); - <T extends Entity> void registerEntityRenderer(EntityType<? extends T> type, EntityRendererProvider<T> renderer); + <T extends Entity> void registerEntityRenderer( + EntityType<? extends T> type, EntityRendererProvider<T> renderer); - void registerItemProperty(Item item, ResourceLocation id, ItemPropertyFunction func); + void registerItemProperty(Item item, ResourceLocation id, ItemPropertyFunction func); - ClientCastingStack getClientCastingStack(Player player); + ClientCastingStack getClientCastingStack(Player player); - // On Forge, these are already exposed; on Farbc we do a mixin - void setFilterSave(AbstractTexture texture, boolean filter, boolean mipmap); + // On Forge, these are already exposed; on Farbc we do a mixin + void setFilterSave(AbstractTexture texture, boolean filter, boolean mipmap); - void restoreLastFilter(AbstractTexture texture); + void restoreLastFilter(AbstractTexture texture); - boolean fabricAdditionalQuenchFrustumCheck(AABB aabb); + boolean fabricAdditionalQuenchFrustumCheck(AABB aabb); - IClientXplatAbstractions INSTANCE = find(); + IClientXplatAbstractions INSTANCE = find(); - private static IClientXplatAbstractions find() { - var providers = ServiceLoader.load(IClientXplatAbstractions.class).stream().toList(); - if (providers.size() != 1) { - var names = providers.stream().map(p -> p.type().getName()).collect(Collectors.joining(",", "[", "]")); - throw new IllegalStateException( - "There should be exactly one IClientXplatAbstractions implementation on the classpath. Found: " + names); - } else { - var provider = providers.get(0); - HexAPI.LOGGER.debug("Instantiating client xplat impl: " + provider.type().getName()); - return provider.get(); - } - } + private static IClientXplatAbstractions find() { + var providers = ServiceLoader.load(IClientXplatAbstractions.class).stream().toList(); + if (providers.size() != 1) { + var names = + providers.stream() + .map(p -> p.type().getName()) + .collect(Collectors.joining(",", "[", "]")); + throw new IllegalStateException( + "There should be exactly one IClientXplatAbstractions implementation on the classpath. Found: " + + names); + } else { + var provider = providers.get(0); + HexAPI.LOGGER.debug("Instantiating client xplat impl: " + provider.type().getName()); + return provider.get(); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/xplat/IForgeLikeBlock.java b/Common/src/main/java/at/petrak/hexcasting/xplat/IForgeLikeBlock.java index 1c4bb99645..a852288a3a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/xplat/IForgeLikeBlock.java +++ b/Common/src/main/java/at/petrak/hexcasting/xplat/IForgeLikeBlock.java @@ -7,15 +7,20 @@ import net.minecraft.world.level.block.state.BlockState; /** - * An interface that mimics some methods of IForgeBlock. - * Fabric implementation will use mixins to achieve the same effects. + * An interface that mimics some methods of IForgeBlock. Fabric implementation will use mixins to + * achieve the same effects. */ public interface IForgeLikeBlock { - default boolean addLandingEffects(BlockState state, ServerLevel level, BlockPos pos, LivingEntity entity, int numberOfParticles) { - return false; - } + default boolean addLandingEffects( + BlockState state, + ServerLevel level, + BlockPos pos, + LivingEntity entity, + int numberOfParticles) { + return false; + } - default boolean hasEnchantPowerBonus(BlockState state, LevelReader level, BlockPos pos) { - return false; - } + default boolean hasEnchantPowerBonus(BlockState state, LevelReader level, BlockPos pos) { + return false; + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/xplat/IXplatAbstractions.java b/Common/src/main/java/at/petrak/hexcasting/xplat/IXplatAbstractions.java index 86dbc24586..dde36ddeab 100644 --- a/Common/src/main/java/at/petrak/hexcasting/xplat/IXplatAbstractions.java +++ b/Common/src/main/java/at/petrak/hexcasting/xplat/IXplatAbstractions.java @@ -22,6 +22,11 @@ import at.petrak.hexcasting.common.msgs.IMessage; import at.petrak.hexcasting.interop.pehkui.PehkuiInterop; import com.mojang.authlib.GameProfile; +import java.util.List; +import java.util.ServiceLoader; +import java.util.UUID; +import java.util.function.BiFunction; +import java.util.stream.Collectors; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; import net.minecraft.network.protocol.Packet; @@ -47,164 +52,154 @@ import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; -import java.util.List; -import java.util.ServiceLoader; -import java.util.UUID; -import java.util.function.BiFunction; -import java.util.stream.Collectors; - -/** - * more like IHexplatAbstracts lmaooooooo - */ +/** more like IHexplatAbstracts lmaooooooo */ public interface IXplatAbstractions { - Platform platform(); + Platform platform(); - boolean isModPresent(String id); + boolean isModPresent(String id); - boolean isPhysicalClient(); + boolean isPhysicalClient(); - void initPlatformSpecific(); + void initPlatformSpecific(); - void sendPacketToPlayer(ServerPlayer target, IMessage packet); + void sendPacketToPlayer(ServerPlayer target, IMessage packet); - void sendPacketNear(Vec3 pos, double radius, ServerLevel dimension, IMessage packet); + void sendPacketNear(Vec3 pos, double radius, ServerLevel dimension, IMessage packet); - void sendPacketTracking(Entity entity, IMessage packet); + void sendPacketTracking(Entity entity, IMessage packet); - // https://github.com/VazkiiMods/Botania/blob/13b7bcd9cbb6b1a418b0afe455662d29b46f1a7f/Xplat/src/main/java/vazkii/botania/xplat/IXplatAbstractions.java#L157 - Packet<ClientGamePacketListener> toVanillaClientboundPacket(IMessage message); + // https://github.com/VazkiiMods/Botania/blob/13b7bcd9cbb6b1a418b0afe455662d29b46f1a7f/Xplat/src/main/java/vazkii/botania/xplat/IXplatAbstractions.java#L157 + Packet<ClientGamePacketListener> toVanillaClientboundPacket(IMessage message); -// double getReachDistance(Player player); + // double getReachDistance(Player player); - // Things that used to be caps + // Things that used to be caps - /** - * Doesn't actually knock out its AI or anything anymore, just sets caps/ccs - */ - // heheheheh addled data - void setBrainsweepAddlData(Mob mob); + /** Doesn't actually knock out its AI or anything anymore, just sets caps/ccs */ + // heheheheh addled data + void setBrainsweepAddlData(Mob mob); - boolean isBrainswept(Mob mob); + boolean isBrainswept(Mob mob); - @Nullable FrozenPigment setPigment(Player target, @Nullable FrozenPigment colorizer); + @Nullable FrozenPigment setPigment(Player target, @Nullable FrozenPigment colorizer); - void setSentinel(Player target, @Nullable Sentinel sentinel); + void setSentinel(Player target, @Nullable Sentinel sentinel); - void setFlight(ServerPlayer target, @Nullable FlightAbility flight); + void setFlight(ServerPlayer target, @Nullable FlightAbility flight); - void setAltiora(Player target, @Nullable AltioraAbility altiora); + void setAltiora(Player target, @Nullable AltioraAbility altiora); - void setStaffcastImage(ServerPlayer target, @Nullable CastingImage image); + void setStaffcastImage(ServerPlayer target, @Nullable CastingImage image); - void setPatterns(ServerPlayer target, List<ResolvedPattern> patterns); + void setPatterns(ServerPlayer target, List<ResolvedPattern> patterns); - @Nullable FlightAbility getFlight(ServerPlayer player); + @Nullable FlightAbility getFlight(ServerPlayer player); - @Nullable AltioraAbility getAltiora(Player player); + @Nullable AltioraAbility getAltiora(Player player); - FrozenPigment getPigment(Player player); + FrozenPigment getPigment(Player player); - @Nullable Sentinel getSentinel(Player player); + @Nullable Sentinel getSentinel(Player player); - CastingVM getStaffcastVM(ServerPlayer player, InteractionHand hand); + CastingVM getStaffcastVM(ServerPlayer player, InteractionHand hand); - List<ResolvedPattern> getPatternsSavedInUi(ServerPlayer player); + List<ResolvedPattern> getPatternsSavedInUi(ServerPlayer player); - void clearCastingData(ServerPlayer player); + void clearCastingData(ServerPlayer player); - @Nullable - ADMediaHolder findMediaHolder(ItemStack stack); + @Nullable ADMediaHolder findMediaHolder(ItemStack stack); - @Nullable - ADMediaHolder findMediaHolder(ServerPlayer player); + @Nullable ADMediaHolder findMediaHolder(ServerPlayer player); - @Nullable - ADIotaHolder findDataHolder(ItemStack stack); + @Nullable ADIotaHolder findDataHolder(ItemStack stack); - @Nullable - ADIotaHolder findDataHolder(Entity entity); + @Nullable ADIotaHolder findDataHolder(Entity entity); - @Nullable - ADHexHolder findHexHolder(ItemStack stack); + @Nullable ADHexHolder findHexHolder(ItemStack stack); - @Nullable ADVariantItem findVariantHolder(ItemStack stack); + @Nullable ADVariantItem findVariantHolder(ItemStack stack); - // coooollooorrrs + // coooollooorrrs - boolean isPigment(ItemStack stack); + boolean isPigment(ItemStack stack); - ColorProvider getColorProvider(FrozenPigment pigment); + ColorProvider getColorProvider(FrozenPigment pigment); - // Items + // Items - /** - * No-op on forge (use a SoftImplement) - */ - Item.Properties addEquipSlotFabric(EquipmentSlot slot); + /** No-op on forge (use a SoftImplement) */ + Item.Properties addEquipSlotFabric(EquipmentSlot slot); - // Blocks + // Blocks - <T extends BlockEntity> BlockEntityType<T> createBlockEntityType(BiFunction<BlockPos, BlockState, T> func, - Block... blocks); + <T extends BlockEntity> BlockEntityType<T> createBlockEntityType( + BiFunction<BlockPos, BlockState, T> func, Block... blocks); - boolean tryPlaceFluid(Level level, InteractionHand hand, BlockPos pos, Fluid fluid); + boolean tryPlaceFluid(Level level, InteractionHand hand, BlockPos pos, Fluid fluid); - boolean drainAllFluid(Level level, BlockPos pos); + boolean drainAllFluid(Level level, BlockPos pos); - // misc + // misc - boolean isCorrectTierForDrops(Tier tier, BlockState bs); + boolean isCorrectTierForDrops(Tier tier, BlockState bs); - Ingredient getUnsealedIngredient(ItemStack stack); + Ingredient getUnsealedIngredient(ItemStack stack); - IXplatTags tags(); + IXplatTags tags(); - LootItemCondition.Builder isShearsCondition(); + LootItemCondition.Builder isShearsCondition(); - String getModName(String namespace); + String getModName(String namespace); - /** - * Registry for actions. - * <p> - * There's some internal caching (so we can directly look up signatures in a map, for example) - * but this registry is the source of truth. - */ - Registry<ActionRegistryEntry> getActionRegistry(); + /** + * Registry for actions. + * + * <p>There's some internal caching (so we can directly look up signatures in a map, for example) + * but this registry is the source of truth. + */ + Registry<ActionRegistryEntry> getActionRegistry(); - Registry<SpecialHandler.Factory<?>> getSpecialHandlerRegistry(); + Registry<SpecialHandler.Factory<?>> getSpecialHandlerRegistry(); - Registry<IotaType<?>> getIotaTypeRegistry(); + Registry<IotaType<?>> getIotaTypeRegistry(); - Registry<Arithmetic> getArithmeticRegistry(); - Registry<ContinuationFrame.Type<?>> getContinuationTypeRegistry(); + Registry<Arithmetic> getArithmeticRegistry(); - Registry<EvalSound> getEvalSoundRegistry(); + Registry<ContinuationFrame.Type<?>> getContinuationTypeRegistry(); - GameProfile HEXCASTING = new GameProfile(UUID.fromString("8BE7E9DA-1667-11EE-BE56-0242AC120002"), "[HexCasting]"); + Registry<EvalSound> getEvalSoundRegistry(); - boolean isBreakingAllowed(ServerLevel world, BlockPos pos, BlockState state, @Nullable Player player); + GameProfile HEXCASTING = + new GameProfile(UUID.fromString("8BE7E9DA-1667-11EE-BE56-0242AC120002"), "[HexCasting]"); - boolean isPlacingAllowed(ServerLevel world, BlockPos pos, ItemStack blockStack, @Nullable Player player); + boolean isBreakingAllowed( + ServerLevel world, BlockPos pos, BlockState state, @Nullable Player player); - // interop + boolean isPlacingAllowed( + ServerLevel world, BlockPos pos, ItemStack blockStack, @Nullable Player player); - PehkuiInterop.ApiAbstraction getPehkuiApi(); + // interop - /// + PehkuiInterop.ApiAbstraction getPehkuiApi(); - IXplatAbstractions INSTANCE = find(); + /// - private static IXplatAbstractions find() { - var providers = ServiceLoader.load(IXplatAbstractions.class).stream().toList(); - if (providers.size() != 1) { - var names = providers.stream().map(p -> p.type().getName()).collect(Collectors.joining(",", "[", "]")); - throw new IllegalStateException( - "There should be exactly one IXplatAbstractions implementation on the classpath. Found: " + names); - } else { - var provider = providers.get(0); - HexAPI.LOGGER.debug("Instantiating xplat impl: " + provider.type().getName()); - return provider.get(); - } - } + IXplatAbstractions INSTANCE = find(); + private static IXplatAbstractions find() { + var providers = ServiceLoader.load(IXplatAbstractions.class).stream().toList(); + if (providers.size() != 1) { + var names = + providers.stream() + .map(p -> p.type().getName()) + .collect(Collectors.joining(",", "[", "]")); + throw new IllegalStateException( + "There should be exactly one IXplatAbstractions implementation on the classpath. Found: " + + names); + } else { + var provider = providers.get(0); + HexAPI.LOGGER.debug("Instantiating xplat impl: " + provider.type().getName()); + return provider.get(); + } + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/xplat/IXplatTags.java b/Common/src/main/java/at/petrak/hexcasting/xplat/IXplatTags.java index 13126df336..fb0b4633bb 100644 --- a/Common/src/main/java/at/petrak/hexcasting/xplat/IXplatTags.java +++ b/Common/src/main/java/at/petrak/hexcasting/xplat/IXplatTags.java @@ -5,7 +5,7 @@ // https://fabricmc.net/wiki/tutorial:tags#existing_common_tags public interface IXplatTags { - TagKey<Item> amethystDust(); + TagKey<Item> amethystDust(); - TagKey<Item> gems(); + TagKey<Item> gems(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/xplat/Platform.java b/Common/src/main/java/at/petrak/hexcasting/xplat/Platform.java index 6acb3cec20..7541b27144 100644 --- a/Common/src/main/java/at/petrak/hexcasting/xplat/Platform.java +++ b/Common/src/main/java/at/petrak/hexcasting/xplat/Platform.java @@ -1,5 +1,6 @@ package at.petrak.hexcasting.xplat; public enum Platform { - FORGE, FABRIC + FORGE, + FABRIC } diff --git a/Common/src/test/java/EulerPathFinderTest.kt b/Common/src/test/java/EulerPathFinderTest.kt index f0eca91532..4dd3acfdac 100644 --- a/Common/src/test/java/EulerPathFinderTest.kt +++ b/Common/src/test/java/EulerPathFinderTest.kt @@ -4,13 +4,13 @@ import at.petrak.hexcasting.api.casting.math.HexPattern.Companion.fromAngles import org.junit.jupiter.api.Test internal class EulerPathFinderTest { - @Test - fun findAltDrawing() { - val sig = "dadaddwwaadada" - val pat = fromAngles(sig, HexDir.NORTH_EAST) - for (i in 0 until 8) { - val scrungled = findAltDrawing(pat, i.toLong()) - println(scrungled) - } - } + @Test + fun findAltDrawing() { + val sig = "dadaddwwaadada" + val pat = fromAngles(sig, HexDir.NORTH_EAST) + for (i in 0 until 8) { + val scrungled = findAltDrawing(pat, i.toLong()) + println(scrungled) + } + } } diff --git a/Common/src/test/java/WhatRangeDoTheNoisesOutputAnywaysTest.java b/Common/src/test/java/WhatRangeDoTheNoisesOutputAnywaysTest.java index 827ca5c9fe..9196c4de40 100644 --- a/Common/src/test/java/WhatRangeDoTheNoisesOutputAnywaysTest.java +++ b/Common/src/test/java/WhatRangeDoTheNoisesOutputAnywaysTest.java @@ -1,39 +1,38 @@ +import java.util.List; import net.minecraft.world.level.levelgen.SingleThreadedRandomSource; import net.minecraft.world.level.levelgen.synth.PerlinNoise; import net.minecraft.world.level.levelgen.synth.SimplexNoise; import org.junit.jupiter.api.Test; -import java.util.List; - public class WhatRangeDoTheNoisesOutputAnywaysTest { - @Test - public void test() { - var perlin = PerlinNoise.create(new SingleThreadedRandomSource(12345), List.of(0, 1, 2, 3, 4)); - var simplex = new SimplexNoise(new SingleThreadedRandomSource(12345)); + @Test + public void test() { + var perlin = PerlinNoise.create(new SingleThreadedRandomSource(12345), List.of(0, 1, 2, 3, 4)); + var simplex = new SimplexNoise(new SingleThreadedRandomSource(12345)); - System.out.println("Perlin:"); - for (int i = 0; i < 20; i++) { - System.out.printf(" %f%n", perlin.getValue(i / 10.0, 69420.0, 1337.0)); - } + System.out.println("Perlin:"); + for (int i = 0; i < 20; i++) { + System.out.printf(" %f%n", perlin.getValue(i / 10.0, 69420.0, 1337.0)); + } - System.out.println("Simplex:"); - for (int i = 0; i < 20; i++) { - System.out.printf(" %f%n", simplex.getValue(i / 10.0, 69420.0, 1337.0)); - } - } + System.out.println("Simplex:"); + for (int i = 0; i < 20; i++) { + System.out.printf(" %f%n", simplex.getValue(i / 10.0, 69420.0, 1337.0)); + } + } - @Test - public void perlinBounds() { - var perlin = PerlinNoise.create(new SingleThreadedRandomSource(12345), List.of(0, 1, 2, 3, 4)); - var min = Double.POSITIVE_INFINITY; - var max = Double.NEGATIVE_INFINITY; + @Test + public void perlinBounds() { + var perlin = PerlinNoise.create(new SingleThreadedRandomSource(12345), List.of(0, 1, 2, 3, 4)); + var min = Double.POSITIVE_INFINITY; + var max = Double.NEGATIVE_INFINITY; - for (int i = 0; i < 10000; i++) { - var it = perlin.getValue(i / 10.0, 12345.0, 7604.0); - min = Math.min(min, it); - max = Math.max(max, it); - } + for (int i = 0; i < 10000; i++) { + var it = perlin.getValue(i / 10.0, 12345.0, 7604.0); + min = Math.min(min, it); + max = Math.max(max, it); + } - System.out.printf("Min: %f\nMax: %f\n", min, max); - } + System.out.printf("Min: %f\nMax: %f\n", min, max); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexClientInitializer.kt b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexClientInitializer.kt index 2ad2ec1d4a..b3e956656e 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexClientInitializer.kt +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexClientInitializer.kt @@ -11,6 +11,7 @@ import at.petrak.hexcasting.common.lib.HexParticles import at.petrak.hexcasting.fabric.event.MouseScrollCallback import at.petrak.hexcasting.fabric.network.FabricPacketHandler import at.petrak.hexcasting.interop.HexInterop +import java.util.function.Function import net.fabricmc.api.ClientModInitializer import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry @@ -24,53 +25,58 @@ import net.minecraft.core.particles.ParticleOptions import net.minecraft.core.particles.ParticleType import net.minecraft.world.level.block.entity.BlockEntity import net.minecraft.world.level.block.entity.BlockEntityType -import java.util.function.Function object FabricHexClientInitializer : ClientModInitializer { - override fun onInitializeClient() { - FabricPacketHandler.initClient() - - WorldRenderEvents.AFTER_TRANSLUCENT.register { ctx -> - HexAdditionalRenderers.overlayLevel(ctx.matrixStack(), ctx.tickDelta()) - } - HudRenderCallback.EVENT.register(HexAdditionalRenderers::overlayGui) - WorldRenderEvents.START.register { ClientTickCounter.renderTickStart(it.tickDelta()) } - ClientTickEvents.END_CLIENT_TICK.register { - ClientTickCounter.clientTickEnd() - ShiftScrollListener.clientTickEnd() - } - TooltipComponentCallback.EVENT.register(PatternTooltipComponent::tryConvert) - ClientPlayConnectionEvents.JOIN.register { _, _, _ -> - PatternRegistryManifest.processRegistry(null) - } + override fun onInitializeClient() { + FabricPacketHandler.initClient() - MouseScrollCallback.EVENT.register(ShiftScrollListener::onScrollInGameplay) + WorldRenderEvents.AFTER_TRANSLUCENT.register { ctx -> + HexAdditionalRenderers.overlayLevel(ctx.matrixStack(), ctx.tickDelta()) + } + HudRenderCallback.EVENT.register(HexAdditionalRenderers::overlayGui) + WorldRenderEvents.START.register { ClientTickCounter.renderTickStart(it.tickDelta()) } + ClientTickEvents.END_CLIENT_TICK.register { + ClientTickCounter.clientTickEnd() + ShiftScrollListener.clientTickEnd() + } + TooltipComponentCallback.EVENT.register(PatternTooltipComponent::tryConvert) + ClientPlayConnectionEvents.JOIN.register { _, _, _ -> + PatternRegistryManifest.processRegistry(null) + } - RegisterClientStuff.init() - HexModelLayers.init { loc, defn -> EntityModelLayerRegistry.registerModelLayer(loc, defn::get) } + MouseScrollCallback.EVENT.register(ShiftScrollListener::onScrollInGameplay) + RegisterClientStuff.init() + HexModelLayers.init { loc, defn -> EntityModelLayerRegistry.registerModelLayer(loc, defn::get) } - HexParticles.FactoryHandler.registerFactories(object : HexParticles.FactoryHandler.Consumer { - override fun <T : ParticleOptions?> register(type: ParticleType<T>, constructor: Function<SpriteSet, ParticleProvider<T>>) { - ParticleFactoryRegistry.getInstance().register(type, constructor::apply) - } - }) + HexParticles.FactoryHandler.registerFactories( + object : HexParticles.FactoryHandler.Consumer { + override fun <T : ParticleOptions?> register( + type: ParticleType<T>, + constructor: Function<SpriteSet, ParticleProvider<T>> + ) { + ParticleFactoryRegistry.getInstance().register(type, constructor::apply) + } + } + ) - // how ergonomic - RegisterClientStuff.registerBlockEntityRenderers(object : - RegisterClientStuff.BlockEntityRendererRegisterererer { - override fun <T : BlockEntity> registerBlockEntityRenderer( - type: BlockEntityType<T>, - berp: BlockEntityRendererProvider<in T> - ) { - BlockEntityRendererRegistry.register(type, berp) - } - }) + // how ergonomic + RegisterClientStuff.registerBlockEntityRenderers( + object : RegisterClientStuff.BlockEntityRendererRegisterererer { + override fun <T : BlockEntity> registerBlockEntityRenderer( + type: BlockEntityType<T>, + berp: BlockEntityRendererProvider<in T> + ) { + BlockEntityRendererRegistry.register(type, berp) + } + } + ) - HexInterop.clientInit() - RegisterClientStuff.registerColorProviders( - { colorizer, item -> ColorProviderRegistry.ITEM.register(colorizer, item) }, - { colorizer, block -> ColorProviderRegistry.BLOCK.register(colorizer, block) }) - ModelLoadingRegistry.INSTANCE.registerModelProvider(RegisterClientStuff::onModelRegister) - } + HexInterop.clientInit() + RegisterClientStuff.registerColorProviders( + { colorizer, item -> ColorProviderRegistry.ITEM.register(colorizer, item) }, + { colorizer, block -> ColorProviderRegistry.BLOCK.register(colorizer, block) } + ) + ModelLoadingRegistry.INSTANCE.registerModelProvider(RegisterClientStuff::onModelRegister) + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java index a49ab760f3..5e2b91ddf7 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java @@ -1,5 +1,8 @@ package at.petrak.hexcasting.fabric; +import static at.petrak.hexcasting.api.mod.HexConfig.anyMatchResLoc; +import static at.petrak.hexcasting.api.mod.HexConfig.noneMatch; + import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.mod.HexConfig; import at.petrak.hexcasting.common.loot.HexLootHandler; @@ -7,6 +10,8 @@ import com.google.gson.GsonBuilder; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import java.util.ArrayList; +import java.util.List; import me.shedaniel.autoconfig.AutoConfig; import me.shedaniel.autoconfig.ConfigData; import me.shedaniel.autoconfig.annotation.Config; @@ -18,282 +23,266 @@ import net.minecraft.util.Mth; import net.minecraft.world.level.Level; -import java.util.ArrayList; -import java.util.List; - -import static at.petrak.hexcasting.api.mod.HexConfig.anyMatchResLoc; -import static at.petrak.hexcasting.api.mod.HexConfig.noneMatch; - @Config(name = HexAPI.MOD_ID) @Config.Gui.Background("minecraft:textures/block/calcite.png") @SuppressWarnings({"FieldMayBeFinal", "FieldCanBeLocal"}) - public class FabricHexConfig extends PartitioningSerializer.GlobalData { - @ConfigEntry.Category("common") - @ConfigEntry.Gui.TransitiveObject - public final Common common = new Common(); - @ConfigEntry.Category("client") - @ConfigEntry.Gui.TransitiveObject - public final Client client = new Client(); - @ConfigEntry.Category("server") - @ConfigEntry.Gui.TransitiveObject - public final Server server = new Server(); - - public static FabricHexConfig setup() { - var gson = new GsonBuilder() - .setPrettyPrinting() - .registerTypeAdapter(ResourceLocation.class, new ResourceLocation.Serializer()) - .create(); - AutoConfig.register(FabricHexConfig.class, PartitioningSerializer.wrap((cfg, clazz) -> - new GsonConfigSerializer<>(cfg, clazz, gson))); - var instance = AutoConfig.getConfigHolder(FabricHexConfig.class).getConfig(); - - HexConfig.setCommon(instance.common); - // We care about the client only on the *physical* client ... - if (IXplatAbstractions.INSTANCE.isPhysicalClient()) { - HexConfig.setClient(instance.client); - } - // but we care about the server on the *logical* server - // i believe this should Just Work without a guard? assuming we don't access it from the client ever - HexConfig.setServer(instance.server); - - return instance; - } - - @Config(name = "common") - public static final class Common implements HexConfig.CommonConfigAccess, ConfigData { - @ConfigEntry.Gui.Tooltip - private long dustMediaAmount = DEFAULT_DUST_MEDIA_AMOUNT; - @ConfigEntry.Gui.Tooltip - private long shardMediaAmount = DEFAULT_SHARD_MEDIA_AMOUNT; - @ConfigEntry.Gui.Tooltip - private long chargedCrystalMediaAmount = DEFAULT_CHARGED_MEDIA_AMOUNT; - @ConfigEntry.Gui.Tooltip - private double mediaToHealthRate = DEFAULT_MEDIA_TO_HEALTH_RATE; - - @ConfigEntry.Gui.Tooltip - private int cypherCooldown = DEFAULT_CYPHER_COOLDOWN; - @ConfigEntry.Gui.Tooltip - private int trinketCooldown = DEFAULT_TRINKET_COOLDOWN; - @ConfigEntry.Gui.Tooltip - private int artifactCooldown = DEFAULT_ARTIFACT_COOLDOWN; - - - @Override - public void validatePostLoad() throws ValidationException { - this.dustMediaAmount = Math.max(this.dustMediaAmount, 0); - this.shardMediaAmount = Math.max(this.shardMediaAmount, 0); - this.chargedCrystalMediaAmount = Math.max(this.chargedCrystalMediaAmount, 0); - this.mediaToHealthRate = Math.max(this.mediaToHealthRate, 0); - } - - @Override - public long dustMediaAmount() { - return dustMediaAmount; - } - - @Override - public long shardMediaAmount() { - return shardMediaAmount; - } - - @Override - public long chargedCrystalMediaAmount() { - return chargedCrystalMediaAmount; - } - - @Override - public double mediaToHealthRate() { - return mediaToHealthRate; - } - - @Override - public int cypherCooldown() { - return cypherCooldown; - } - - @Override - public int trinketCooldown() { - return trinketCooldown; - } - - @Override - public int artifactCooldown() { - return artifactCooldown; - } - } - - @Config(name = "client") - public static final class Client implements HexConfig.ClientConfigAccess, ConfigData { - @ConfigEntry.Gui.Tooltip - private boolean ctrlTogglesOffStrokeOrder = DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER; - @ConfigEntry.Gui.Tooltip - private boolean invertSpellbookScrollDirection = DEFAULT_INVERT_SPELLBOOK_SCROLL; - @ConfigEntry.Gui.Tooltip - private boolean invertAbacusScrollDirection = DEFAULT_INVERT_SPELLBOOK_SCROLL; - @ConfigEntry.Gui.Tooltip - private double gridSnapThreshold = DEFAULT_GRID_SNAP_THRESHOLD; - @ConfigEntry.Gui.Tooltip - private boolean clickingTogglesDrawing = DEFAULT_CLICKING_TOGGLES_DRAWING; - - @Override - public void validatePostLoad() throws ValidationException { - this.gridSnapThreshold = Mth.clamp(this.gridSnapThreshold, 0.5, 1.0); - } - - @Override - public boolean ctrlTogglesOffStrokeOrder() { - return ctrlTogglesOffStrokeOrder; - } - - @Override - public boolean invertSpellbookScrollDirection() { - return invertSpellbookScrollDirection; - } - - @Override - public boolean invertAbacusScrollDirection() { - return invertAbacusScrollDirection; - } - - @Override - public double gridSnapThreshold() { - return gridSnapThreshold; - } - - @Override - public boolean clickingTogglesDrawing() { - return clickingTogglesDrawing; - } - } - - @Config(name = "server") - public static final class Server implements HexConfig.ServerConfigAccess, ConfigData { - @ConfigEntry.BoundedDiscrete(min = 0, max = 4) - @ConfigEntry.Gui.Tooltip - private int opBreakHarvestLevel = DEFAULT_OP_BREAK_HARVEST_LEVEL; - @ConfigEntry.Gui.Tooltip - private int maxOpCount = DEFAULT_MAX_OP_COUNT; - @ConfigEntry.Gui.Tooltip - private int maxSpellCircleLength = DEFAULT_MAX_SPELL_CIRCLE_LENGTH; - @ConfigEntry.Gui.Tooltip - private List<String> actionDenyList = List.of(); - @ConfigEntry.Gui.Tooltip - private List<String> circleActionDenyList = List.of(); - @ConfigEntry.Gui.Tooltip - private boolean villagersOffendedByMindMurder = DEFAULT_VILLAGERS_DISLIKE_MIND_MURDER; - @ConfigEntry.Gui.Tooltip - private boolean doesTrueNameHaveAmbit = DEFAULT_TRUE_NAME_HAS_AMBIT; - - - @ConfigEntry.Gui.Tooltip - private List<String> tpDimDenylist = DEFAULT_DIM_TP_DENYLIST; - - // ModMenu bad and doesn't like java objects in here so we do stupid string parsing - @ConfigEntry.Gui.Tooltip - private List<String> scrollInjectionsRaw = HexLootHandler.DEFAULT_SCROLL_INJECTS - .stream() - .map(si -> si.injectee() + " " + si.countRange()) - .toList(); - @ConfigEntry.Gui.Excluded - private transient Object2IntMap<ResourceLocation> scrollInjections; - - // TODO: hook this up to the config, change Jankery, test, also test scroll injects on fabric - @ConfigEntry.Gui.Tooltip - private List<String> loreInjectionsRaw = HexLootHandler.DEFAULT_LORE_INJECTS - .stream() - .map(ResourceLocation::toString) - .toList(); - @ConfigEntry.Gui.Excluded - private transient List<ResourceLocation> loreInjections; - @ConfigEntry.Gui.Tooltip - private double loreChance = HexLootHandler.DEFAULT_LORE_CHANCE; - - - @Override - public void validatePostLoad() throws ValidationException { - this.maxOpCount = Math.max(this.maxOpCount, 0); - this.maxSpellCircleLength = Math.max(this.maxSpellCircleLength, 4); - - this.scrollInjections = new Object2IntOpenHashMap<>(); - try { - for (var auugh : this.scrollInjectionsRaw) { - String[] split = auugh.split(" "); - ResourceLocation loc = new ResourceLocation(split[0]); - int count = Integer.parseInt(split[1]); - this.scrollInjections.put(loc, count); - } - - } catch (Exception e) { - throw new ValidationException("Bad parsing of scroll injects", e); - } - - this.loreInjections = new ArrayList<>(); - try { - for (var table : this.loreInjectionsRaw) { - ResourceLocation loc = new ResourceLocation(table); - this.loreInjections.add(loc); - } - } catch (Exception e) { - throw new ValidationException("Bad parsing of lore injects", e); - } - - this.loreChance = Mth.clamp(this.loreChance, 0.0, 1.0); - } - - @Override - public int opBreakHarvestLevelBecauseForgeThoughtItWasAGoodIdeaToImplementHarvestTiersUsingAnHonestToGodTopoSort() { - return opBreakHarvestLevel; - } - - @Override - public int maxOpCount() { - return maxOpCount; - } - - @Override - public int maxSpellCircleLength() { - return maxSpellCircleLength; - } - - @Override - public boolean isActionAllowed(ResourceLocation actionID) { - return noneMatch(actionDenyList, actionID); - } - - @Override - public boolean isActionAllowedInCircles(ResourceLocation actionID) { - return noneMatch(circleActionDenyList, actionID); - } - - @Override - public boolean doVillagersTakeOffenseAtMindMurder() { - return villagersOffendedByMindMurder; - } - - @Override - public boolean canTeleportInThisDimension(ResourceKey<Level> dimension) { - return noneMatch(tpDimDenylist, dimension.location()); - } - - @Override - public boolean trueNameHasAmbit() { - return doesTrueNameHaveAmbit; - } - - /** - * Returns -1 if none is found - */ - public int scrollRangeForLootTable(ResourceLocation lootTable) { - return this.scrollInjections.getOrDefault(lootTable, -1); - } - - public boolean shouldInjectLore(ResourceLocation lootTable) { - return anyMatchResLoc(this.loreInjections, lootTable); - } - - public double getLoreChance() { - return loreChance; - } - } + @ConfigEntry.Category("common") + @ConfigEntry.Gui.TransitiveObject + public final Common common = new Common(); + + @ConfigEntry.Category("client") + @ConfigEntry.Gui.TransitiveObject + public final Client client = new Client(); + + @ConfigEntry.Category("server") + @ConfigEntry.Gui.TransitiveObject + public final Server server = new Server(); + + public static FabricHexConfig setup() { + var gson = + new GsonBuilder() + .setPrettyPrinting() + .registerTypeAdapter(ResourceLocation.class, new ResourceLocation.Serializer()) + .create(); + AutoConfig.register( + FabricHexConfig.class, + PartitioningSerializer.wrap((cfg, clazz) -> new GsonConfigSerializer<>(cfg, clazz, gson))); + var instance = AutoConfig.getConfigHolder(FabricHexConfig.class).getConfig(); + + HexConfig.setCommon(instance.common); + // We care about the client only on the *physical* client ... + if (IXplatAbstractions.INSTANCE.isPhysicalClient()) { + HexConfig.setClient(instance.client); + } + // but we care about the server on the *logical* server + // i believe this should Just Work without a guard? assuming we don't access it from the client + // ever + HexConfig.setServer(instance.server); + + return instance; + } + + @Config(name = "common") + public static final class Common implements HexConfig.CommonConfigAccess, ConfigData { + @ConfigEntry.Gui.Tooltip private long dustMediaAmount = DEFAULT_DUST_MEDIA_AMOUNT; + @ConfigEntry.Gui.Tooltip private long shardMediaAmount = DEFAULT_SHARD_MEDIA_AMOUNT; + @ConfigEntry.Gui.Tooltip private long chargedCrystalMediaAmount = DEFAULT_CHARGED_MEDIA_AMOUNT; + @ConfigEntry.Gui.Tooltip private double mediaToHealthRate = DEFAULT_MEDIA_TO_HEALTH_RATE; + + @ConfigEntry.Gui.Tooltip private int cypherCooldown = DEFAULT_CYPHER_COOLDOWN; + @ConfigEntry.Gui.Tooltip private int trinketCooldown = DEFAULT_TRINKET_COOLDOWN; + @ConfigEntry.Gui.Tooltip private int artifactCooldown = DEFAULT_ARTIFACT_COOLDOWN; + + @Override + public void validatePostLoad() throws ValidationException { + this.dustMediaAmount = Math.max(this.dustMediaAmount, 0); + this.shardMediaAmount = Math.max(this.shardMediaAmount, 0); + this.chargedCrystalMediaAmount = Math.max(this.chargedCrystalMediaAmount, 0); + this.mediaToHealthRate = Math.max(this.mediaToHealthRate, 0); + } + + @Override + public long dustMediaAmount() { + return dustMediaAmount; + } + + @Override + public long shardMediaAmount() { + return shardMediaAmount; + } + + @Override + public long chargedCrystalMediaAmount() { + return chargedCrystalMediaAmount; + } + + @Override + public double mediaToHealthRate() { + return mediaToHealthRate; + } + + @Override + public int cypherCooldown() { + return cypherCooldown; + } + + @Override + public int trinketCooldown() { + return trinketCooldown; + } + + @Override + public int artifactCooldown() { + return artifactCooldown; + } + } + + @Config(name = "client") + public static final class Client implements HexConfig.ClientConfigAccess, ConfigData { + @ConfigEntry.Gui.Tooltip + private boolean ctrlTogglesOffStrokeOrder = DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER; + + @ConfigEntry.Gui.Tooltip + private boolean invertSpellbookScrollDirection = DEFAULT_INVERT_SPELLBOOK_SCROLL; + + @ConfigEntry.Gui.Tooltip + private boolean invertAbacusScrollDirection = DEFAULT_INVERT_SPELLBOOK_SCROLL; + + @ConfigEntry.Gui.Tooltip private double gridSnapThreshold = DEFAULT_GRID_SNAP_THRESHOLD; + + @ConfigEntry.Gui.Tooltip + private boolean clickingTogglesDrawing = DEFAULT_CLICKING_TOGGLES_DRAWING; + + @Override + public void validatePostLoad() throws ValidationException { + this.gridSnapThreshold = Mth.clamp(this.gridSnapThreshold, 0.5, 1.0); + } + + @Override + public boolean ctrlTogglesOffStrokeOrder() { + return ctrlTogglesOffStrokeOrder; + } + + @Override + public boolean invertSpellbookScrollDirection() { + return invertSpellbookScrollDirection; + } + + @Override + public boolean invertAbacusScrollDirection() { + return invertAbacusScrollDirection; + } + + @Override + public double gridSnapThreshold() { + return gridSnapThreshold; + } + + @Override + public boolean clickingTogglesDrawing() { + return clickingTogglesDrawing; + } + } + + @Config(name = "server") + public static final class Server implements HexConfig.ServerConfigAccess, ConfigData { + @ConfigEntry.BoundedDiscrete(min = 0, max = 4) + @ConfigEntry.Gui.Tooltip + private int opBreakHarvestLevel = DEFAULT_OP_BREAK_HARVEST_LEVEL; + + @ConfigEntry.Gui.Tooltip private int maxOpCount = DEFAULT_MAX_OP_COUNT; + @ConfigEntry.Gui.Tooltip private int maxSpellCircleLength = DEFAULT_MAX_SPELL_CIRCLE_LENGTH; + @ConfigEntry.Gui.Tooltip private List<String> actionDenyList = List.of(); + @ConfigEntry.Gui.Tooltip private List<String> circleActionDenyList = List.of(); + + @ConfigEntry.Gui.Tooltip + private boolean villagersOffendedByMindMurder = DEFAULT_VILLAGERS_DISLIKE_MIND_MURDER; + + @ConfigEntry.Gui.Tooltip private boolean doesTrueNameHaveAmbit = DEFAULT_TRUE_NAME_HAS_AMBIT; + + @ConfigEntry.Gui.Tooltip private List<String> tpDimDenylist = DEFAULT_DIM_TP_DENYLIST; + + // ModMenu bad and doesn't like java objects in here so we do stupid string parsing + @ConfigEntry.Gui.Tooltip + private List<String> scrollInjectionsRaw = + HexLootHandler.DEFAULT_SCROLL_INJECTS.stream() + .map(si -> si.injectee() + " " + si.countRange()) + .toList(); + + @ConfigEntry.Gui.Excluded private transient Object2IntMap<ResourceLocation> scrollInjections; + + // TODO: hook this up to the config, change Jankery, test, also test scroll injects on fabric + @ConfigEntry.Gui.Tooltip + private List<String> loreInjectionsRaw = + HexLootHandler.DEFAULT_LORE_INJECTS.stream().map(ResourceLocation::toString).toList(); + + @ConfigEntry.Gui.Excluded private transient List<ResourceLocation> loreInjections; + @ConfigEntry.Gui.Tooltip private double loreChance = HexLootHandler.DEFAULT_LORE_CHANCE; + + @Override + public void validatePostLoad() throws ValidationException { + this.maxOpCount = Math.max(this.maxOpCount, 0); + this.maxSpellCircleLength = Math.max(this.maxSpellCircleLength, 4); + + this.scrollInjections = new Object2IntOpenHashMap<>(); + try { + for (var auugh : this.scrollInjectionsRaw) { + String[] split = auugh.split(" "); + ResourceLocation loc = new ResourceLocation(split[0]); + int count = Integer.parseInt(split[1]); + this.scrollInjections.put(loc, count); + } + + } catch (Exception e) { + throw new ValidationException("Bad parsing of scroll injects", e); + } + + this.loreInjections = new ArrayList<>(); + try { + for (var table : this.loreInjectionsRaw) { + ResourceLocation loc = new ResourceLocation(table); + this.loreInjections.add(loc); + } + } catch (Exception e) { + throw new ValidationException("Bad parsing of lore injects", e); + } + + this.loreChance = Mth.clamp(this.loreChance, 0.0, 1.0); + } + + @Override + public int + opBreakHarvestLevelBecauseForgeThoughtItWasAGoodIdeaToImplementHarvestTiersUsingAnHonestToGodTopoSort() { + return opBreakHarvestLevel; + } + + @Override + public int maxOpCount() { + return maxOpCount; + } + + @Override + public int maxSpellCircleLength() { + return maxSpellCircleLength; + } + + @Override + public boolean isActionAllowed(ResourceLocation actionID) { + return noneMatch(actionDenyList, actionID); + } + + @Override + public boolean isActionAllowedInCircles(ResourceLocation actionID) { + return noneMatch(circleActionDenyList, actionID); + } + + @Override + public boolean doVillagersTakeOffenseAtMindMurder() { + return villagersOffendedByMindMurder; + } + + @Override + public boolean canTeleportInThisDimension(ResourceKey<Level> dimension) { + return noneMatch(tpDimDenylist, dimension.location()); + } + + @Override + public boolean trueNameHasAmbit() { + return doesTrueNameHaveAmbit; + } + + /** Returns -1 if none is found */ + public int scrollRangeForLootTable(ResourceLocation lootTable) { + return this.scrollInjections.getOrDefault(lootTable, -1); + } + + public boolean shouldInjectLore(ResourceLocation lootTable) { + return anyMatchResLoc(this.loreInjections, lootTable); + } + + public double getLoreChance() { + return loreChance; + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt index e7d3163458..cfa7880848 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt @@ -26,6 +26,7 @@ import at.petrak.hexcasting.fabric.storage.FabricImpetusStorage import at.petrak.hexcasting.interop.HexInterop import at.petrak.hexcasting.xplat.IXplatAbstractions import io.github.tropheusj.serialization_hooks.ingredient.IngredientDeserializer +import java.util.function.BiConsumer import net.fabricmc.api.ModInitializer import net.fabricmc.fabric.api.command.v2.ArgumentTypeRegistry import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback @@ -44,179 +45,189 @@ import net.minecraft.resources.ResourceLocation import net.minecraft.world.InteractionResult import net.minecraft.world.entity.player.Player import net.minecraft.world.level.block.state.properties.BlockSetType -import java.util.function.BiConsumer object FabricHexInitializer : ModInitializer { - lateinit var CONFIG: FabricHexConfig - - override fun onInitialize() { - this.CONFIG = FabricHexConfig.setup() - FabricPacketHandler.init() - - initListeners() - - initRegistries() - - ArgumentTypeRegistry.registerArgumentType( - modLoc("pattern"), - PatternResLocArgument::class.java, - SingletonArgumentInfo.contextFree { PatternResLocArgument.id() } - ) - HexAdvancementTriggers.registerTriggers() - HexComposting.setup() - HexStrippables.init() - FabricImpetusStorage.registerStorage() - - HexInterop.init() - RegisterMisc.register() - } - - fun initListeners() { - UseEntityCallback.EVENT.register(BrainsweepingEvents::interactWithBrainswept) - VillagerConversionCallback.EVENT.register(BrainsweepingEvents::copyBrainsweepPostTransformation) - AttackBlockCallback.EVENT.register { player, world, _, pos, _ -> - // SUCCESS cancels further processing and, on the client, sends a packet to the server. - // PASS falls back to further processing. - // FAIL cancels further processing and does not send a packet to the server. - if (ItemJewelerHammer.shouldFailToBreak(player, world.getBlockState(pos), pos)) { - InteractionResult.SUCCESS // "success" - } else { - InteractionResult.PASS - } - } - - ServerLifecycleEvents.SERVER_STARTED.register { server -> - PatternRegistryManifest.processRegistry(server.overworld()) - } - - ServerTickEvents.END_WORLD_TICK.register(PlayerPositionRecorder::updateAllPlayers) - ServerTickEvents.END_WORLD_TICK.register(OpFlight::tickAllPlayers) - ServerTickEvents.END_WORLD_TICK.register(OpAltiora::checkAllPlayers) - - CommandRegistrationCallback.EVENT.register { dp, _, _ -> HexCommands.register(dp) } - - LootTableEvents.MODIFY.register { _, _, id, supplier, _ -> - FabricHexLootModJankery.lootLoad(id, supplier::withPool) - } - - EntityElytraEvents.CUSTOM.register { target, _ -> - if (target is Player) { - val altiora = IXplatAbstractions.INSTANCE.getAltiora(target) - altiora != null - } else { - false - } - } - - ItemGroupEvents.MODIFY_ENTRIES_ALL.register { tab, entries -> - HexBlocks.registerBlockCreativeTab(entries::accept, tab) - HexItems.registerItemCreativeTab(entries, tab) - } - } - - private fun initRegistries() { - fabricOnlyRegistration() - - HexBlockSetTypes.registerBlocks(BlockSetType::register) - - HexCreativeTabs.registerCreativeTabs(bind(BuiltInRegistries.CREATIVE_MODE_TAB)) - - HexSounds.registerSounds(bind(BuiltInRegistries.SOUND_EVENT)) - HexBlocks.registerBlocks(bind(BuiltInRegistries.BLOCK)) - HexBlocks.registerBlockItems(bind(BuiltInRegistries.ITEM)) - HexBlockEntities.registerTiles(bind(BuiltInRegistries.BLOCK_ENTITY_TYPE)) - HexItems.registerItems(bind(BuiltInRegistries.ITEM)) - Registry.register(IngredientDeserializer.REGISTRY, FabricModConditionalIngredient.ID, FabricModConditionalIngredient.Deserializer.INSTANCE) - - HexEntities.registerEntities(bind(BuiltInRegistries.ENTITY_TYPE)) - HexAttributes.register(bind(BuiltInRegistries.ATTRIBUTE)) - HexMobEffects.register(bind(BuiltInRegistries.MOB_EFFECT)) - HexPotions.register(bind(BuiltInRegistries.POTION)) - HexPotions.addRecipes() - - HexRecipeStuffRegistry.registerSerializers(bind(BuiltInRegistries.RECIPE_SERIALIZER)) - HexRecipeStuffRegistry.registerTypes(bind(BuiltInRegistries.RECIPE_TYPE)) - - HexParticles.registerParticles(bind(BuiltInRegistries.PARTICLE_TYPE)) - - HexLootFunctions.registerSerializers(bind(BuiltInRegistries.LOOT_FUNCTION_TYPE)) - - HexIotaTypes.registerTypes(bind(IXplatAbstractions.INSTANCE.iotaTypeRegistry)) - HexActions.register(bind(IXplatAbstractions.INSTANCE.actionRegistry)) - HexSpecialHandlers.register(bind(IXplatAbstractions.INSTANCE.specialHandlerRegistry)) - HexArithmetics.register(bind(IXplatAbstractions.INSTANCE.arithmeticRegistry)) - HexContinuationTypes.registerContinuations(bind(IXplatAbstractions.INSTANCE.continuationTypeRegistry)) - HexEvalSounds.register(bind(IXplatAbstractions.INSTANCE.evalSoundRegistry)) - - // Because of Java's lazy-loading of classes, can't use Kotlin static initialization for - // any calls that will eventually touch FeatureUtils.register(), as the growers here do, - // unless the class is called in this initialization step. - AkashicTreeGrower.init() - - // Done with soft implements in forge - butYouCouldBeFire() - - HexStatistics.register() - } - - // sorry lex (not sorry) - private fun fabricOnlyRegistration() { -// if (GravityApiInterop.isActive()) { -// HexActions.make("interop/gravity/get", -// ActionRegistryEntry(HexPattern.fromAngles("wawawddew", HexDir.NORTH_EAST), OpGetGravity)) -// HexActions.make("interop/gravity/set", -// ActionRegistryEntry(HexPattern.fromAngles("wdwdwaaqw", HexDir.NORTH_WEST), OpChangeGravity)) -// } - } - - private fun butYouCouldBeFire() { - val flameOn = FlammableBlockRegistry.getDefaultInstance() - for (log in listOf( - HexBlocks.EDIFIED_LOG, - HexBlocks.EDIFIED_LOG_AMETHYST, - HexBlocks.EDIFIED_LOG_AVENTURINE, - HexBlocks.EDIFIED_LOG_CITRINE, - HexBlocks.EDIFIED_LOG_PURPLE, - HexBlocks.STRIPPED_EDIFIED_LOG, - HexBlocks.EDIFIED_WOOD, - HexBlocks.STRIPPED_EDIFIED_LOG, - )) { - flameOn.add(log, 5, 5) - } - for (wood in listOf( - HexBlocks.EDIFIED_PLANKS, - HexBlocks.EDIFIED_PANEL, - HexBlocks.EDIFIED_TILE, - HexBlocks.EDIFIED_DOOR, - HexBlocks.EDIFIED_TRAPDOOR, - HexBlocks.EDIFIED_STAIRS, - HexBlocks.EDIFIED_SLAB, - HexBlocks.EDIFIED_FENCE, - HexBlocks.EDIFIED_FENCE_GATE, - HexBlocks.EDIFIED_SLAB, - HexBlocks.EDIFIED_BUTTON, - HexBlocks.EDIFIED_PRESSURE_PLATE, - )) { - flameOn.add(wood, 20, 5) - } - for (papery in listOf( - HexBlocks.SCROLL_PAPER, - HexBlocks.SCROLL_PAPER_LANTERN, - HexBlocks.ANCIENT_SCROLL_PAPER, - HexBlocks.ANCIENT_SCROLL_PAPER_LANTERN, - - )) { - flameOn.add(papery, 100, 60) - } - for (leaves in listOf( - HexBlocks.AMETHYST_EDIFIED_LEAVES, - HexBlocks.AVENTURINE_EDIFIED_LEAVES, - HexBlocks.CITRINE_EDIFIED_LEAVES, - )) { - flameOn.add(leaves, 60, 30) - } - } - - private fun <T> bind(registry: Registry<in T>): BiConsumer<T, ResourceLocation> = - BiConsumer<T, ResourceLocation> { t, id -> Registry.register(registry, id, t) } + lateinit var CONFIG: FabricHexConfig + + override fun onInitialize() { + this.CONFIG = FabricHexConfig.setup() + FabricPacketHandler.init() + + initListeners() + + initRegistries() + + ArgumentTypeRegistry.registerArgumentType( + modLoc("pattern"), + PatternResLocArgument::class.java, + SingletonArgumentInfo.contextFree { PatternResLocArgument.id() } + ) + HexAdvancementTriggers.registerTriggers() + HexComposting.setup() + HexStrippables.init() + FabricImpetusStorage.registerStorage() + + HexInterop.init() + RegisterMisc.register() + } + + fun initListeners() { + UseEntityCallback.EVENT.register(BrainsweepingEvents::interactWithBrainswept) + VillagerConversionCallback.EVENT.register(BrainsweepingEvents::copyBrainsweepPostTransformation) + AttackBlockCallback.EVENT.register { player, world, _, pos, _ -> + // SUCCESS cancels further processing and, on the client, sends a packet to the server. + // PASS falls back to further processing. + // FAIL cancels further processing and does not send a packet to the server. + if (ItemJewelerHammer.shouldFailToBreak(player, world.getBlockState(pos), pos)) { + InteractionResult.SUCCESS // "success" + } else { + InteractionResult.PASS + } + } + + ServerLifecycleEvents.SERVER_STARTED.register { server -> + PatternRegistryManifest.processRegistry(server.overworld()) + } + + ServerTickEvents.END_WORLD_TICK.register(PlayerPositionRecorder::updateAllPlayers) + ServerTickEvents.END_WORLD_TICK.register(OpFlight::tickAllPlayers) + ServerTickEvents.END_WORLD_TICK.register(OpAltiora::checkAllPlayers) + + CommandRegistrationCallback.EVENT.register { dp, _, _ -> HexCommands.register(dp) } + + LootTableEvents.MODIFY.register { _, _, id, supplier, _ -> + FabricHexLootModJankery.lootLoad(id, supplier::withPool) + } + + EntityElytraEvents.CUSTOM.register { target, _ -> + if (target is Player) { + val altiora = IXplatAbstractions.INSTANCE.getAltiora(target) + altiora != null + } else { + false + } + } + + ItemGroupEvents.MODIFY_ENTRIES_ALL.register { tab, entries -> + HexBlocks.registerBlockCreativeTab(entries::accept, tab) + HexItems.registerItemCreativeTab(entries, tab) + } + } + + private fun initRegistries() { + fabricOnlyRegistration() + + HexBlockSetTypes.registerBlocks(BlockSetType::register) + + HexCreativeTabs.registerCreativeTabs(bind(BuiltInRegistries.CREATIVE_MODE_TAB)) + + HexSounds.registerSounds(bind(BuiltInRegistries.SOUND_EVENT)) + HexBlocks.registerBlocks(bind(BuiltInRegistries.BLOCK)) + HexBlocks.registerBlockItems(bind(BuiltInRegistries.ITEM)) + HexBlockEntities.registerTiles(bind(BuiltInRegistries.BLOCK_ENTITY_TYPE)) + HexItems.registerItems(bind(BuiltInRegistries.ITEM)) + Registry.register( + IngredientDeserializer.REGISTRY, + FabricModConditionalIngredient.ID, + FabricModConditionalIngredient.Deserializer.INSTANCE + ) + + HexEntities.registerEntities(bind(BuiltInRegistries.ENTITY_TYPE)) + HexAttributes.register(bind(BuiltInRegistries.ATTRIBUTE)) + HexMobEffects.register(bind(BuiltInRegistries.MOB_EFFECT)) + HexPotions.register(bind(BuiltInRegistries.POTION)) + HexPotions.addRecipes() + + HexRecipeStuffRegistry.registerSerializers(bind(BuiltInRegistries.RECIPE_SERIALIZER)) + HexRecipeStuffRegistry.registerTypes(bind(BuiltInRegistries.RECIPE_TYPE)) + + HexParticles.registerParticles(bind(BuiltInRegistries.PARTICLE_TYPE)) + + HexLootFunctions.registerSerializers(bind(BuiltInRegistries.LOOT_FUNCTION_TYPE)) + + HexIotaTypes.registerTypes(bind(IXplatAbstractions.INSTANCE.iotaTypeRegistry)) + HexActions.register(bind(IXplatAbstractions.INSTANCE.actionRegistry)) + HexSpecialHandlers.register(bind(IXplatAbstractions.INSTANCE.specialHandlerRegistry)) + HexArithmetics.register(bind(IXplatAbstractions.INSTANCE.arithmeticRegistry)) + HexContinuationTypes.registerContinuations( + bind(IXplatAbstractions.INSTANCE.continuationTypeRegistry) + ) + HexEvalSounds.register(bind(IXplatAbstractions.INSTANCE.evalSoundRegistry)) + + // Because of Java's lazy-loading of classes, can't use Kotlin static initialization for + // any calls that will eventually touch FeatureUtils.register(), as the growers here do, + // unless the class is called in this initialization step. + AkashicTreeGrower.init() + + // Done with soft implements in forge + butYouCouldBeFire() + + HexStatistics.register() + } + + // sorry lex (not sorry) + private fun fabricOnlyRegistration() { + // if (GravityApiInterop.isActive()) { + // HexActions.make("interop/gravity/get", + // ActionRegistryEntry(HexPattern.fromAngles("wawawddew", HexDir.NORTH_EAST), + // OpGetGravity)) + // HexActions.make("interop/gravity/set", + // ActionRegistryEntry(HexPattern.fromAngles("wdwdwaaqw", HexDir.NORTH_WEST), + // OpChangeGravity)) + // } + } + + private fun butYouCouldBeFire() { + val flameOn = FlammableBlockRegistry.getDefaultInstance() + for (log in + listOf( + HexBlocks.EDIFIED_LOG, + HexBlocks.EDIFIED_LOG_AMETHYST, + HexBlocks.EDIFIED_LOG_AVENTURINE, + HexBlocks.EDIFIED_LOG_CITRINE, + HexBlocks.EDIFIED_LOG_PURPLE, + HexBlocks.STRIPPED_EDIFIED_LOG, + HexBlocks.EDIFIED_WOOD, + HexBlocks.STRIPPED_EDIFIED_LOG, + )) { + flameOn.add(log, 5, 5) + } + for (wood in + listOf( + HexBlocks.EDIFIED_PLANKS, + HexBlocks.EDIFIED_PANEL, + HexBlocks.EDIFIED_TILE, + HexBlocks.EDIFIED_DOOR, + HexBlocks.EDIFIED_TRAPDOOR, + HexBlocks.EDIFIED_STAIRS, + HexBlocks.EDIFIED_SLAB, + HexBlocks.EDIFIED_FENCE, + HexBlocks.EDIFIED_FENCE_GATE, + HexBlocks.EDIFIED_SLAB, + HexBlocks.EDIFIED_BUTTON, + HexBlocks.EDIFIED_PRESSURE_PLATE, + )) { + flameOn.add(wood, 20, 5) + } + for (papery in + listOf( + HexBlocks.SCROLL_PAPER, + HexBlocks.SCROLL_PAPER_LANTERN, + HexBlocks.ANCIENT_SCROLL_PAPER, + HexBlocks.ANCIENT_SCROLL_PAPER_LANTERN, + )) { + flameOn.add(papery, 100, 60) + } + for (leaves in + listOf( + HexBlocks.AMETHYST_EDIFIED_LEAVES, + HexBlocks.AVENTURINE_EDIFIED_LEAVES, + HexBlocks.CITRINE_EDIFIED_LEAVES, + )) { + flameOn.add(leaves, 60, 30) + } + } + + private fun <T> bind(registry: Registry<in T>): BiConsumer<T, ResourceLocation> = + BiConsumer<T, ResourceLocation> { t, id -> Registry.register(registry, id, t) } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCAltiora.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCAltiora.java index 17d1489f76..0c576e8785 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCAltiora.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCAltiora.java @@ -8,47 +8,41 @@ import org.jetbrains.annotations.Nullable; public class CCAltiora implements Component, AutoSyncedComponent { - public static final String - TAG_ALLOWED = "allowed", - TAG_GRACE = "grace_period"; - - @Nullable - private AltioraAbility altiora = null; - - private final Player owner; - - public CCAltiora(Player owner) { - this.owner = owner; - } - - - @Nullable - public AltioraAbility getAltiora() { - return this.altiora; - } - - - public void setAltiora(AltioraAbility altiora) { - this.altiora = altiora; - HexCardinalComponents.ALTIORA.sync(this.owner); - } - - @Override - public void readFromNbt(CompoundTag tag) { - var allowed = tag.getBoolean(TAG_ALLOWED); - if (!allowed) { - this.altiora = null; - } else { - var grace = tag.getInt(TAG_GRACE); - this.altiora = new AltioraAbility(grace); - } - } - - @Override - public void writeToNbt(CompoundTag tag) { - tag.putBoolean(TAG_ALLOWED, this.altiora != null); - if (this.altiora != null) { - tag.putInt(TAG_GRACE, this.altiora.gracePeriod()); - } - } + public static final String TAG_ALLOWED = "allowed", TAG_GRACE = "grace_period"; + + @Nullable private AltioraAbility altiora = null; + + private final Player owner; + + public CCAltiora(Player owner) { + this.owner = owner; + } + + @Nullable public AltioraAbility getAltiora() { + return this.altiora; + } + + public void setAltiora(AltioraAbility altiora) { + this.altiora = altiora; + HexCardinalComponents.ALTIORA.sync(this.owner); + } + + @Override + public void readFromNbt(CompoundTag tag) { + var allowed = tag.getBoolean(TAG_ALLOWED); + if (!allowed) { + this.altiora = null; + } else { + var grace = tag.getInt(TAG_GRACE); + this.altiora = new AltioraAbility(grace); + } + } + + @Override + public void writeToNbt(CompoundTag tag) { + tag.putBoolean(TAG_ALLOWED, this.altiora != null); + if (this.altiora != null) { + tag.putInt(TAG_GRACE, this.altiora.gracePeriod()); + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCBrainswept.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCBrainswept.java index 34406f7421..145737347f 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCBrainswept.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCBrainswept.java @@ -8,39 +8,38 @@ import net.minecraft.world.entity.Mob; public class CCBrainswept implements Component, AutoSyncedComponent { - public static final String TAG_BRAINSWEPT = "brainswept"; + public static final String TAG_BRAINSWEPT = "brainswept"; - private final LivingEntity owner; + private final LivingEntity owner; - public CCBrainswept(LivingEntity owner) { - this.owner = owner; - } + public CCBrainswept(LivingEntity owner) { + this.owner = owner; + } - private boolean brainswept = false; + private boolean brainswept = false; - public boolean isBrainswept() { - return this.brainswept; - } + public boolean isBrainswept() { + return this.brainswept; + } - public void setBrainswept(boolean brainswept) { - this.brainswept = brainswept; - HexCardinalComponents.BRAINSWEPT.sync(this.owner); - } + public void setBrainswept(boolean brainswept) { + this.brainswept = brainswept; + HexCardinalComponents.BRAINSWEPT.sync(this.owner); + } - @Override - public void applySyncPacket(FriendlyByteBuf buf) { - AutoSyncedComponent.super.applySyncPacket(buf); - if (owner instanceof Mob mob && brainswept) - mob.removeFreeWill(); - } + @Override + public void applySyncPacket(FriendlyByteBuf buf) { + AutoSyncedComponent.super.applySyncPacket(buf); + if (owner instanceof Mob mob && brainswept) mob.removeFreeWill(); + } - @Override - public void readFromNbt(CompoundTag tag) { - this.brainswept = tag.getBoolean(TAG_BRAINSWEPT); - } + @Override + public void readFromNbt(CompoundTag tag) { + this.brainswept = tag.getBoolean(TAG_BRAINSWEPT); + } - @Override - public void writeToNbt(CompoundTag tag) { - tag.putBoolean(TAG_BRAINSWEPT, this.brainswept); - } + @Override + public void writeToNbt(CompoundTag tag) { + tag.putBoolean(TAG_BRAINSWEPT, this.brainswept); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCClientCastingStack.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCClientCastingStack.java index 90fbadffeb..56b35b25d0 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCClientCastingStack.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCClientCastingStack.java @@ -8,23 +8,22 @@ public class CCClientCastingStack implements Component, ClientTickingComponent { - public CCClientCastingStack(Player owner) { - } + public CCClientCastingStack(Player owner) {} - private final ClientCastingStack clientCastingStack = new ClientCastingStack(); + private final ClientCastingStack clientCastingStack = new ClientCastingStack(); - public ClientCastingStack getClientCastingStack() { - return clientCastingStack; - } + public ClientCastingStack getClientCastingStack() { + return clientCastingStack; + } - @Override - public void clientTick() { - clientCastingStack.tick(); - } + @Override + public void clientTick() { + clientCastingStack.tick(); + } - @Override - public void readFromNbt(CompoundTag tag) { } + @Override + public void readFromNbt(CompoundTag tag) {} - @Override - public void writeToNbt(CompoundTag tag) { } + @Override + public void writeToNbt(CompoundTag tag) {} } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCFavoredPigment.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCFavoredPigment.java index 7eaf3b5ba1..81a00f30de 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCFavoredPigment.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCFavoredPigment.java @@ -7,38 +7,36 @@ import net.minecraft.world.entity.player.Player; import org.jetbrains.annotations.Nullable; -/** - * Holds the pigment item favored by the player - */ +/** Holds the pigment item favored by the player */ public class CCFavoredPigment implements Component, AutoSyncedComponent { - public static final String TAG_PIGMENT = "pigment"; + public static final String TAG_PIGMENT = "pigment"; - private final Player owner; + private final Player owner; - public CCFavoredPigment(Player owner) { - this.owner = owner; - } + public CCFavoredPigment(Player owner) { + this.owner = owner; + } - private FrozenPigment pigment = FrozenPigment.DEFAULT.get(); + private FrozenPigment pigment = FrozenPigment.DEFAULT.get(); - public FrozenPigment getPigment() { - return pigment; - } + public FrozenPigment getPigment() { + return pigment; + } - public FrozenPigment setPigment(@Nullable FrozenPigment pigment) { - var old = this.pigment; - this.pigment = pigment != null ? pigment : FrozenPigment.DEFAULT.get(); - HexCardinalComponents.FAVORED_PIGMENT.sync(this.owner); - return old; - } + public FrozenPigment setPigment(@Nullable FrozenPigment pigment) { + var old = this.pigment; + this.pigment = pigment != null ? pigment : FrozenPigment.DEFAULT.get(); + HexCardinalComponents.FAVORED_PIGMENT.sync(this.owner); + return old; + } - @Override - public void readFromNbt(CompoundTag tag) { - this.pigment = FrozenPigment.fromNBT(tag.getCompound(TAG_PIGMENT)); - } + @Override + public void readFromNbt(CompoundTag tag) { + this.pigment = FrozenPigment.fromNBT(tag.getCompound(TAG_PIGMENT)); + } - @Override - public void writeToNbt(CompoundTag tag) { - tag.put(TAG_PIGMENT, this.pigment.serializeToNBT()); - } + @Override + public void writeToNbt(CompoundTag tag) { + tag.put(TAG_PIGMENT, this.pigment.serializeToNBT()); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCFlight.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCFlight.java index e7747fac3f..dd992fb878 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCFlight.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCFlight.java @@ -11,54 +11,51 @@ import org.jetbrains.annotations.Nullable; public class CCFlight implements Component { - public static final String - TAG_ALLOWED = "allowed", // Fake: use this as a null sentinel - TAG_TIME_LEFT = "time_left", - TAG_DIMENSION = "dimension", - TAG_ORIGIN = "origin", - TAG_RADIUS = "radius"; - - private final ServerPlayer owner; - @Nullable - private FlightAbility flight = null; - - public CCFlight(ServerPlayer owner) { - this.owner = owner; - } - - - @Nullable - public FlightAbility getFlight() { - return flight; - } - - public void setFlight(FlightAbility flight) { - this.flight = flight; - } - - @Override - public void readFromNbt(CompoundTag tag) { - var allowed = tag.getBoolean(TAG_ALLOWED); - if (!allowed) { - this.flight = null; - } else { - var timeLeft = tag.getInt(TAG_TIME_LEFT); - var dim = ResourceKey.create(Registries.DIMENSION, - new ResourceLocation(tag.getString(TAG_DIMENSION))); - var origin = HexUtils.vecFromNBT(tag.getCompound(TAG_ORIGIN)); - var radius = tag.getDouble(TAG_RADIUS); - this.flight = new FlightAbility(timeLeft, dim, origin, radius); - } - } - - @Override - public void writeToNbt(CompoundTag tag) { - tag.putBoolean(TAG_ALLOWED, this.flight != null); - if (this.flight != null) { - tag.putInt(TAG_TIME_LEFT, this.flight.timeLeft()); - tag.putString(TAG_DIMENSION, this.flight.dimension().location().toString()); - tag.put(TAG_ORIGIN, HexUtils.serializeToNBT(this.flight.origin())); - tag.putDouble(TAG_RADIUS, this.flight.radius()); - } - } + public static final String TAG_ALLOWED = "allowed", // Fake: use this as a null sentinel + TAG_TIME_LEFT = "time_left", + TAG_DIMENSION = "dimension", + TAG_ORIGIN = "origin", + TAG_RADIUS = "radius"; + + private final ServerPlayer owner; + @Nullable private FlightAbility flight = null; + + public CCFlight(ServerPlayer owner) { + this.owner = owner; + } + + @Nullable public FlightAbility getFlight() { + return flight; + } + + public void setFlight(FlightAbility flight) { + this.flight = flight; + } + + @Override + public void readFromNbt(CompoundTag tag) { + var allowed = tag.getBoolean(TAG_ALLOWED); + if (!allowed) { + this.flight = null; + } else { + var timeLeft = tag.getInt(TAG_TIME_LEFT); + var dim = + ResourceKey.create( + Registries.DIMENSION, new ResourceLocation(tag.getString(TAG_DIMENSION))); + var origin = HexUtils.vecFromNBT(tag.getCompound(TAG_ORIGIN)); + var radius = tag.getDouble(TAG_RADIUS); + this.flight = new FlightAbility(timeLeft, dim, origin, radius); + } + } + + @Override + public void writeToNbt(CompoundTag tag) { + tag.putBoolean(TAG_ALLOWED, this.flight != null); + if (this.flight != null) { + tag.putInt(TAG_TIME_LEFT, this.flight.timeLeft()); + tag.putString(TAG_DIMENSION, this.flight.dimension().location().toString()); + tag.put(TAG_ORIGIN, HexUtils.serializeToNBT(this.flight.origin())); + tag.putDouble(TAG_RADIUS, this.flight.radius()); + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCPatterns.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCPatterns.java index 6faa0f70d8..872a894249 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCPatterns.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCPatterns.java @@ -2,54 +2,52 @@ import at.petrak.hexcasting.api.casting.eval.ResolvedPattern; import dev.onyxstudios.cca.api.v3.component.Component; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - public class CCPatterns implements Component { - public static final String TAG_PATTERNS = "patterns"; - - private final Player owner; + public static final String TAG_PATTERNS = "patterns"; - private List<ResolvedPattern> patterns = Collections.emptyList(); + private final Player owner; - public CCPatterns(ServerPlayer owner) { - this.owner = owner; - } + private List<ResolvedPattern> patterns = Collections.emptyList(); + public CCPatterns(ServerPlayer owner) { + this.owner = owner; + } - public List<ResolvedPattern> getPatterns() { - return patterns; - } + public List<ResolvedPattern> getPatterns() { + return patterns; + } - public void setPatterns(List<ResolvedPattern> patterns) { - this.patterns = patterns; - } + public void setPatterns(List<ResolvedPattern> patterns) { + this.patterns = patterns; + } - @Override - public void readFromNbt(CompoundTag tag) { - ListTag patternsTag = tag.getList(TAG_PATTERNS, Tag.TAG_COMPOUND); + @Override + public void readFromNbt(CompoundTag tag) { + ListTag patternsTag = tag.getList(TAG_PATTERNS, Tag.TAG_COMPOUND); - List<ResolvedPattern> patterns = new ArrayList<>(patternsTag.size()); + List<ResolvedPattern> patterns = new ArrayList<>(patternsTag.size()); - for (int i = 0; i < patternsTag.size(); i++) { - patterns.add(ResolvedPattern.fromNBT(patternsTag.getCompound(i))); - } - this.patterns = patterns; - } + for (int i = 0; i < patternsTag.size(); i++) { + patterns.add(ResolvedPattern.fromNBT(patternsTag.getCompound(i))); + } + this.patterns = patterns; + } - @Override - public void writeToNbt(CompoundTag tag) { - var listTag = new ListTag(); - for (ResolvedPattern pattern : patterns) { - listTag.add(pattern.serializeToNBT()); - } - tag.put(TAG_PATTERNS, listTag); - } + @Override + public void writeToNbt(CompoundTag tag) { + var listTag = new ListTag(); + for (ResolvedPattern pattern : patterns) { + listTag.add(pattern.serializeToNBT()); + } + tag.put(TAG_PATTERNS, listTag); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCSentinel.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCSentinel.java index d5925796fb..decc046b61 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCSentinel.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCSentinel.java @@ -4,58 +4,57 @@ import at.petrak.hexcasting.api.utils.HexUtils; import dev.onyxstudios.cca.api.v3.component.Component; import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; +import javax.annotation.Nullable; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; -import javax.annotation.Nullable; - public class CCSentinel implements Component, AutoSyncedComponent { - public static final String - TAG_HAS_SENTINEL = "has_sentinel", - TAG_EXTENDS_RANGE = "extends_range", - TAG_POSITION = "position", - TAG_DIMENSION = "dimension"; - - private final Player owner; - private @Nullable Sentinel sentinel = null; - - public CCSentinel(Player owner) { - this.owner = owner; - } - - public @Nullable Sentinel getSentinel() { - return sentinel; - } - - public void setSentinel(Sentinel sentinel) { - this.sentinel = sentinel; - HexCardinalComponents.SENTINEL.sync(this.owner); - } - - @Override - public void readFromNbt(CompoundTag tag) { - var hasSentinel = tag.getBoolean(TAG_HAS_SENTINEL); - if (hasSentinel) { - var extendsRange = tag.getBoolean(TAG_EXTENDS_RANGE); - var position = HexUtils.vecFromNBT(tag.getCompound(TAG_POSITION)); - var dim = ResourceKey.create(Registries.DIMENSION, - new ResourceLocation(tag.getString(TAG_DIMENSION))); - this.sentinel = new Sentinel(extendsRange, position, dim); - } else { - this.sentinel = null; - } - } - - @Override - public void writeToNbt(CompoundTag tag) { - tag.putBoolean(TAG_HAS_SENTINEL, this.sentinel != null); - if (this.sentinel != null) { - tag.putBoolean(TAG_EXTENDS_RANGE, this.sentinel.extendsRange()); - tag.put(TAG_POSITION, HexUtils.serializeToNBT(this.sentinel.position())); - tag.putString(TAG_DIMENSION, this.sentinel.dimension().location().toString()); - } - } + public static final String TAG_HAS_SENTINEL = "has_sentinel", + TAG_EXTENDS_RANGE = "extends_range", + TAG_POSITION = "position", + TAG_DIMENSION = "dimension"; + + private final Player owner; + private @Nullable Sentinel sentinel = null; + + public CCSentinel(Player owner) { + this.owner = owner; + } + + public @Nullable Sentinel getSentinel() { + return sentinel; + } + + public void setSentinel(Sentinel sentinel) { + this.sentinel = sentinel; + HexCardinalComponents.SENTINEL.sync(this.owner); + } + + @Override + public void readFromNbt(CompoundTag tag) { + var hasSentinel = tag.getBoolean(TAG_HAS_SENTINEL); + if (hasSentinel) { + var extendsRange = tag.getBoolean(TAG_EXTENDS_RANGE); + var position = HexUtils.vecFromNBT(tag.getCompound(TAG_POSITION)); + var dim = + ResourceKey.create( + Registries.DIMENSION, new ResourceLocation(tag.getString(TAG_DIMENSION))); + this.sentinel = new Sentinel(extendsRange, position, dim); + } else { + this.sentinel = null; + } + } + + @Override + public void writeToNbt(CompoundTag tag) { + tag.putBoolean(TAG_HAS_SENTINEL, this.sentinel != null); + if (this.sentinel != null) { + tag.putBoolean(TAG_EXTENDS_RANGE, this.sentinel.extendsRange()); + tag.put(TAG_POSITION, HexUtils.serializeToNBT(this.sentinel.position())); + tag.putString(TAG_DIMENSION, this.sentinel.dimension().location().toString()); + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCStaffcastImage.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCStaffcastImage.java index bb6018946f..70e16cde29 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCStaffcastImage.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/CCStaffcastImage.java @@ -10,40 +10,36 @@ import org.jetbrains.annotations.Nullable; public class CCStaffcastImage implements Component { - public static final String TAG_HARNESS = "harness"; - - private final ServerPlayer owner; - private CompoundTag lazyLoadedTag = new CompoundTag(); - - public CCStaffcastImage(ServerPlayer owner) { - this.owner = owner; - } - - /** - * Turn the saved image into a VM in a player staffcasting environment - */ - public CastingVM getVM(InteractionHand hand) { - var img = this.lazyLoadedTag.isEmpty() - ? new CastingImage() - : CastingImage.loadFromNbt(this.lazyLoadedTag, this.owner.serverLevel()); - var env = new StaffCastEnv(this.owner, hand); - return new CastingVM(img, env); - } - - public void setImage(@Nullable CastingImage image) { - this.lazyLoadedTag = - image == null - ? new CompoundTag() - : image.serializeToNbt(); - } - - @Override - public void readFromNbt(CompoundTag tag) { - this.lazyLoadedTag = tag.getCompound(TAG_HARNESS); - } - - @Override - public void writeToNbt(CompoundTag tag) { - tag.put(TAG_HARNESS, this.lazyLoadedTag); - } + public static final String TAG_HARNESS = "harness"; + + private final ServerPlayer owner; + private CompoundTag lazyLoadedTag = new CompoundTag(); + + public CCStaffcastImage(ServerPlayer owner) { + this.owner = owner; + } + + /** Turn the saved image into a VM in a player staffcasting environment */ + public CastingVM getVM(InteractionHand hand) { + var img = + this.lazyLoadedTag.isEmpty() + ? new CastingImage() + : CastingImage.loadFromNbt(this.lazyLoadedTag, this.owner.serverLevel()); + var env = new StaffCastEnv(this.owner, hand); + return new CastingVM(img, env); + } + + public void setImage(@Nullable CastingImage image) { + this.lazyLoadedTag = image == null ? new CompoundTag() : image.serializeToNbt(); + } + + @Override + public void readFromNbt(CompoundTag tag) { + this.lazyLoadedTag = tag.getCompound(TAG_HARNESS); + } + + @Override + public void writeToNbt(CompoundTag tag) { + tag.put(TAG_HARNESS, this.lazyLoadedTag); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/HexCardinalComponents.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/HexCardinalComponents.java index fd2f5978e1..5e74c9424b 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/HexCardinalComponents.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/HexCardinalComponents.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.fabric.cc; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.addldata.ADMediaHolder; import at.petrak.hexcasting.api.addldata.ItemDelegatingEntityIotaHolder; import at.petrak.hexcasting.api.casting.iota.DoubleIota; @@ -18,6 +20,7 @@ import dev.onyxstudios.cca.api.v3.entity.RespawnCopyStrategy; import dev.onyxstudios.cca.api.v3.item.ItemComponentFactoryRegistry; import dev.onyxstudios.cca.api.v3.item.ItemComponentInitializer; +import java.util.function.Function; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Mob; @@ -25,99 +28,131 @@ import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.Items; -import java.util.function.Function; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class HexCardinalComponents implements EntityComponentInitializer, ItemComponentInitializer { - // entities - public static final ComponentKey<CCBrainswept> BRAINSWEPT = ComponentRegistry.getOrCreate(modLoc("brainswept"), - CCBrainswept.class); - public static final ComponentKey<CCFavoredPigment> FAVORED_PIGMENT = ComponentRegistry.getOrCreate( - modLoc("favored_pigment"), CCFavoredPigment.class); - public static final ComponentKey<CCSentinel> SENTINEL = ComponentRegistry.getOrCreate(modLoc("sentinel"), - CCSentinel.class); - public static final ComponentKey<CCFlight> FLIGHT = ComponentRegistry.getOrCreate(modLoc("flight"), - CCFlight.class); - - public static final ComponentKey<CCAltiora> ALTIORA = ComponentRegistry.getOrCreate(modLoc("altiora"), - CCAltiora.class); - public static final ComponentKey<CCStaffcastImage> STAFFCAST_IMAGE = ComponentRegistry.getOrCreate(modLoc( - "harness"), - CCStaffcastImage.class); - public static final ComponentKey<CCPatterns> PATTERNS = ComponentRegistry.getOrCreate(modLoc("patterns"), - CCPatterns.class); - - public static final ComponentKey<CCClientCastingStack> CLIENT_CASTING_STACK = ComponentRegistry.getOrCreate(modLoc("client_casting_stack"), - CCClientCastingStack.class); - - public static final ComponentKey<CCPigment> PIGMENT = ComponentRegistry.getOrCreate(modLoc("pigment"), - CCPigment.class); - public static final ComponentKey<CCIotaHolder> IOTA_HOLDER = ComponentRegistry.getOrCreate(modLoc("iota_holder"), - CCIotaHolder.class); - public static final ComponentKey<CCMediaHolder> MEDIA_HOLDER = ComponentRegistry.getOrCreate(modLoc("media_holder"), - CCMediaHolder.class); - public static final ComponentKey<CCHexHolder> HEX_HOLDER = ComponentRegistry.getOrCreate(modLoc("hex_holder"), - CCHexHolder.class); - - public static final ComponentKey<CCVariantItem> VARIANT_ITEM = ComponentRegistry.getOrCreate(modLoc("variant_item"), - CCVariantItem.class); - - @Override - public void registerEntityComponentFactories(EntityComponentFactoryRegistry registry) { - registry.registerFor(Mob.class, BRAINSWEPT, CCBrainswept::new); - registry.registerForPlayers(FAVORED_PIGMENT, CCFavoredPigment::new, RespawnCopyStrategy.ALWAYS_COPY); - registry.registerForPlayers(SENTINEL, CCSentinel::new, RespawnCopyStrategy.ALWAYS_COPY); - registry.registerForPlayers(ALTIORA, CCAltiora::new, RespawnCopyStrategy.LOSSLESS_ONLY); - registry.registerForPlayers(CLIENT_CASTING_STACK, CCClientCastingStack::new, RespawnCopyStrategy.NEVER_COPY); - // Fortunately these are all both only needed on the server and don't want to be copied across death - registry.registerFor(ServerPlayer.class, FLIGHT, CCFlight::new); - registry.registerFor(ServerPlayer.class, STAFFCAST_IMAGE, CCStaffcastImage::new); - registry.registerFor(ServerPlayer.class, PATTERNS, CCPatterns::new); - - - registry.registerFor(ItemEntity.class, IOTA_HOLDER, wrapItemEntityDelegate( - ItemDelegatingEntityIotaHolder.ToItemEntity::new)); - registry.registerFor(ItemFrame.class, IOTA_HOLDER, wrapItemEntityDelegate( - ItemDelegatingEntityIotaHolder.ToItemFrame::new)); - registry.registerFor(EntityWallScroll.class, IOTA_HOLDER, - wrapItemEntityDelegate(ItemDelegatingEntityIotaHolder.ToWallScroll::new)); - } - - @Override - public void registerItemComponentFactories(ItemComponentFactoryRegistry registry) { - registry.register(i -> i instanceof PigmentItem, PIGMENT, CCPigment.ItemBased::new); - - registry.register(i -> i instanceof IotaHolderItem, IOTA_HOLDER, CCItemIotaHolder.ItemBased::new); - // oh havoc, you think you're so funny - // the worst part is you're /right/ - registry.register(Items.PUMPKIN_PIE, IOTA_HOLDER, stack -> new CCItemIotaHolder.Static(stack, - s -> new DoubleIota(Math.PI * s.getCount()))); - - registry.register(i -> i instanceof MediaHolderItem, MEDIA_HOLDER, CCMediaHolder.ItemBased::new); - registry.register(HexItems.AMETHYST_DUST, MEDIA_HOLDER, s -> new CCMediaHolder.Static( - () -> HexConfig.common().dustMediaAmount(), ADMediaHolder.AMETHYST_DUST_PRIORITY, s - )); - registry.register(Items.AMETHYST_SHARD, MEDIA_HOLDER, s -> new CCMediaHolder.Static( - () -> HexConfig.common().shardMediaAmount(), ADMediaHolder.AMETHYST_SHARD_PRIORITY, s - )); - registry.register(HexItems.CHARGED_AMETHYST, MEDIA_HOLDER, s -> new CCMediaHolder.Static( - () -> HexConfig.common().chargedCrystalMediaAmount(), ADMediaHolder.CHARGED_AMETHYST_PRIORITY, s - )); - registry.register(HexItems.QUENCHED_SHARD.asItem(), MEDIA_HOLDER, s -> new CCMediaHolder.Static( - () -> MediaConstants.QUENCHED_SHARD_UNIT, ADMediaHolder.QUENCHED_SHARD_PRIORITY, s - )); - registry.register(HexBlocks.QUENCHED_ALLAY.asItem(), MEDIA_HOLDER, s -> new CCMediaHolder.Static( - () -> MediaConstants.QUENCHED_BLOCK_UNIT, ADMediaHolder.QUENCHED_ALLAY_PRIORITY, s - )); - - registry.register(i -> i instanceof HexHolderItem, HEX_HOLDER, CCHexHolder.ItemBased::new); - - registry.register(i -> i instanceof VariantItem, VARIANT_ITEM, CCVariantItem.ItemBased::new); - } - - private <E extends Entity> ComponentFactory<E, CCEntityIotaHolder.Wrapper> wrapItemEntityDelegate(Function<E, - ItemDelegatingEntityIotaHolder> make) { - return e -> new CCEntityIotaHolder.Wrapper(make.apply(e)); - } + // entities + public static final ComponentKey<CCBrainswept> BRAINSWEPT = + ComponentRegistry.getOrCreate(modLoc("brainswept"), CCBrainswept.class); + public static final ComponentKey<CCFavoredPigment> FAVORED_PIGMENT = + ComponentRegistry.getOrCreate(modLoc("favored_pigment"), CCFavoredPigment.class); + public static final ComponentKey<CCSentinel> SENTINEL = + ComponentRegistry.getOrCreate(modLoc("sentinel"), CCSentinel.class); + public static final ComponentKey<CCFlight> FLIGHT = + ComponentRegistry.getOrCreate(modLoc("flight"), CCFlight.class); + + public static final ComponentKey<CCAltiora> ALTIORA = + ComponentRegistry.getOrCreate(modLoc("altiora"), CCAltiora.class); + public static final ComponentKey<CCStaffcastImage> STAFFCAST_IMAGE = + ComponentRegistry.getOrCreate(modLoc("harness"), CCStaffcastImage.class); + public static final ComponentKey<CCPatterns> PATTERNS = + ComponentRegistry.getOrCreate(modLoc("patterns"), CCPatterns.class); + + public static final ComponentKey<CCClientCastingStack> CLIENT_CASTING_STACK = + ComponentRegistry.getOrCreate(modLoc("client_casting_stack"), CCClientCastingStack.class); + + public static final ComponentKey<CCPigment> PIGMENT = + ComponentRegistry.getOrCreate(modLoc("pigment"), CCPigment.class); + public static final ComponentKey<CCIotaHolder> IOTA_HOLDER = + ComponentRegistry.getOrCreate(modLoc("iota_holder"), CCIotaHolder.class); + public static final ComponentKey<CCMediaHolder> MEDIA_HOLDER = + ComponentRegistry.getOrCreate(modLoc("media_holder"), CCMediaHolder.class); + public static final ComponentKey<CCHexHolder> HEX_HOLDER = + ComponentRegistry.getOrCreate(modLoc("hex_holder"), CCHexHolder.class); + + public static final ComponentKey<CCVariantItem> VARIANT_ITEM = + ComponentRegistry.getOrCreate(modLoc("variant_item"), CCVariantItem.class); + + @Override + public void registerEntityComponentFactories(EntityComponentFactoryRegistry registry) { + registry.registerFor(Mob.class, BRAINSWEPT, CCBrainswept::new); + registry.registerForPlayers( + FAVORED_PIGMENT, CCFavoredPigment::new, RespawnCopyStrategy.ALWAYS_COPY); + registry.registerForPlayers(SENTINEL, CCSentinel::new, RespawnCopyStrategy.ALWAYS_COPY); + registry.registerForPlayers(ALTIORA, CCAltiora::new, RespawnCopyStrategy.LOSSLESS_ONLY); + registry.registerForPlayers( + CLIENT_CASTING_STACK, CCClientCastingStack::new, RespawnCopyStrategy.NEVER_COPY); + // Fortunately these are all both only needed on the server and don't want to be copied across + // death + registry.registerFor(ServerPlayer.class, FLIGHT, CCFlight::new); + registry.registerFor(ServerPlayer.class, STAFFCAST_IMAGE, CCStaffcastImage::new); + registry.registerFor(ServerPlayer.class, PATTERNS, CCPatterns::new); + + registry.registerFor( + ItemEntity.class, + IOTA_HOLDER, + wrapItemEntityDelegate(ItemDelegatingEntityIotaHolder.ToItemEntity::new)); + registry.registerFor( + ItemFrame.class, + IOTA_HOLDER, + wrapItemEntityDelegate(ItemDelegatingEntityIotaHolder.ToItemFrame::new)); + registry.registerFor( + EntityWallScroll.class, + IOTA_HOLDER, + wrapItemEntityDelegate(ItemDelegatingEntityIotaHolder.ToWallScroll::new)); + } + + @Override + public void registerItemComponentFactories(ItemComponentFactoryRegistry registry) { + registry.register(i -> i instanceof PigmentItem, PIGMENT, CCPigment.ItemBased::new); + + registry.register( + i -> i instanceof IotaHolderItem, IOTA_HOLDER, CCItemIotaHolder.ItemBased::new); + // oh havoc, you think you're so funny + // the worst part is you're /right/ + registry.register( + Items.PUMPKIN_PIE, + IOTA_HOLDER, + stack -> new CCItemIotaHolder.Static(stack, s -> new DoubleIota(Math.PI * s.getCount()))); + + registry.register( + i -> i instanceof MediaHolderItem, MEDIA_HOLDER, CCMediaHolder.ItemBased::new); + registry.register( + HexItems.AMETHYST_DUST, + MEDIA_HOLDER, + s -> + new CCMediaHolder.Static( + () -> HexConfig.common().dustMediaAmount(), + ADMediaHolder.AMETHYST_DUST_PRIORITY, + s)); + registry.register( + Items.AMETHYST_SHARD, + MEDIA_HOLDER, + s -> + new CCMediaHolder.Static( + () -> HexConfig.common().shardMediaAmount(), + ADMediaHolder.AMETHYST_SHARD_PRIORITY, + s)); + registry.register( + HexItems.CHARGED_AMETHYST, + MEDIA_HOLDER, + s -> + new CCMediaHolder.Static( + () -> HexConfig.common().chargedCrystalMediaAmount(), + ADMediaHolder.CHARGED_AMETHYST_PRIORITY, + s)); + registry.register( + HexItems.QUENCHED_SHARD.asItem(), + MEDIA_HOLDER, + s -> + new CCMediaHolder.Static( + () -> MediaConstants.QUENCHED_SHARD_UNIT, + ADMediaHolder.QUENCHED_SHARD_PRIORITY, + s)); + registry.register( + HexBlocks.QUENCHED_ALLAY.asItem(), + MEDIA_HOLDER, + s -> + new CCMediaHolder.Static( + () -> MediaConstants.QUENCHED_BLOCK_UNIT, + ADMediaHolder.QUENCHED_ALLAY_PRIORITY, + s)); + + registry.register(i -> i instanceof HexHolderItem, HEX_HOLDER, CCHexHolder.ItemBased::new); + + registry.register(i -> i instanceof VariantItem, VARIANT_ITEM, CCVariantItem.ItemBased::new); + } + + private <E extends Entity> ComponentFactory<E, CCEntityIotaHolder.Wrapper> wrapItemEntityDelegate( + Function<E, ItemDelegatingEntityIotaHolder> make) { + return e -> new CCEntityIotaHolder.Wrapper(make.apply(e)); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCEntityIotaHolder.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCEntityIotaHolder.java index 81998b9e69..44b81a8165 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCEntityIotaHolder.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCEntityIotaHolder.java @@ -8,47 +8,46 @@ import org.jetbrains.annotations.Nullable; public abstract class CCEntityIotaHolder implements CCIotaHolder { - @Override - public void writeToNbt(@NotNull CompoundTag tag) { - // NO-OP - } - - @Override - public void readFromNbt(@NotNull CompoundTag tag) { - // NO-OP - } - - public static class Wrapper extends CCEntityIotaHolder { - private final ItemDelegatingEntityIotaHolder inner; - - public Wrapper(ItemDelegatingEntityIotaHolder inner) { - this.inner = inner; - } - - - @Override - public @Nullable CompoundTag readIotaTag() { - return inner.readIotaTag(); - } - - @Override - public boolean writeable() { - return inner.writeable(); - } - - @Override - public boolean writeIota(@Nullable Iota iota, boolean simulate) { - return inner.writeIota(iota, simulate); - } - - @Override - public @Nullable Iota readIota(ServerLevel world) { - return inner.readIota(world); - } - - @Override - public @Nullable Iota emptyIota() { - return inner.emptyIota(); - } - } + @Override + public void writeToNbt(@NotNull CompoundTag tag) { + // NO-OP + } + + @Override + public void readFromNbt(@NotNull CompoundTag tag) { + // NO-OP + } + + public static class Wrapper extends CCEntityIotaHolder { + private final ItemDelegatingEntityIotaHolder inner; + + public Wrapper(ItemDelegatingEntityIotaHolder inner) { + this.inner = inner; + } + + @Override + public @Nullable CompoundTag readIotaTag() { + return inner.readIotaTag(); + } + + @Override + public boolean writeable() { + return inner.writeable(); + } + + @Override + public boolean writeIota(@Nullable Iota iota, boolean simulate) { + return inner.writeIota(iota, simulate); + } + + @Override + public @Nullable Iota readIota(ServerLevel world) { + return inner.readIota(world); + } + + @Override + public @Nullable Iota emptyIota() { + return inner.emptyIota(); + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCHexHolder.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCHexHolder.java index 3da4e8dade..2fb2f60d73 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCHexHolder.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCHexHolder.java @@ -1,63 +1,61 @@ package at.petrak.hexcasting.fabric.cc.adimpl; import at.petrak.hexcasting.api.addldata.ADHexHolder; -import at.petrak.hexcasting.api.item.HexHolderItem; import at.petrak.hexcasting.api.casting.iota.Iota; +import at.petrak.hexcasting.api.item.HexHolderItem; import at.petrak.hexcasting.api.pigment.FrozenPigment; import at.petrak.hexcasting.fabric.cc.HexCardinalComponents; import dev.onyxstudios.cca.api.v3.item.ItemComponent; +import java.util.List; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Nullable; -import java.util.List; - public abstract class CCHexHolder extends ItemComponent implements ADHexHolder { - public CCHexHolder(ItemStack stack) { - super(stack, HexCardinalComponents.HEX_HOLDER); - } - - public static class ItemBased extends CCHexHolder { - private final HexHolderItem hexHolder; - - public ItemBased(ItemStack owner) { - super(owner); - var item = owner.getItem(); - if (!(item instanceof HexHolderItem hexHolderItem)) { - throw new IllegalStateException("item is not a pigment: " + owner); - } - this.hexHolder = hexHolderItem; - } - - - @Override - public boolean canDrawMediaFromInventory() { - return this.hexHolder.canDrawMediaFromInventory(this.stack); - } - - @Override - public boolean hasHex() { - return this.hexHolder.hasHex(this.stack); - } - - @Override - public @Nullable List<Iota> getHex(ServerLevel level) { - return this.hexHolder.getHex(this.stack, level); - } - - @Override - public void writeHex(List<Iota> patterns, @Nullable FrozenPigment pigment, long media) { - this.hexHolder.writeHex(this.stack, patterns, pigment, media); - } - - @Override - public void clearHex() { - this.hexHolder.clearHex(this.stack); - } - - @Override - public @Nullable FrozenPigment getPigment() { - return this.hexHolder.getPigment(this.stack); - } - } + public CCHexHolder(ItemStack stack) { + super(stack, HexCardinalComponents.HEX_HOLDER); + } + + public static class ItemBased extends CCHexHolder { + private final HexHolderItem hexHolder; + + public ItemBased(ItemStack owner) { + super(owner); + var item = owner.getItem(); + if (!(item instanceof HexHolderItem hexHolderItem)) { + throw new IllegalStateException("item is not a pigment: " + owner); + } + this.hexHolder = hexHolderItem; + } + + @Override + public boolean canDrawMediaFromInventory() { + return this.hexHolder.canDrawMediaFromInventory(this.stack); + } + + @Override + public boolean hasHex() { + return this.hexHolder.hasHex(this.stack); + } + + @Override + public @Nullable List<Iota> getHex(ServerLevel level) { + return this.hexHolder.getHex(this.stack, level); + } + + @Override + public void writeHex(List<Iota> patterns, @Nullable FrozenPigment pigment, long media) { + this.hexHolder.writeHex(this.stack, patterns, pigment, media); + } + + @Override + public void clearHex() { + this.hexHolder.clearHex(this.stack); + } + + @Override + public @Nullable FrozenPigment getPigment() { + return this.hexHolder.getPigment(this.stack); + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCIotaHolder.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCIotaHolder.java index 19e522a9ad..8eae7ec9fc 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCIotaHolder.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCIotaHolder.java @@ -3,5 +3,4 @@ import at.petrak.hexcasting.api.addldata.ADIotaHolder; import dev.onyxstudios.cca.api.v3.component.Component; -public interface CCIotaHolder extends ADIotaHolder, Component { -} +public interface CCIotaHolder extends ADIotaHolder, Component {} diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCItemIotaHolder.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCItemIotaHolder.java index 10e9566594..db4cec792e 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCItemIotaHolder.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCItemIotaHolder.java @@ -5,73 +5,72 @@ import at.petrak.hexcasting.api.item.IotaHolderItem; import at.petrak.hexcasting.fabric.cc.HexCardinalComponents; import dev.onyxstudios.cca.api.v3.item.ItemComponent; +import java.util.function.Function; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Nullable; -import java.util.function.Function; - public abstract class CCItemIotaHolder extends ItemComponent implements CCIotaHolder { - public CCItemIotaHolder(ItemStack stack) { - super(stack, HexCardinalComponents.IOTA_HOLDER); - } + public CCItemIotaHolder(ItemStack stack) { + super(stack, HexCardinalComponents.IOTA_HOLDER); + } - public static class ItemBased extends CCItemIotaHolder { - private final IotaHolderItem iotaHolder; + public static class ItemBased extends CCItemIotaHolder { + private final IotaHolderItem iotaHolder; - public ItemBased(ItemStack stack) { - super(stack); - if (!(stack.getItem() instanceof IotaHolderItem data)) { - throw new IllegalStateException("item is not a data holder: " + stack); - } - this.iotaHolder = data; - } + public ItemBased(ItemStack stack) { + super(stack); + if (!(stack.getItem() instanceof IotaHolderItem data)) { + throw new IllegalStateException("item is not a data holder: " + stack); + } + this.iotaHolder = data; + } - @Override - public @Nullable CompoundTag readIotaTag() { - return this.iotaHolder.readIotaTag(this.stack); - } + @Override + public @Nullable CompoundTag readIotaTag() { + return this.iotaHolder.readIotaTag(this.stack); + } - @Override - public boolean writeable() { - return this.iotaHolder.writeable(this.stack); - } + @Override + public boolean writeable() { + return this.iotaHolder.writeable(this.stack); + } - @Override - public boolean writeIota(@Nullable Iota iota, boolean simulate) { - var canWrite = this.iotaHolder.canWrite(this.stack, iota); - if (!canWrite) { - return false; - } - if (!simulate) { - this.iotaHolder.writeDatum(this.stack, iota); - } - return true; - } - } + @Override + public boolean writeIota(@Nullable Iota iota, boolean simulate) { + var canWrite = this.iotaHolder.canWrite(this.stack, iota); + if (!canWrite) { + return false; + } + if (!simulate) { + this.iotaHolder.writeDatum(this.stack, iota); + } + return true; + } + } - public static class Static extends CCItemIotaHolder { - private final Function<ItemStack, Iota> provider; + public static class Static extends CCItemIotaHolder { + private final Function<ItemStack, Iota> provider; - public Static(ItemStack stack, Function<ItemStack, Iota> provider) { - super(stack); - this.provider = provider; - } + public Static(ItemStack stack, Function<ItemStack, Iota> provider) { + super(stack); + this.provider = provider; + } - @Override - public @Nullable CompoundTag readIotaTag() { - var iota = this.provider.apply(this.stack); - return iota == null ? null : IotaType.serialize(iota); - } + @Override + public @Nullable CompoundTag readIotaTag() { + var iota = this.provider.apply(this.stack); + return iota == null ? null : IotaType.serialize(iota); + } - @Override - public boolean writeable() { - return false; - } + @Override + public boolean writeable() { + return false; + } - @Override - public boolean writeIota(@Nullable Iota datum, boolean simulate) { - return false; - } - } + @Override + public boolean writeIota(@Nullable Iota datum, boolean simulate) { + return false; + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCMediaHolder.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCMediaHolder.java index b4ff6ed091..0d319b20ff 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCMediaHolder.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCMediaHolder.java @@ -4,129 +4,128 @@ import at.petrak.hexcasting.api.item.MediaHolderItem; import at.petrak.hexcasting.fabric.cc.HexCardinalComponents; import dev.onyxstudios.cca.api.v3.item.ItemComponent; -import net.minecraft.world.item.ItemStack; - import java.util.function.Supplier; +import net.minecraft.world.item.ItemStack; public abstract class CCMediaHolder extends ItemComponent implements ADMediaHolder { - public CCMediaHolder(ItemStack stack) { - super(stack, HexCardinalComponents.MEDIA_HOLDER); - } - - public static class ItemBased extends CCMediaHolder { - private final MediaHolderItem mediaHolder; - - public ItemBased(ItemStack stack) { - super(stack); - if (!(stack.getItem() instanceof MediaHolderItem media)) { - throw new IllegalStateException("item is not a media holder: " + stack); - } - this.mediaHolder = media; - } - - @Override - public long getMedia() { - return this.mediaHolder.getMedia(this.stack); - } - - @Override - public long getMaxMedia() { - return this.mediaHolder.getMaxMedia(this.stack); - } - - @Override - public void setMedia(long media) { - this.mediaHolder.setMedia(this.stack, media); - } - - @Override - public boolean canRecharge() { - return this.mediaHolder.canRecharge(this.stack); - } - - @Override - public boolean canProvide() { - return this.mediaHolder.canProvideMedia(this.stack); - } - - @Override - public int getConsumptionPriority() { - return this.mediaHolder.getConsumptionPriority(this.stack); - } - - @Override - public boolean canConstructBattery() { - return false; - } - - @Override - public long withdrawMedia(long cost, boolean simulate) { - return this.mediaHolder.withdrawMedia(this.stack, cost, simulate); - } - - @Override - public long insertMedia(long amount, boolean simulate) { - return this.mediaHolder.insertMedia(this.stack, amount, simulate); - } - } - - public static class Static extends CCMediaHolder { - private final Supplier<Long> baseWorth; - private final int consumptionPriority; - - public Static(Supplier<Long> baseWorth, int consumptionPriority, ItemStack stack) { - super(stack); - this.baseWorth = baseWorth; - this.consumptionPriority = consumptionPriority; - } - - @Override - public long getMedia() { - return baseWorth.get() * stack.getCount(); - } - - @Override - public long getMaxMedia() { - return getMedia(); - } - - @Override - public void setMedia(long media) { - // NO-OP - } - - @Override - public boolean canRecharge() { - return false; - } - - @Override - public boolean canProvide() { - return true; - } - - @Override - public int getConsumptionPriority() { - return consumptionPriority; - } - - @Override - public boolean canConstructBattery() { - return true; - } - - @Override - public long withdrawMedia(long cost, boolean simulate) { - long worth = baseWorth.get(); - if (cost < 0) { - cost = worth * stack.getCount(); - } - double itemsRequired = cost / (double) worth; - int itemsUsed = Math.min((int) Math.ceil(itemsRequired), stack.getCount()); - if (!simulate) { - stack.shrink(itemsUsed); - } - return itemsUsed * worth; - } - } + public CCMediaHolder(ItemStack stack) { + super(stack, HexCardinalComponents.MEDIA_HOLDER); + } + + public static class ItemBased extends CCMediaHolder { + private final MediaHolderItem mediaHolder; + + public ItemBased(ItemStack stack) { + super(stack); + if (!(stack.getItem() instanceof MediaHolderItem media)) { + throw new IllegalStateException("item is not a media holder: " + stack); + } + this.mediaHolder = media; + } + + @Override + public long getMedia() { + return this.mediaHolder.getMedia(this.stack); + } + + @Override + public long getMaxMedia() { + return this.mediaHolder.getMaxMedia(this.stack); + } + + @Override + public void setMedia(long media) { + this.mediaHolder.setMedia(this.stack, media); + } + + @Override + public boolean canRecharge() { + return this.mediaHolder.canRecharge(this.stack); + } + + @Override + public boolean canProvide() { + return this.mediaHolder.canProvideMedia(this.stack); + } + + @Override + public int getConsumptionPriority() { + return this.mediaHolder.getConsumptionPriority(this.stack); + } + + @Override + public boolean canConstructBattery() { + return false; + } + + @Override + public long withdrawMedia(long cost, boolean simulate) { + return this.mediaHolder.withdrawMedia(this.stack, cost, simulate); + } + + @Override + public long insertMedia(long amount, boolean simulate) { + return this.mediaHolder.insertMedia(this.stack, amount, simulate); + } + } + + public static class Static extends CCMediaHolder { + private final Supplier<Long> baseWorth; + private final int consumptionPriority; + + public Static(Supplier<Long> baseWorth, int consumptionPriority, ItemStack stack) { + super(stack); + this.baseWorth = baseWorth; + this.consumptionPriority = consumptionPriority; + } + + @Override + public long getMedia() { + return baseWorth.get() * stack.getCount(); + } + + @Override + public long getMaxMedia() { + return getMedia(); + } + + @Override + public void setMedia(long media) { + // NO-OP + } + + @Override + public boolean canRecharge() { + return false; + } + + @Override + public boolean canProvide() { + return true; + } + + @Override + public int getConsumptionPriority() { + return consumptionPriority; + } + + @Override + public boolean canConstructBattery() { + return true; + } + + @Override + public long withdrawMedia(long cost, boolean simulate) { + long worth = baseWorth.get(); + if (cost < 0) { + cost = worth * stack.getCount(); + } + double itemsRequired = cost / (double) worth; + int itemsUsed = Math.min((int) Math.ceil(itemsRequired), stack.getCount()); + if (!simulate) { + stack.shrink(itemsUsed); + } + return itemsUsed * worth; + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCPigment.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCPigment.java index 3247810fb2..323c7b7c04 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCPigment.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCPigment.java @@ -5,33 +5,30 @@ import at.petrak.hexcasting.api.pigment.ColorProvider; import at.petrak.hexcasting.fabric.cc.HexCardinalComponents; import dev.onyxstudios.cca.api.v3.item.ItemComponent; -import net.minecraft.world.item.ItemStack; - import java.util.UUID; +import net.minecraft.world.item.ItemStack; -/** - * The pigment itself - */ +/** The pigment itself */ public abstract class CCPigment extends ItemComponent implements ADPigment { - public CCPigment(ItemStack stack) { - super(stack, HexCardinalComponents.PIGMENT); - } + public CCPigment(ItemStack stack) { + super(stack, HexCardinalComponents.PIGMENT); + } - public static class ItemBased extends CCPigment { - private final PigmentItem item; + public static class ItemBased extends CCPigment { + private final PigmentItem item; - public ItemBased(ItemStack owner) { - super(owner); - var item = owner.getItem(); - if (!(item instanceof PigmentItem col)) { - throw new IllegalStateException("item is not a pigment: " + owner); - } - this.item = col; - } + public ItemBased(ItemStack owner) { + super(owner); + var item = owner.getItem(); + if (!(item instanceof PigmentItem col)) { + throw new IllegalStateException("item is not a pigment: " + owner); + } + this.item = col; + } - @Override - public ColorProvider provideColor(UUID owner) { - return item.provideColor(this.stack, owner); - } - } + @Override + public ColorProvider provideColor(UUID owner) { + return item.provideColor(this.stack, owner); + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCVariantItem.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCVariantItem.java index 281dfb8014..90a5e03f6c 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCVariantItem.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCVariantItem.java @@ -7,35 +7,35 @@ import net.minecraft.world.item.ItemStack; public abstract class CCVariantItem extends ItemComponent implements ADVariantItem { - public CCVariantItem(ItemStack stack) { - super(stack, HexCardinalComponents.VARIANT_ITEM); - } + public CCVariantItem(ItemStack stack) { + super(stack, HexCardinalComponents.VARIANT_ITEM); + } - public static class ItemBased extends CCVariantItem { - private final VariantItem variantItem; + public static class ItemBased extends CCVariantItem { + private final VariantItem variantItem; - public ItemBased(ItemStack owner) { - super(owner); - var item = owner.getItem(); - if (!(item instanceof VariantItem variantItem)) { - throw new IllegalStateException("item is not a colorizer: " + owner); - } - this.variantItem = variantItem; - } + public ItemBased(ItemStack owner) { + super(owner); + var item = owner.getItem(); + if (!(item instanceof VariantItem variantItem)) { + throw new IllegalStateException("item is not a colorizer: " + owner); + } + this.variantItem = variantItem; + } - @Override - public int numVariants() { - return variantItem.numVariants(); - } + @Override + public int numVariants() { + return variantItem.numVariants(); + } - @Override - public int getVariant() { - return variantItem.getVariant(this.stack); - } + @Override + public int getVariant() { + return variantItem.getVariant(this.stack); + } - @Override - public void setVariant(int variant) { - variantItem.setVariant(this.stack, variant); - } - } + @Override + public void setVariant(int variant) { + variantItem.setVariant(this.stack, variant); + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/package-info.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/package-info.java index c1f2319c16..944c5b060a 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/package-info.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/package-info.java @@ -1,8 +1,8 @@ /** - * Some Cardinal Components in the mod are substitutes for Forge's ability to store arbitrary data on an entity; - * some are implementations of the Additional Data abstraction. - * <p> - * In the root of this folder are the substitutes for entitydata; - * in the {@link at.petrak.hexcasting.fabric.cc.adimpl adimpl} folder are the implementations of additional datas. + * Some Cardinal Components in the mod are substitutes for Forge's ability to store arbitrary data + * on an entity; some are implementations of the Additional Data abstraction. + * + * <p>In the root of this folder are the substitutes for entitydata; in the {@link + * at.petrak.hexcasting.fabric.cc.adimpl adimpl} folder are the implementations of additional datas. */ -package at.petrak.hexcasting.fabric.cc; \ No newline at end of file +package at.petrak.hexcasting.fabric.cc; diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/client/ExtendedTexture.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/client/ExtendedTexture.java index f7b18a7eed..6b5ba85f35 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/client/ExtendedTexture.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/client/ExtendedTexture.java @@ -2,7 +2,7 @@ // https://github.com/VazkiiMods/Botania/blob/db85d778ab23f44c11181209319066d1f04a9e3d/Fabric/src/main/java/vazkii/botania/fabric/client/ExtendedTexture.java public interface ExtendedTexture { - void setFilterSave(boolean bilinear, boolean mipmap); + void setFilterSave(boolean bilinear, boolean mipmap); - void restoreLastFilter(); + void restoreLastFilter(); } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/datagen/HexFabricConditionsBuilder.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/datagen/HexFabricConditionsBuilder.java index eb4f16aa78..83c5eded0e 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/datagen/HexFabricConditionsBuilder.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/datagen/HexFabricConditionsBuilder.java @@ -2,6 +2,9 @@ import at.petrak.hexcasting.datagen.IXplatConditionsBuilder; import com.google.gson.JsonObject; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; import net.fabricmc.fabric.api.resource.conditions.v1.ConditionJsonProvider; import net.fabricmc.fabric.api.resource.conditions.v1.DefaultResourceConditions; import net.fabricmc.fabric.impl.datagen.FabricDataGenHelper; @@ -14,83 +17,81 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - public class HexFabricConditionsBuilder implements IXplatConditionsBuilder { - private final List<ConditionJsonProvider> conditions = new ArrayList<>(); - private final RecipeBuilder parent; - - public HexFabricConditionsBuilder(RecipeBuilder parent) { - this.parent = parent; - } - - @Override - public IXplatConditionsBuilder whenModLoaded(String modid) { - conditions.add(DefaultResourceConditions.allModsLoaded(modid)); - return this; - } - - @Override - public IXplatConditionsBuilder whenModMissing(String modid) { - conditions.add(DefaultResourceConditions.not(DefaultResourceConditions.allModsLoaded(modid))); - return this; - } - - @Override - public RecipeBuilder unlockedBy(@NotNull String string, @NotNull CriterionTriggerInstance criterionTriggerInstance) { - return parent.unlockedBy(string, criterionTriggerInstance); - } - - @Override - public RecipeBuilder group(@Nullable String string) { - return parent.group(string); - } - - @Override - public Item getResult() { - return parent.getResult(); - } - - @Override - @SuppressWarnings("UnstableApiUsage") - public void save(@NotNull Consumer<FinishedRecipe> consumer, @NotNull ResourceLocation resourceLocation) { - Consumer<FinishedRecipe> withConditions = json -> { - FabricDataGenHelper.addConditions(json, conditions.toArray(new ConditionJsonProvider[0])); - - consumer.accept(new FinishedRecipe() { - @Override - public void serializeRecipeData(@NotNull JsonObject jsonObject) { - json.serializeRecipeData(jsonObject); - ConditionJsonProvider[] conditions = FabricDataGenHelper.consumeConditions(json); - ConditionJsonProvider.write(jsonObject, conditions); - } - - @Override - public ResourceLocation getId() { - return json.getId(); - } - - @Override - public RecipeSerializer<?> getType() { - return json.getType(); - } - - @Nullable - @Override - public JsonObject serializeAdvancement() { - return json.serializeAdvancement(); - } - - @Nullable - @Override - public ResourceLocation getAdvancementId() { - return json.getAdvancementId(); - } - }); - }; - - parent.save(withConditions, resourceLocation); - } + private final List<ConditionJsonProvider> conditions = new ArrayList<>(); + private final RecipeBuilder parent; + + public HexFabricConditionsBuilder(RecipeBuilder parent) { + this.parent = parent; + } + + @Override + public IXplatConditionsBuilder whenModLoaded(String modid) { + conditions.add(DefaultResourceConditions.allModsLoaded(modid)); + return this; + } + + @Override + public IXplatConditionsBuilder whenModMissing(String modid) { + conditions.add(DefaultResourceConditions.not(DefaultResourceConditions.allModsLoaded(modid))); + return this; + } + + @Override + public RecipeBuilder unlockedBy( + @NotNull String string, @NotNull CriterionTriggerInstance criterionTriggerInstance) { + return parent.unlockedBy(string, criterionTriggerInstance); + } + + @Override + public RecipeBuilder group(@Nullable String string) { + return parent.group(string); + } + + @Override + public Item getResult() { + return parent.getResult(); + } + + @Override + @SuppressWarnings("UnstableApiUsage") + public void save( + @NotNull Consumer<FinishedRecipe> consumer, @NotNull ResourceLocation resourceLocation) { + Consumer<FinishedRecipe> withConditions = + json -> { + FabricDataGenHelper.addConditions(json, conditions.toArray(new ConditionJsonProvider[0])); + + consumer.accept( + new FinishedRecipe() { + @Override + public void serializeRecipeData(@NotNull JsonObject jsonObject) { + json.serializeRecipeData(jsonObject); + ConditionJsonProvider[] conditions = FabricDataGenHelper.consumeConditions(json); + ConditionJsonProvider.write(jsonObject, conditions); + } + + @Override + public ResourceLocation getId() { + return json.getId(); + } + + @Override + public RecipeSerializer<?> getType() { + return json.getType(); + } + + @Nullable @Override + public JsonObject serializeAdvancement() { + return json.serializeAdvancement(); + } + + @Nullable @Override + public ResourceLocation getAdvancementId() { + return json.getAdvancementId(); + } + }); + }; + + parent.save(withConditions, resourceLocation); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/datagen/HexFabricDataGenerators.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/datagen/HexFabricDataGenerators.java index 6bf539423a..f3c8abbde1 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/datagen/HexFabricDataGenerators.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/datagen/HexFabricDataGenerators.java @@ -11,6 +11,10 @@ import at.petrak.hexcasting.fabric.recipe.FabricModConditionalIngredient; import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.google.gson.JsonObject; +import java.util.EnumMap; +import java.util.List; +import java.util.Set; +import java.util.stream.Stream; import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint; import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator; import net.minecraft.core.registries.Registries; @@ -21,147 +25,160 @@ import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; -import java.util.EnumMap; -import java.util.List; -import java.util.Set; -import java.util.stream.Stream; - public class HexFabricDataGenerators implements DataGeneratorEntrypoint { - @Override - public void onInitializeDataGenerator(FabricDataGenerator gen) { - HexAPI.LOGGER.info("Starting Fabric-specific datagen"); - - var pack = gen.createPack(); - var xtags = IXplatAbstractions.INSTANCE.tags(); - - pack.addProvider((FabricDataGenerator.Pack.Factory<HexplatRecipes>) x -> new HexplatRecipes(x, INGREDIENTS, HexFabricConditionsBuilder::new)); - - var btagProviderWrapper = new BlockTagProviderWrapper(); // CURSED - pack.addProvider((output, lookup) -> { - btagProviderWrapper.provider = new HexBlockTagProvider(output, lookup, xtags); - return btagProviderWrapper.provider; - }); - pack.addProvider((output, lookup) -> new HexItemTagProvider(output, lookup, btagProviderWrapper.provider, xtags)); - - pack.addProvider(HexActionTagProvider::new); - - pack.addProvider((FabricDataGenerator.Pack.Factory<LootTableProvider>) (output) -> new LootTableProvider( - output, Set.of(), List.of(new LootTableProvider.SubProviderEntry(HexLootTables::new, LootContextParamSets.ALL_PARAMS)) - )); - } - - private static class BlockTagProviderWrapper { - HexBlockTagProvider provider; - } - - private static final IXplatIngredients INGREDIENTS = new IXplatIngredients() { - @Override - public Ingredient glowstoneDust() { - return new Ingredient(Stream.of( - new Ingredient.ItemValue(new ItemStack(Items.GLOWSTONE_DUST)), - new Ingredient.TagValue(tag("glowstone_dusts")) - )); - } - - @Override - public Ingredient leather() { - // apparently c:leather also includes rabbit hide - return Ingredient.of(Items.LEATHER); - } - - @Override - public Ingredient ironNugget() { - return new Ingredient(Stream.of( - new Ingredient.ItemValue(new ItemStack(Items.IRON_NUGGET)), - new Ingredient.TagValue(tag("iron_nuggets")) - )); - } - - @Override - public Ingredient goldNugget() { - return new Ingredient(Stream.of( - new Ingredient.ItemValue(new ItemStack(Items.GOLD_NUGGET)), - new Ingredient.TagValue(tag("gold_nuggets")) - )); - } - - @Override - public Ingredient copperIngot() { - return new Ingredient(Stream.of( - new Ingredient.ItemValue(new ItemStack(Items.COPPER_INGOT)), - new Ingredient.TagValue(tag("copper_ingots")) - )); - } - - @Override - public Ingredient ironIngot() { - return new Ingredient(Stream.of( - new Ingredient.ItemValue(new ItemStack(Items.IRON_INGOT)), - new Ingredient.TagValue(tag("iron_ingots")) - )); - } - - @Override - public Ingredient goldIngot() { - return new Ingredient(Stream.of( - new Ingredient.ItemValue(new ItemStack(Items.GOLD_INGOT)), - new Ingredient.TagValue(tag("gold_ingots")) - )); - } - - @Override - public EnumMap<DyeColor, Ingredient> dyes() { - var out = new EnumMap<DyeColor, Ingredient>(DyeColor.class); - for (var col : DyeColor.values()) { - out.put(col, new Ingredient(Stream.of( - new Ingredient.ItemValue(new ItemStack(DyeItem.byColor(col))), - new Ingredient.TagValue( - TagKey.create(Registries.ITEM, - new ResourceLocation("c", col.getSerializedName() + "_dye"))), - new Ingredient.TagValue( - TagKey.create(Registries.ITEM, - new ResourceLocation("c", col.getSerializedName() + "_dyes")) - )))); - } - return out; - } - - @Override - public Ingredient stick() { - return new Ingredient(Stream.of( - new Ingredient.ItemValue(new ItemStack(Items.STICK)), - new Ingredient.TagValue(tag("wood_sticks")) - )); - } - - @Override - public Ingredient whenModIngredient(Ingredient defaultIngredient, String modid, Ingredient modIngredient) { - return FabricModConditionalIngredient.of(defaultIngredient, modid, modIngredient); - } - - private final FarmersDelightToolIngredient AXE_INGREDIENT = () -> { - JsonObject object = new JsonObject(); - object.addProperty("type", "farmersdelight:tool"); - object.addProperty("tag", "c:tools/axes"); - return object; - }; - - @Override - public FarmersDelightToolIngredient axeStrip() { - return AXE_INGREDIENT; - } - - @Override - public FarmersDelightToolIngredient axeDig() { - return AXE_INGREDIENT; - } - }; - - private static TagKey<Item> tag(String s) { - return tag("c", s); - } - - private static TagKey<Item> tag(String namespace, String s) { - return TagKey.create(Registries.ITEM, new ResourceLocation(namespace, s)); - } + @Override + public void onInitializeDataGenerator(FabricDataGenerator gen) { + HexAPI.LOGGER.info("Starting Fabric-specific datagen"); + + var pack = gen.createPack(); + var xtags = IXplatAbstractions.INSTANCE.tags(); + + pack.addProvider( + (FabricDataGenerator.Pack.Factory<HexplatRecipes>) + x -> new HexplatRecipes(x, INGREDIENTS, HexFabricConditionsBuilder::new)); + + var btagProviderWrapper = new BlockTagProviderWrapper(); // CURSED + pack.addProvider( + (output, lookup) -> { + btagProviderWrapper.provider = new HexBlockTagProvider(output, lookup, xtags); + return btagProviderWrapper.provider; + }); + pack.addProvider( + (output, lookup) -> + new HexItemTagProvider(output, lookup, btagProviderWrapper.provider, xtags)); + + pack.addProvider(HexActionTagProvider::new); + + pack.addProvider( + (FabricDataGenerator.Pack.Factory<LootTableProvider>) + (output) -> + new LootTableProvider( + output, + Set.of(), + List.of( + new LootTableProvider.SubProviderEntry( + HexLootTables::new, LootContextParamSets.ALL_PARAMS)))); + } + + private static class BlockTagProviderWrapper { + HexBlockTagProvider provider; + } + + private static final IXplatIngredients INGREDIENTS = + new IXplatIngredients() { + @Override + public Ingredient glowstoneDust() { + return new Ingredient( + Stream.of( + new Ingredient.ItemValue(new ItemStack(Items.GLOWSTONE_DUST)), + new Ingredient.TagValue(tag("glowstone_dusts")))); + } + + @Override + public Ingredient leather() { + // apparently c:leather also includes rabbit hide + return Ingredient.of(Items.LEATHER); + } + + @Override + public Ingredient ironNugget() { + return new Ingredient( + Stream.of( + new Ingredient.ItemValue(new ItemStack(Items.IRON_NUGGET)), + new Ingredient.TagValue(tag("iron_nuggets")))); + } + + @Override + public Ingredient goldNugget() { + return new Ingredient( + Stream.of( + new Ingredient.ItemValue(new ItemStack(Items.GOLD_NUGGET)), + new Ingredient.TagValue(tag("gold_nuggets")))); + } + + @Override + public Ingredient copperIngot() { + return new Ingredient( + Stream.of( + new Ingredient.ItemValue(new ItemStack(Items.COPPER_INGOT)), + new Ingredient.TagValue(tag("copper_ingots")))); + } + + @Override + public Ingredient ironIngot() { + return new Ingredient( + Stream.of( + new Ingredient.ItemValue(new ItemStack(Items.IRON_INGOT)), + new Ingredient.TagValue(tag("iron_ingots")))); + } + + @Override + public Ingredient goldIngot() { + return new Ingredient( + Stream.of( + new Ingredient.ItemValue(new ItemStack(Items.GOLD_INGOT)), + new Ingredient.TagValue(tag("gold_ingots")))); + } + + @Override + public EnumMap<DyeColor, Ingredient> dyes() { + var out = new EnumMap<DyeColor, Ingredient>(DyeColor.class); + for (var col : DyeColor.values()) { + out.put( + col, + new Ingredient( + Stream.of( + new Ingredient.ItemValue(new ItemStack(DyeItem.byColor(col))), + new Ingredient.TagValue( + TagKey.create( + Registries.ITEM, + new ResourceLocation("c", col.getSerializedName() + "_dye"))), + new Ingredient.TagValue( + TagKey.create( + Registries.ITEM, + new ResourceLocation("c", col.getSerializedName() + "_dyes")))))); + } + return out; + } + + @Override + public Ingredient stick() { + return new Ingredient( + Stream.of( + new Ingredient.ItemValue(new ItemStack(Items.STICK)), + new Ingredient.TagValue(tag("wood_sticks")))); + } + + @Override + public Ingredient whenModIngredient( + Ingredient defaultIngredient, String modid, Ingredient modIngredient) { + return FabricModConditionalIngredient.of(defaultIngredient, modid, modIngredient); + } + + private final FarmersDelightToolIngredient AXE_INGREDIENT = + () -> { + JsonObject object = new JsonObject(); + object.addProperty("type", "farmersdelight:tool"); + object.addProperty("tag", "c:tools/axes"); + return object; + }; + + @Override + public FarmersDelightToolIngredient axeStrip() { + return AXE_INGREDIENT; + } + + @Override + public FarmersDelightToolIngredient axeDig() { + return AXE_INGREDIENT; + } + }; + + private static TagKey<Item> tag(String s) { + return tag("c", s); + } + + private static TagKey<Item> tag(String namespace, String s) { + return TagKey.create(Registries.ITEM, new ResourceLocation(namespace, s)); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/event/MouseScrollCallback.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/event/MouseScrollCallback.java index 71d34820f4..2aeac94598 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/event/MouseScrollCallback.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/event/MouseScrollCallback.java @@ -3,21 +3,22 @@ import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; -/** - * Return true to cancel any further processing of the mouse scroll, false to keep going. - */ +/** Return true to cancel any further processing of the mouse scroll, false to keep going. */ @FunctionalInterface public interface MouseScrollCallback { - Event<MouseScrollCallback> EVENT = EventFactory.createArrayBacked(MouseScrollCallback.class, - listeners -> (delta) -> { - for (var cb : listeners) { - var cancel = cb.interact(delta); - if (cancel) { - return true; - } - } - return false; - }); + Event<MouseScrollCallback> EVENT = + EventFactory.createArrayBacked( + MouseScrollCallback.class, + listeners -> + (delta) -> { + for (var cb : listeners) { + var cancel = cb.interact(delta); + if (cancel) { + return true; + } + } + return false; + }); - boolean interact(double delta); + boolean interact(double delta); } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/event/VillagerConversionCallback.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/event/VillagerConversionCallback.java index 184015e29f..5eb0aaea51 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/event/VillagerConversionCallback.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/event/VillagerConversionCallback.java @@ -7,17 +7,20 @@ // https://fabricmc.net/wiki/tutorial:events /** - * Callback for when a LivingEntity turns into another entity, like a villager being struck by lightning. - * This event is fired after the conversion happens and cannot be cancelled. + * Callback for when a LivingEntity turns into another entity, like a villager being struck by + * lightning. This event is fired after the conversion happens and cannot be cancelled. */ @FunctionalInterface public interface VillagerConversionCallback { - Event<VillagerConversionCallback> EVENT = EventFactory.createArrayBacked(VillagerConversionCallback.class, - listeners -> (original, outcome) -> { - for (var cb : listeners) { - cb.interact(original, outcome); - } - }); + Event<VillagerConversionCallback> EVENT = + EventFactory.createArrayBacked( + VillagerConversionCallback.class, + listeners -> + (original, outcome) -> { + for (var cb : listeners) { + cb.interact(original, outcome); + } + }); - void interact(LivingEntity original, LivingEntity outcome); + void interact(LivingEntity original, LivingEntity outcome); } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/ModMenuInterop.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/ModMenuInterop.java index 39b6586da7..0c44d61fa4 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/ModMenuInterop.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/ModMenuInterop.java @@ -9,8 +9,8 @@ @Environment(EnvType.CLIENT) public class ModMenuInterop implements ModMenuApi { - @Override - public ConfigScreenFactory<?> getModConfigScreenFactory() { - return parent -> AutoConfig.getConfigScreen(FabricHexConfig.class, parent).get(); - } + @Override + public ConfigScreenFactory<?> getModConfigScreenFactory() { + return parent -> AutoConfig.getConfigScreen(FabricHexConfig.class, parent).get(); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/BrainsweepeeEmiStack.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/BrainsweepeeEmiStack.java index 4fd6772fa9..405cc12196 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/BrainsweepeeEmiStack.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/BrainsweepeeEmiStack.java @@ -1,10 +1,14 @@ package at.petrak.hexcasting.fabric.interop.emi; +import static at.petrak.hexcasting.api.HexAPI.modLoc; +import static at.petrak.hexcasting.client.render.RenderLib.renderEntity; + import at.petrak.hexcasting.client.ClientTickCounter; import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.BrainsweepeeIngredient; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; import dev.emi.emi.api.stack.EmiStack; +import java.util.List; +import java.util.stream.Collectors; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; @@ -13,85 +17,80 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; -import java.util.List; -import java.util.stream.Collectors; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; -import static at.petrak.hexcasting.client.render.RenderLib.renderEntity; - public class BrainsweepeeEmiStack extends EmiStack { - public final BrainsweepeeIngredient ingredient; - private final ResourceLocation id; - - public BrainsweepeeEmiStack(BrainsweepeeIngredient ingr) { - this.ingredient = ingr; - - var bareId = this.ingredient.getSomeKindOfReasonableIDForEmi(); - this.id = modLoc(bareId); - } - - @Override - public EmiStack copy() { - return new BrainsweepeeEmiStack(this.ingredient); - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public CompoundTag getNbt() { - return null; - } - - @Override - public Object getKey() { - return id; - } - - @Override - public ResourceLocation getId() { - return id; - } - - @Override - public List<Component> getTooltipText() { - Minecraft mc = Minecraft.getInstance(); - boolean advanced = mc.options.advancedItemTooltips; - - return ingredient.getTooltip(advanced); - } - - @Override - public List<ClientTooltipComponent> getTooltip() { - return getTooltipText().stream() - .map(Component::getVisualOrderText) - .map(ClientTooltipComponent::create) - .collect(Collectors.toList()); - } - - @Override - public Component getName() { - return ingredient.getName(); - } - - @Override - public void render(GuiGraphics graphics, int x, int y, float delta, int flags) { - if ((flags & RENDER_ICON) != 0) { - Minecraft mc = Minecraft.getInstance(); - ClientLevel level = mc.level; - if (level != null) { - var example = this.ingredient.exampleEntity(level); - - RenderSystem.enableBlend(); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - renderEntity(graphics, example, level, x + 8, y + 16, ClientTickCounter.getTotal(), 8, 0, it -> it); - } - } - -// if ((flags & RENDER_REMAINDER) != 0) { -// EmiRender.renderRemainderIcon(this, poseStack, x, y); -// } - } + public final BrainsweepeeIngredient ingredient; + private final ResourceLocation id; + + public BrainsweepeeEmiStack(BrainsweepeeIngredient ingr) { + this.ingredient = ingr; + + var bareId = this.ingredient.getSomeKindOfReasonableIDForEmi(); + this.id = modLoc(bareId); + } + + @Override + public EmiStack copy() { + return new BrainsweepeeEmiStack(this.ingredient); + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public CompoundTag getNbt() { + return null; + } + + @Override + public Object getKey() { + return id; + } + + @Override + public ResourceLocation getId() { + return id; + } + + @Override + public List<Component> getTooltipText() { + Minecraft mc = Minecraft.getInstance(); + boolean advanced = mc.options.advancedItemTooltips; + + return ingredient.getTooltip(advanced); + } + + @Override + public List<ClientTooltipComponent> getTooltip() { + return getTooltipText().stream() + .map(Component::getVisualOrderText) + .map(ClientTooltipComponent::create) + .collect(Collectors.toList()); + } + + @Override + public Component getName() { + return ingredient.getName(); + } + + @Override + public void render(GuiGraphics graphics, int x, int y, float delta, int flags) { + if ((flags & RENDER_ICON) != 0) { + Minecraft mc = Minecraft.getInstance(); + ClientLevel level = mc.level; + if (level != null) { + var example = this.ingredient.exampleEntity(level); + + RenderSystem.enableBlend(); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + renderEntity( + graphics, example, level, x + 8, y + 16, ClientTickCounter.getTotal(), 8, 0, it -> it); + } + } + + // if ((flags & RENDER_REMAINDER) != 0) { + // EmiRender.renderRemainderIcon(this, poseStack, x, y); + // } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/EmiBrainsweepRecipe.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/EmiBrainsweepRecipe.java index 441a7e12ff..eb815c340d 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/EmiBrainsweepRecipe.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/EmiBrainsweepRecipe.java @@ -1,61 +1,80 @@ package at.petrak.hexcasting.fabric.interop.emi; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import dev.emi.emi.api.recipe.EmiRecipe; import dev.emi.emi.api.recipe.EmiRecipeCategory; import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.WidgetHolder; +import java.util.List; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; -import java.util.List; +public record EmiBrainsweepRecipe( + EmiIngredient blockInput, EmiIngredient villagerInput, EmiStack output, ResourceLocation id) + implements EmiRecipe { + private static final ResourceLocation OVERLAY = modLoc("textures/gui/brainsweep_jei.png"); -import static at.petrak.hexcasting.api.HexAPI.modLoc; + @Override + public EmiRecipeCategory getCategory() { + return HexEMIPlugin.BRAINSWEEP; + } + + @Override + public @Nullable ResourceLocation getId() { + return id; + } + + @Override + public List<EmiIngredient> getInputs() { + return List.of(blockInput, villagerInput); + } + + @Override + public List<EmiStack> getOutputs() { + return List.of(output); + } + + @Override + public int getDisplayWidth() { + return 118; + } + + @Override + public int getDisplayHeight() { + return 85; + } + + @Override + public void addWidgets(WidgetHolder widgets) { + widgets.addTexture( + OVERLAY, + 0, + 0, + getDisplayWidth(), + getDisplayHeight(), + 0, + 0, + getDisplayWidth(), + getDisplayHeight(), + 128, + 128); + widgets.addSlot(blockInput, 11, 34).drawBack(false).customBackground(null, 0, 0, 19, 19); + + widgets + .add( + new TheCoolerSlotWidget(villagerInput, 37, 19, 2.75f) + .useOffset(false) + .customShift(-8.5f, 2.485f)) + .drawBack(false) + .customBackground(null, 0, 0, 27, 49); -public record EmiBrainsweepRecipe(EmiIngredient blockInput, - EmiIngredient villagerInput, - EmiStack output, - ResourceLocation id) implements EmiRecipe { - private static final ResourceLocation OVERLAY = modLoc("textures/gui/brainsweep_jei.png"); - - @Override - public EmiRecipeCategory getCategory() { - return HexEMIPlugin.BRAINSWEEP; - } - - @Override - public @Nullable ResourceLocation getId() { - return id; - } - - @Override - public List<EmiIngredient> getInputs() { - return List.of(blockInput, villagerInput); - } - - @Override - public List<EmiStack> getOutputs() { - return List.of(output); - } - - @Override - public int getDisplayWidth() { - return 118; - } - - @Override - public int getDisplayHeight() { - return 85; - } - - @Override - public void addWidgets(WidgetHolder widgets) { - widgets.addTexture(OVERLAY, 0, 0, getDisplayWidth(), getDisplayHeight(), 0, 0, getDisplayWidth(), getDisplayHeight(), 128, 128); - widgets.addSlot(blockInput, 11, 34).drawBack(false).customBackground(null, 0, 0, 19, 19); - - widgets.add(new TheCoolerSlotWidget(villagerInput, 37, 19, 2.75f).useOffset(false).customShift(-8.5f, 2.485f)) - .drawBack(false).customBackground(null, 0, 0, 27, 49); - - widgets.addSlot(output, 86, 34).drawBack(false).large(true).recipeContext(this).customBackground(null, 0, 0, 19, 19); - } + widgets + .addSlot(output, 86, 34) + .drawBack(false) + .large(true) + .recipeContext(this) + .customBackground(null, 0, 0, 19, 19); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/EmiEdifyRecipe.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/EmiEdifyRecipe.java index 4c3f8d4c4d..1c6bcbb337 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/EmiEdifyRecipe.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/EmiEdifyRecipe.java @@ -1,87 +1,113 @@ package at.petrak.hexcasting.fabric.interop.emi; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.common.lib.HexBlocks; import dev.emi.emi.api.recipe.EmiRecipe; import dev.emi.emi.api.recipe.EmiRecipeCategory; import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.WidgetHolder; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.ItemTags; -import org.jetbrains.annotations.Nullable; - import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.ItemTags; +import org.jetbrains.annotations.Nullable; public class EmiEdifyRecipe implements EmiRecipe { - private static final ResourceLocation OVERLAY = modLoc("textures/gui/edify_jei.png"); + private static final ResourceLocation OVERLAY = modLoc("textures/gui/edify_jei.png"); - private final EmiIngredient saplings; - private final EmiIngredient leaves; - private final EmiIngredient log; + private final EmiIngredient saplings; + private final EmiIngredient leaves; + private final EmiIngredient log; - public EmiEdifyRecipe() { - this.saplings = EmiIngredient.of(ItemTags.SAPLINGS); - this.leaves = EmiIngredient.of(List.of( - EmiStack.of(HexBlocks.AMETHYST_EDIFIED_LEAVES), - EmiStack.of(HexBlocks.AVENTURINE_EDIFIED_LEAVES), - EmiStack.of(HexBlocks.CITRINE_EDIFIED_LEAVES) - )); - this.log = EmiIngredient.of(List.of( - EmiStack.of(HexBlocks.EDIFIED_LOG), - EmiStack.of(HexBlocks.EDIFIED_LOG_AMETHYST), - EmiStack.of(HexBlocks.EDIFIED_LOG_AVENTURINE), - EmiStack.of(HexBlocks.EDIFIED_LOG_CITRINE) -// EmiStack.of(HexBlocks.EDIFIED_LOG_PURPLE) - )); - } + public EmiEdifyRecipe() { + this.saplings = EmiIngredient.of(ItemTags.SAPLINGS); + this.leaves = + EmiIngredient.of( + List.of( + EmiStack.of(HexBlocks.AMETHYST_EDIFIED_LEAVES), + EmiStack.of(HexBlocks.AVENTURINE_EDIFIED_LEAVES), + EmiStack.of(HexBlocks.CITRINE_EDIFIED_LEAVES))); + this.log = + EmiIngredient.of( + List.of( + EmiStack.of(HexBlocks.EDIFIED_LOG), + EmiStack.of(HexBlocks.EDIFIED_LOG_AMETHYST), + EmiStack.of(HexBlocks.EDIFIED_LOG_AVENTURINE), + EmiStack.of(HexBlocks.EDIFIED_LOG_CITRINE) + // EmiStack.of(HexBlocks.EDIFIED_LOG_PURPLE) + )); + } - @Override - public EmiRecipeCategory getCategory() { - return HexEMIPlugin.EDIFY; - } + @Override + public EmiRecipeCategory getCategory() { + return HexEMIPlugin.EDIFY; + } - @Override - public @Nullable ResourceLocation getId() { - return HexEMIPlugin.EDIFY_ID; - } + @Override + public @Nullable ResourceLocation getId() { + return HexEMIPlugin.EDIFY_ID; + } - @Override - public List<EmiIngredient> getInputs() { - return List.of(saplings); - } + @Override + public List<EmiIngredient> getInputs() { + return List.of(saplings); + } - @Override - public List<EmiStack> getOutputs() { - return Stream.concat(leaves.getEmiStacks().stream(), log.getEmiStacks().stream()).collect(Collectors.toList()); - } + @Override + public List<EmiStack> getOutputs() { + return Stream.concat(leaves.getEmiStacks().stream(), log.getEmiStacks().stream()) + .collect(Collectors.toList()); + } - @Override - public int getDisplayWidth() { - return 79; - } + @Override + public int getDisplayWidth() { + return 79; + } - @Override - public int getDisplayHeight() { - return 61; - } + @Override + public int getDisplayHeight() { + return 61; + } - @Override - public boolean supportsRecipeTree() { - return false; - } + @Override + public boolean supportsRecipeTree() { + return false; + } - @Override - public void addWidgets(WidgetHolder widgets) { - widgets.addTexture(OVERLAY, 0, 0, getDisplayWidth(), getDisplayHeight(), 0, 0, getDisplayWidth(), getDisplayHeight(), 128, 128); - widgets.addSlot(saplings, 11, 21).drawBack(false).customBackground(null, 0, 0, 19, 19); - widgets.addGeneratedSlot(r -> { - var stacks = leaves.getEmiStacks(); - return stacks.get(r.nextInt(stacks.size())); - }, 0, 50, 9).drawBack(false).recipeContext(this).customBackground(null, 0, 0, 19, 19); - widgets.addSlot(log, 50, 34).drawBack(false).recipeContext(this).customBackground(null, 0, 0, 19, 19); - } + @Override + public void addWidgets(WidgetHolder widgets) { + widgets.addTexture( + OVERLAY, + 0, + 0, + getDisplayWidth(), + getDisplayHeight(), + 0, + 0, + getDisplayWidth(), + getDisplayHeight(), + 128, + 128); + widgets.addSlot(saplings, 11, 21).drawBack(false).customBackground(null, 0, 0, 19, 19); + widgets + .addGeneratedSlot( + r -> { + var stacks = leaves.getEmiStacks(); + return stacks.get(r.nextInt(stacks.size())); + }, + 0, + 50, + 9) + .drawBack(false) + .recipeContext(this) + .customBackground(null, 0, 0, 19, 19); + widgets + .addSlot(log, 50, 34) + .drawBack(false) + .recipeContext(this) + .customBackground(null, 0, 0, 19, 19); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/EmiPhialRecipe.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/EmiPhialRecipe.java index 2e74629169..139fb8fb07 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/EmiPhialRecipe.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/EmiPhialRecipe.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.fabric.interop.emi; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.mod.HexTags; import at.petrak.hexcasting.interop.utils.PhialRecipeStackBuilder; import dev.emi.emi.EmiUtil; @@ -8,77 +10,102 @@ import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.WidgetHolder; -import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.Nullable; - import java.util.List; import java.util.stream.Collectors; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.Nullable; public class EmiPhialRecipe implements EmiRecipe { - private static final ResourceLocation OVERLAY = modLoc("textures/gui/phial_jei.png"); + private static final ResourceLocation OVERLAY = modLoc("textures/gui/phial_jei.png"); - private final EmiIngredient inputs; - private final EmiIngredient bottle; - private final EmiIngredient outputs; + private final EmiIngredient inputs; + private final EmiIngredient bottle; + private final EmiIngredient outputs; - private final int uniq = EmiUtil.RANDOM.nextInt(); + private final int uniq = EmiUtil.RANDOM.nextInt(); - public EmiPhialRecipe() { - var stacks = PhialRecipeStackBuilder.createStacks(); - this.inputs = EmiIngredient.of(stacks.getFirst().stream().map(EmiStack::of).collect(Collectors.toList())); - this.bottle = EmiIngredient.of(HexTags.Items.PHIAL_BASE); - this.outputs = EmiIngredient.of(stacks.getSecond().stream().map(EmiStack::of).collect(Collectors.toList())); - } + public EmiPhialRecipe() { + var stacks = PhialRecipeStackBuilder.createStacks(); + this.inputs = + EmiIngredient.of(stacks.getFirst().stream().map(EmiStack::of).collect(Collectors.toList())); + this.bottle = EmiIngredient.of(HexTags.Items.PHIAL_BASE); + this.outputs = + EmiIngredient.of( + stacks.getSecond().stream().map(EmiStack::of).collect(Collectors.toList())); + } - @Override - public EmiRecipeCategory getCategory() { - return HexEMIPlugin.PHIAL; - } + @Override + public EmiRecipeCategory getCategory() { + return HexEMIPlugin.PHIAL; + } - @Override - public @Nullable ResourceLocation getId() { - return HexEMIPlugin.PHIAL_ID; - } + @Override + public @Nullable ResourceLocation getId() { + return HexEMIPlugin.PHIAL_ID; + } - @Override - public List<EmiIngredient> getInputs() { - return List.of(inputs, bottle); - } + @Override + public List<EmiIngredient> getInputs() { + return List.of(inputs, bottle); + } - @Override - public List<EmiStack> getOutputs() { - return outputs.getEmiStacks(); - } + @Override + public List<EmiStack> getOutputs() { + return outputs.getEmiStacks(); + } - @Override - public int getDisplayWidth() { - return 113; - } + @Override + public int getDisplayWidth() { + return 113; + } - @Override - public int getDisplayHeight() { - return 40; - } + @Override + public int getDisplayHeight() { + return 40; + } - @Override - public boolean supportsRecipeTree() { - return false; - } + @Override + public boolean supportsRecipeTree() { + return false; + } - @Override - public void addWidgets(WidgetHolder widgets) { - widgets.addTexture(OVERLAY, 0, 0, getDisplayWidth(), getDisplayHeight(), 0, 0, getDisplayWidth(), - getDisplayHeight(), 128, 128); - widgets.addGeneratedSlot((r) -> { - var stacks = inputs.getEmiStacks(); - return stacks.get(r.nextInt(stacks.size())); - }, uniq, 11, 11).drawBack(false).customBackground(null, 0, 0, 19, 19); - widgets.addSlot(bottle, 46, 11).drawBack(false).customBackground(null, 0, 0, 19, 19); - widgets.addGeneratedSlot((r) -> { - var stacks = outputs.getEmiStacks(); - return stacks.get(r.nextInt(stacks.size())); - }, uniq, 84, 11).drawBack(false).recipeContext(this).customBackground(null, 0, 0, 19, 19); - } + @Override + public void addWidgets(WidgetHolder widgets) { + widgets.addTexture( + OVERLAY, + 0, + 0, + getDisplayWidth(), + getDisplayHeight(), + 0, + 0, + getDisplayWidth(), + getDisplayHeight(), + 128, + 128); + widgets + .addGeneratedSlot( + (r) -> { + var stacks = inputs.getEmiStacks(); + return stacks.get(r.nextInt(stacks.size())); + }, + uniq, + 11, + 11) + .drawBack(false) + .customBackground(null, 0, 0, 19, 19); + widgets.addSlot(bottle, 46, 11).drawBack(false).customBackground(null, 0, 0, 19, 19); + widgets + .addGeneratedSlot( + (r) -> { + var stacks = outputs.getEmiStacks(); + return stacks.get(r.nextInt(stacks.size())); + }, + uniq, + 84, + 11) + .drawBack(false) + .recipeContext(this) + .customBackground(null, 0, 0, 19, 19); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/HexEMIPlugin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/HexEMIPlugin.java index 3c10fb9d4f..32997d8149 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/HexEMIPlugin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/HexEMIPlugin.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.fabric.interop.emi; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.mod.HexTags; import at.petrak.hexcasting.common.recipe.BrainsweepRecipe; import at.petrak.hexcasting.common.recipe.HexRecipeStuffRegistry; @@ -12,28 +14,35 @@ import dev.emi.emi.api.stack.EmiStack; import net.minecraft.resources.ResourceLocation; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class HexEMIPlugin implements EmiPlugin { private static final ResourceLocation BRAINSWEEP_ID = modLoc("brainsweep"); public static final ResourceLocation PHIAL_ID = modLoc("craft/battery"); public static final ResourceLocation EDIFY_ID = modLoc("edify"); - private static final ResourceLocation SIMPLIFIED_ICON_BRAINSWEEP = modLoc("textures/gui/brainsweep_emi.png"); - private static final ResourceLocation SIMPLIFIED_ICON_PHIAL = modLoc("textures/gui/phial_emi.png"); - private static final ResourceLocation SIMPLIFIED_ICON_EDIFY = modLoc("textures/gui/edify_emi.png"); + private static final ResourceLocation SIMPLIFIED_ICON_BRAINSWEEP = + modLoc("textures/gui/brainsweep_emi.png"); + private static final ResourceLocation SIMPLIFIED_ICON_PHIAL = + modLoc("textures/gui/phial_emi.png"); + private static final ResourceLocation SIMPLIFIED_ICON_EDIFY = + modLoc("textures/gui/edify_emi.png"); - public static final EmiRecipeCategory BRAINSWEEP = new EmiRecipeCategory(BRAINSWEEP_ID, - new PatternRendererEMI(BRAINSWEEP_ID, 16, 16), - new EmiTexture(SIMPLIFIED_ICON_BRAINSWEEP, 0, 0, 16, 16, 16, 16, 16, 16)); + public static final EmiRecipeCategory BRAINSWEEP = + new EmiRecipeCategory( + BRAINSWEEP_ID, + new PatternRendererEMI(BRAINSWEEP_ID, 16, 16), + new EmiTexture(SIMPLIFIED_ICON_BRAINSWEEP, 0, 0, 16, 16, 16, 16, 16, 16)); - public static final EmiRecipeCategory PHIAL = new EmiRecipeCategory(PHIAL_ID, - new PatternRendererEMI(PHIAL_ID, 12, 12).shift(2, 2), - new EmiTexture(SIMPLIFIED_ICON_PHIAL, 0, 0, 16, 16, 16, 16, 16, 16)); + public static final EmiRecipeCategory PHIAL = + new EmiRecipeCategory( + PHIAL_ID, + new PatternRendererEMI(PHIAL_ID, 12, 12).shift(2, 2), + new EmiTexture(SIMPLIFIED_ICON_PHIAL, 0, 0, 16, 16, 16, 16, 16, 16)); - public static final EmiRecipeCategory EDIFY = new EmiRecipeCategory(EDIFY_ID, - new PatternRendererEMI(EDIFY_ID, 16, 16).strokeOrder(false), - new EmiTexture(SIMPLIFIED_ICON_EDIFY, 0, 0, 16, 16, 16, 16, 16, 16)); + public static final EmiRecipeCategory EDIFY = + new EmiRecipeCategory( + EDIFY_ID, + new PatternRendererEMI(EDIFY_ID, 16, 16).strokeOrder(false), + new EmiTexture(SIMPLIFIED_ICON_EDIFY, 0, 0, 16, 16, 16, 16, 16, 16)); @Override public void register(EmiRegistry registry) { @@ -44,10 +53,11 @@ public void register(EmiRegistry registry) { registry.addWorkstation(PHIAL, EmiIngredient.of(HexTags.Items.STAVES)); registry.addWorkstation(EDIFY, EmiIngredient.of(HexTags.Items.STAVES)); - for (BrainsweepRecipe recipe : registry.getRecipeManager() - .getAllRecipesFor(HexRecipeStuffRegistry.BRAINSWEEP_TYPE)) { - var inputBlocks = EmiIngredient.of(recipe.blockIn().getDisplayedStacks().stream() - .map(EmiStack::of).toList()); + for (BrainsweepRecipe recipe : + registry.getRecipeManager().getAllRecipesFor(HexRecipeStuffRegistry.BRAINSWEEP_TYPE)) { + var inputBlocks = + EmiIngredient.of( + recipe.blockIn().getDisplayedStacks().stream().map(EmiStack::of).toList()); var inputEntity = new BrainsweepeeEmiStack(recipe.entityIn()); var output = EmiStack.of(recipe.result().getBlock()); registry.addRecipe(new EmiBrainsweepRecipe(inputBlocks, inputEntity, output, recipe.getId())); diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/PatternRendererEMI.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/PatternRendererEMI.java index da699de7a9..9a6fa6a7e6 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/PatternRendererEMI.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/PatternRendererEMI.java @@ -16,58 +16,72 @@ public class PatternRendererEMI implements EmiRenderable { - private final int width; - private final int height; + private final int width; + private final int height; - private int xOffset = 0; - private int yOffset = 0; + private int xOffset = 0; + private int yOffset = 0; - private boolean strokeOrder; + private boolean strokeOrder; - private final HexPattern pat; - private PatternSettings patSets; + private final HexPattern pat; + private PatternSettings patSets; - public PatternRendererEMI(ResourceLocation pattern, int w, int h) { - var regi = IXplatAbstractions.INSTANCE.getActionRegistry(); - var entry = regi.get(pattern); - this.strokeOrder = HexUtils.isOfTag(regi, pattern, HexTags.Actions.PER_WORLD_PATTERN); - this.pat = entry.prototype(); - this.width = w; - this.height = h; - this.patSets = new PatternSettings("pattern_drawable_" + w + "_" + h, - new PositionSettings(width, height, 0, 0, - PatternSettings.AxisAlignment.CENTER_FIT, PatternSettings.AxisAlignment.CENTER_FIT, Math.max(width, height), 0, 0), - StrokeSettings.fromStroke(0.075 * Math.min(width, height)), - ZappySettings.READABLE); - } + public PatternRendererEMI(ResourceLocation pattern, int w, int h) { + var regi = IXplatAbstractions.INSTANCE.getActionRegistry(); + var entry = regi.get(pattern); + this.strokeOrder = HexUtils.isOfTag(regi, pattern, HexTags.Actions.PER_WORLD_PATTERN); + this.pat = entry.prototype(); + this.width = w; + this.height = h; + this.patSets = + new PatternSettings( + "pattern_drawable_" + w + "_" + h, + new PositionSettings( + width, + height, + 0, + 0, + PatternSettings.AxisAlignment.CENTER_FIT, + PatternSettings.AxisAlignment.CENTER_FIT, + Math.max(width, height), + 0, + 0), + StrokeSettings.fromStroke(0.075 * Math.min(width, height)), + ZappySettings.READABLE); + } - public PatternRendererEMI shift(int x, int y) { - xOffset += x; - yOffset += y; - return this; - } + public PatternRendererEMI shift(int x, int y) { + xOffset += x; + yOffset += y; + return this; + } - public PatternRendererEMI strokeOrder(boolean order) { - if(order != strokeOrder){ - patSets = new PatternSettings("pattern_drawable_" + width + "_" + height + (order ? "" : "nostroke"), - patSets.posSets, - patSets.strokeSets, - order ? ZappySettings.READABLE : ZappySettings.STATIC - ); - } - strokeOrder = order; - return this; - } + public PatternRendererEMI strokeOrder(boolean order) { + if (order != strokeOrder) { + patSets = + new PatternSettings( + "pattern_drawable_" + width + "_" + height + (order ? "" : "nostroke"), + patSets.posSets, + patSets.strokeSets, + order ? ZappySettings.READABLE : ZappySettings.STATIC); + } + strokeOrder = order; + return this; + } - @Override - public void render(GuiGraphics graphics, int x, int y, float delta) { - var ps = graphics.pose(); - ps.pushPose(); - ps.translate(xOffset + x, yOffset + y + 1, 0); - PatternRenderer.renderPattern(pat, graphics.pose(), patSets, - new PatternColors(0xc8_0c0a0c, 0xff_333030).withDotColors(0x80_666363, 0), - 0, 10 - ); - ps.popPose(); - } + @Override + public void render(GuiGraphics graphics, int x, int y, float delta) { + var ps = graphics.pose(); + ps.pushPose(); + ps.translate(xOffset + x, yOffset + y + 1, 0); + PatternRenderer.renderPattern( + pat, + graphics.pose(), + patSets, + new PatternColors(0xc8_0c0a0c, 0xff_333030).withDotColors(0x80_666363, 0), + 0, + 10); + ps.popPose(); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/TheCoolerSlotWidget.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/TheCoolerSlotWidget.java index 2f936f78bf..c7c66e4e1d 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/TheCoolerSlotWidget.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/emi/TheCoolerSlotWidget.java @@ -11,56 +11,66 @@ public class TheCoolerSlotWidget extends SlotWidget { - private final float renderScale; + private final float renderScale; - public TheCoolerSlotWidget(EmiIngredient stack, int x, int y, float renderScale) { - super(stack, x, y); - this.renderScale = renderScale; - } + public TheCoolerSlotWidget(EmiIngredient stack, int x, int y, float renderScale) { + super(stack, x, y); + this.renderScale = renderScale; + } - private boolean useOffset = true; - private float xShift = 0; - private float yShift = 0; + private boolean useOffset = true; + private float xShift = 0; + private float yShift = 0; - public TheCoolerSlotWidget useOffset(boolean offset) { - useOffset = offset; - return this; - } + public TheCoolerSlotWidget useOffset(boolean offset) { + useOffset = offset; + return this; + } - public TheCoolerSlotWidget customShift(float xShift, float yShift) { - this.xShift = xShift; - this.yShift = yShift; - return this; - } + public TheCoolerSlotWidget customShift(float xShift, float yShift) { + this.xShift = xShift; + this.yShift = yShift; + return this; + } - @Override - public void render(GuiGraphics graphics, int x, int y, float delta) { - var poseStack = graphics.pose(); - Bounds bounds = this.getBounds(); - RenderSystem.setShader(GameRenderer::getPositionTexShader); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - int width = bounds.width(); - int height = bounds.height(); - if (this.drawBack) { - if (this.textureId != null) { - graphics.blit(this.textureId, bounds.x(), bounds.y(), width, height, (float)this.u, (float)this.v, width, height, 256, 256); - } else { - if (this.output) { - EmiTexture.LARGE_SLOT.render(graphics, bounds.x(), bounds.y(), delta); - } else { - EmiTexture.SLOT.render(graphics, bounds.x(), bounds.y(), delta); - } - } - } + @Override + public void render(GuiGraphics graphics, int x, int y, float delta) { + var poseStack = graphics.pose(); + Bounds bounds = this.getBounds(); + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + int width = bounds.width(); + int height = bounds.height(); + if (this.drawBack) { + if (this.textureId != null) { + graphics.blit( + this.textureId, + bounds.x(), + bounds.y(), + width, + height, + (float) this.u, + (float) this.v, + width, + height, + 256, + 256); + } else { + if (this.output) { + EmiTexture.LARGE_SLOT.render(graphics, bounds.x(), bounds.y(), delta); + } else { + EmiTexture.SLOT.render(graphics, bounds.x(), bounds.y(), delta); + } + } + } - int xOff = useOffset ? (width - 16) / 2 : 0; - int yOff = useOffset ? (height - 16) / 2 : 0; - poseStack.pushPose(); - poseStack.translate(bounds.x() + xOff + xShift, bounds.y() + yOff + yShift, 0); - poseStack.scale(renderScale, renderScale, 1); - this.getStack().render(graphics, 0, 0, delta); - if (this.catalyst) - EmiRender.renderCatalystIcon(this.getStack(), graphics, 0, 0); - poseStack.popPose(); - } + int xOff = useOffset ? (width - 16) / 2 : 0; + int yOff = useOffset ? (height - 16) / 2 : 0; + poseStack.pushPose(); + poseStack.translate(bounds.x() + xOff + xShift, bounds.y() + yOff + yShift, 0); + poseStack.scale(renderScale, renderScale, 1); + this.getStack().render(graphics, 0, 0, delta); + if (this.catalyst) EmiRender.renderCatalystIcon(this.getStack(), graphics, 0, 0); + poseStack.popPose(); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/trinkets/LensTrinketRenderer.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/trinkets/LensTrinketRenderer.java index 805905d03f..195eda780f 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/trinkets/LensTrinketRenderer.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/trinkets/LensTrinketRenderer.java @@ -10,45 +10,62 @@ import net.minecraft.client.model.PlayerModel; import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.block.model.ItemTransforms; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; /** - * @author WireSegal - * Created at 9:50 AM on 7/25/22. + * @author WireSegal Created at 9:50 AM on 7/25/22. */ public class LensTrinketRenderer implements TrinketRenderer { - @Override - @SuppressWarnings("unchecked") - public void render(ItemStack stack, SlotReference slotReference, EntityModel<? extends LivingEntity> model, - PoseStack matrices, MultiBufferSource multiBufferSource, int light, LivingEntity entity, - float limbAngle, float limbDistance, float tickDelta, float animationProgress, - float headYaw, float headPitch) { - if (stack.is(HexItems.SCRYING_LENS) && - model instanceof PlayerModel playerModel && - entity instanceof AbstractClientPlayer player) { + @Override + @SuppressWarnings("unchecked") + public void render( + ItemStack stack, + SlotReference slotReference, + EntityModel<? extends LivingEntity> model, + PoseStack matrices, + MultiBufferSource multiBufferSource, + int light, + LivingEntity entity, + float limbAngle, + float limbDistance, + float tickDelta, + float animationProgress, + float headYaw, + float headPitch) { + if (stack.is(HexItems.SCRYING_LENS) + && model instanceof PlayerModel playerModel + && entity instanceof AbstractClientPlayer player) { - // from https://github.com/Creators-of-Create/Create/blob/ee33823ed0b5084af10ed131a1626ce71db4c07e/src/main/java/com/simibubi/create/compat/curios/GogglesCurioRenderer.java + // from + // https://github.com/Creators-of-Create/Create/blob/ee33823ed0b5084af10ed131a1626ce71db4c07e/src/main/java/com/simibubi/create/compat/curios/GogglesCurioRenderer.java - // Translate and rotate with our head - matrices.pushPose(); - TrinketRenderer.followBodyRotations(entity, playerModel); - TrinketRenderer.translateToFace(matrices, playerModel, player, headYaw, headPitch); + // Translate and rotate with our head + matrices.pushPose(); + TrinketRenderer.followBodyRotations(entity, playerModel); + TrinketRenderer.translateToFace(matrices, playerModel, player, headYaw, headPitch); - // Translate and scale to our head - matrices.translate(0, 0, 0.3); - matrices.mulPose(Axis.ZP.rotationDegrees(180.0f)); - matrices.scale(0.625f, 0.625f, 0.625f); - - // Render - var instance = Minecraft.getInstance(); - instance.getItemRenderer().renderStatic(stack, ItemDisplayContext.HEAD, - light, OverlayTexture.NO_OVERLAY, matrices, multiBufferSource, instance.level, 0); - matrices.popPose(); - } - } + // Translate and scale to our head + matrices.translate(0, 0, 0.3); + matrices.mulPose(Axis.ZP.rotationDegrees(180.0f)); + matrices.scale(0.625f, 0.625f, 0.625f); + // Render + var instance = Minecraft.getInstance(); + instance + .getItemRenderer() + .renderStatic( + stack, + ItemDisplayContext.HEAD, + light, + OverlayTexture.NO_OVERLAY, + matrices, + multiBufferSource, + instance.level, + 0); + matrices.popPose(); + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/trinkets/TrinketsApiInterop.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/trinkets/TrinketsApiInterop.java index 54e51ed446..a618b800d5 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/trinkets/TrinketsApiInterop.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/interop/trinkets/TrinketsApiInterop.java @@ -10,6 +10,8 @@ import dev.emi.trinkets.api.TrinketComponent; import dev.emi.trinkets.api.TrinketsApi; import dev.emi.trinkets.api.client.TrinketRendererRegistry; +import java.util.Optional; +import java.util.UUID; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.core.registries.BuiltInRegistries; @@ -18,41 +20,43 @@ import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.item.ItemStack; -import java.util.Optional; -import java.util.UUID; - public class TrinketsApiInterop { - public static void init() { - BuiltInRegistries.ITEM.stream().forEach(item -> { - if (item instanceof HexBaubleItem bauble) { - TrinketsApi.registerTrinket(item, new Trinket() { - @Override - public Multimap<Attribute, AttributeModifier> getModifiers(ItemStack stack, SlotReference slot, - LivingEntity entity, UUID uuid) { - var map = Trinket.super.getModifiers(stack, slot, entity, uuid); - map.putAll(bauble.getHexBaubleAttrs(stack)); - return map; - } - }); - } - }); - + public static void init() { + BuiltInRegistries.ITEM.stream() + .forEach( + item -> { + if (item instanceof HexBaubleItem bauble) { + TrinketsApi.registerTrinket( + item, + new Trinket() { + @Override + public Multimap<Attribute, AttributeModifier> getModifiers( + ItemStack stack, SlotReference slot, LivingEntity entity, UUID uuid) { + var map = Trinket.super.getModifiers(stack, slot, entity, uuid); + map.putAll(bauble.getHexBaubleAttrs(stack)); + return map; + } + }); + } + }); - DiscoveryHandlers.addDebugItemDiscoverer((player, type) -> { - Optional<TrinketComponent> optional = TrinketsApi.getTrinketComponent(player); - if (optional.isPresent()) { - TrinketComponent component = optional.get(); - var equipped = component.getEquipped(stack -> ItemCreativeUnlocker.isDebug(stack, type)); - if (!equipped.isEmpty()) { - return equipped.get(0).getB(); - } - } - return ItemStack.EMPTY; - }); - } + DiscoveryHandlers.addDebugItemDiscoverer( + (player, type) -> { + Optional<TrinketComponent> optional = TrinketsApi.getTrinketComponent(player); + if (optional.isPresent()) { + TrinketComponent component = optional.get(); + var equipped = + component.getEquipped(stack -> ItemCreativeUnlocker.isDebug(stack, type)); + if (!equipped.isEmpty()) { + return equipped.get(0).getB(); + } + } + return ItemStack.EMPTY; + }); + } - @Environment(EnvType.CLIENT) - public static void clientInit() { - TrinketRendererRegistry.registerRenderer(HexItems.SCRYING_LENS, new LensTrinketRenderer()); - } + @Environment(EnvType.CLIENT) + public static void clientInit() { + TrinketRendererRegistry.registerRenderer(HexItems.SCRYING_LENS, new LensTrinketRenderer()); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/loot/FabricHexLootModJankery.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/loot/FabricHexLootModJankery.java index 5aadc8df41..808aa2cc50 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/loot/FabricHexLootModJankery.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/loot/FabricHexLootModJankery.java @@ -1,8 +1,12 @@ package at.petrak.hexcasting.fabric.loot; +import static at.petrak.hexcasting.api.HexAPI.modLoc; +import static at.petrak.hexcasting.common.loot.HexLootHandler.TABLE_INJECT_AMETHYST_CLUSTER; + import at.petrak.hexcasting.common.lib.HexItems; import at.petrak.hexcasting.common.loot.AddPerWorldPatternToScrollFunc; import at.petrak.hexcasting.fabric.FabricHexInitializer; +import java.util.function.Consumer; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.storage.loot.LootPool; @@ -14,46 +18,41 @@ import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator; import org.jetbrains.annotations.NotNull; -import java.util.function.Consumer; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; -import static at.petrak.hexcasting.common.loot.HexLootHandler.TABLE_INJECT_AMETHYST_CLUSTER; - public class FabricHexLootModJankery { - public static final ResourceLocation FUNC_AMETHYST_SHARD_REDUCER = modLoc("amethyst_shard_reducer"); - - public static void lootLoad(ResourceLocation id, Consumer<LootPool.Builder> addPool) { - if (id.equals(Blocks.AMETHYST_CLUSTER.getLootTable())) { - addPool.accept(makeAmethystInjectPool()); - } - - int countRange = FabricHexInitializer.CONFIG.server.scrollRangeForLootTable(id); - if (countRange != -1) { - addPool.accept(makeScrollAddPool(countRange)); - } - - if (FabricHexInitializer.CONFIG.server.shouldInjectLore(id)) { - addPool.accept(makeLoreAddPool(FabricHexInitializer.CONFIG.server.getLoreChance())); - } - } - - @NotNull - private static LootPool.Builder makeAmethystInjectPool() { - return LootPool.lootPool() - .add(LootTableReference.lootTableReference(TABLE_INJECT_AMETHYST_CLUSTER)); - } - - private static LootPool.Builder makeScrollAddPool(int range) { - return LootPool.lootPool() - .setRolls(UniformGenerator.between(-range, range)) - .add(LootItem.lootTableItem(HexItems.SCROLL_LARGE)) - .apply(() -> new AddPerWorldPatternToScrollFunc(new LootItemCondition[0])); - } - - private static LootPool.Builder makeLoreAddPool(double chance) { - return LootPool.lootPool() - .when(LootItemRandomChanceCondition.randomChance((float) chance)) - .setRolls(ConstantValue.exactly(1)) - .add(LootItem.lootTableItem(HexItems.LORE_FRAGMENT)); - } + public static final ResourceLocation FUNC_AMETHYST_SHARD_REDUCER = + modLoc("amethyst_shard_reducer"); + + public static void lootLoad(ResourceLocation id, Consumer<LootPool.Builder> addPool) { + if (id.equals(Blocks.AMETHYST_CLUSTER.getLootTable())) { + addPool.accept(makeAmethystInjectPool()); + } + + int countRange = FabricHexInitializer.CONFIG.server.scrollRangeForLootTable(id); + if (countRange != -1) { + addPool.accept(makeScrollAddPool(countRange)); + } + + if (FabricHexInitializer.CONFIG.server.shouldInjectLore(id)) { + addPool.accept(makeLoreAddPool(FabricHexInitializer.CONFIG.server.getLoreChance())); + } + } + + @NotNull private static LootPool.Builder makeAmethystInjectPool() { + return LootPool.lootPool() + .add(LootTableReference.lootTableReference(TABLE_INJECT_AMETHYST_CLUSTER)); + } + + private static LootPool.Builder makeScrollAddPool(int range) { + return LootPool.lootPool() + .setRolls(UniformGenerator.between(-range, range)) + .add(LootItem.lootTableItem(HexItems.SCROLL_LARGE)) + .apply(() -> new AddPerWorldPatternToScrollFunc(new LootItemCondition[0])); + } + + private static LootPool.Builder makeLoreAddPool(double chance) { + return LootPool.lootPool() + .when(LootItemRandomChanceCondition.randomChance((float) chance)) + .setRolls(ConstantValue.exactly(1)) + .add(LootItem.lootTableItem(HexItems.LORE_FRAGMENT)); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricAxeItemMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricAxeItemMixin.java index 77134ef0b1..02b5b1c5b7 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricAxeItemMixin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricAxeItemMixin.java @@ -1,6 +1,7 @@ package at.petrak.hexcasting.fabric.mixin; import at.petrak.hexcasting.common.blocks.behavior.HexStrippables; +import java.util.Optional; import net.minecraft.world.item.AxeItem; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; @@ -8,18 +9,16 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.Optional; - // https://github.com/VazkiiMods/Botania/blob/1.18.x/Fabric/src/main/java/vazkii/botania/fabric/mixin/FabricMixinAxeItem.java @Mixin(AxeItem.class) public class FabricAxeItemMixin { - @Inject(method = "getStripped", at = @At("RETURN"), cancellable = true) - private void stripBlock(BlockState state, CallbackInfoReturnable<Optional<BlockState>> cir) { - if (cir.getReturnValue().isEmpty()) { - var block = HexStrippables.STRIPPABLES.get(state.getBlock()); - if (block != null) { - cir.setReturnValue(Optional.of(block.withPropertiesOf(state))); - } - } - } + @Inject(method = "getStripped", at = @At("RETURN"), cancellable = true) + private void stripBlock(BlockState state, CallbackInfoReturnable<Optional<BlockState>> cir) { + if (cir.getReturnValue().isEmpty()) { + var block = HexStrippables.STRIPPABLES.get(state.getBlock()); + if (block != null) { + cir.setReturnValue(Optional.of(block.withPropertiesOf(state))); + } + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricBlockBehaviorMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricBlockBehaviorMixin.java index 6fefcf68bc..0fafe39f4d 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricBlockBehaviorMixin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricBlockBehaviorMixin.java @@ -13,11 +13,15 @@ @Mixin(BlockBehaviour.class) public class FabricBlockBehaviorMixin { - @Inject(method = "getDestroyProgress", at = @At("HEAD"), cancellable = true) - private void destroyProgress(BlockState blockState, Player player, BlockGetter blockGetter, BlockPos blockPos, - CallbackInfoReturnable<Float> cir) { - if (ItemJewelerHammer.shouldFailToBreak(player, blockState, blockPos)) { - cir.setReturnValue(0F); - } - } + @Inject(method = "getDestroyProgress", at = @At("HEAD"), cancellable = true) + private void destroyProgress( + BlockState blockState, + Player player, + BlockGetter blockGetter, + BlockPos blockPos, + CallbackInfoReturnable<Float> cir) { + if (ItemJewelerHammer.shouldFailToBreak(player, blockState, blockPos)) { + cir.setReturnValue(0F); + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricClipContextMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricClipContextMixin.java index d2793487d0..0b23c25b34 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricClipContextMixin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricClipContextMixin.java @@ -1,6 +1,5 @@ package at.petrak.hexcasting.fabric.mixin; - import net.minecraft.world.entity.Entity; import net.minecraft.world.level.ClipContext; import net.minecraft.world.phys.shapes.CollisionContext; @@ -11,14 +10,16 @@ @Mixin(ClipContext.class) public abstract class FabricClipContextMixin { - @Redirect(method = "<init>", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/phys/shapes/CollisionContext;of" + - "(Lnet/minecraft/world/entity/Entity;)Lnet/minecraft/world/phys/shapes/CollisionContext;")) - public CollisionContext hex$getCollisionContext(Entity entity) { - if (entity == null) - return CollisionContext.empty(); - return CollisionContext.of(entity); - } + @Redirect( + method = "<init>", + at = + @At( + value = "INVOKE", + target = + "Lnet/minecraft/world/phys/shapes/CollisionContext;of" + + "(Lnet/minecraft/world/entity/Entity;)Lnet/minecraft/world/phys/shapes/CollisionContext;")) + public CollisionContext hex$getCollisionContext(Entity entity) { + if (entity == null) return CollisionContext.empty(); + return CollisionContext.of(entity); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricEnchantmentTableBlockMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricEnchantmentTableBlockMixin.java index 09bc4ac83c..fb709ee125 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricEnchantmentTableBlockMixin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricEnchantmentTableBlockMixin.java @@ -12,12 +12,15 @@ @Mixin(EnchantmentTableBlock.class) public class FabricEnchantmentTableBlockMixin { - @Inject(method = "isValidBookShelf", at = @At("HEAD"), cancellable = true) - private static void treatAsBookshelf(Level level, BlockPos blockPos, BlockPos blockPos2, CallbackInfoReturnable<Boolean> cir) { - BlockState state = level.getBlockState(blockPos.offset(blockPos2)); - if (state.getBlock() instanceof IForgeLikeBlock forgeLike) { - boolean emptyBetween = level.isEmptyBlock(blockPos.offset(blockPos2.getX() / 2, blockPos2.getY(), blockPos2.getZ() / 2)); - cir.setReturnValue(emptyBetween && forgeLike.hasEnchantPowerBonus(state, level, blockPos)); - } - } + @Inject(method = "isValidBookShelf", at = @At("HEAD"), cancellable = true) + private static void treatAsBookshelf( + Level level, BlockPos blockPos, BlockPos blockPos2, CallbackInfoReturnable<Boolean> cir) { + BlockState state = level.getBlockState(blockPos.offset(blockPos2)); + if (state.getBlock() instanceof IForgeLikeBlock forgeLike) { + boolean emptyBetween = + level.isEmptyBlock( + blockPos.offset(blockPos2.getX() / 2, blockPos2.getY(), blockPos2.getZ() / 2)); + cir.setReturnValue(emptyBetween && forgeLike.hasEnchantPowerBonus(state, level, blockPos)); + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricItemEntityMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricItemEntityMixin.java index 61f00bcbce..a4835de897 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricItemEntityMixin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricItemEntityMixin.java @@ -9,10 +9,10 @@ @Mixin(ItemEntity.class) public class FabricItemEntityMixin { - @Inject(method = "tick", at = @At("HEAD"), cancellable = true) - private void tick(CallbackInfo ci) { - ItemEntity entity = (ItemEntity) (Object) this; - if (entity.getItem().is(HexItems.SLATE) && HexItems.SLATE.onEntityItemUpdate(entity.getItem(), entity)) - ci.cancel(); - } + @Inject(method = "tick", at = @At("HEAD"), cancellable = true) + private void tick(CallbackInfo ci) { + ItemEntity entity = (ItemEntity) (Object) this; + if (entity.getItem().is(HexItems.SLATE) + && HexItems.SLATE.onEntityItemUpdate(entity.getItem(), entity)) ci.cancel(); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricLivingEntityMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricLivingEntityMixin.java index 6f92a05952..77d514fa26 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricLivingEntityMixin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricLivingEntityMixin.java @@ -15,33 +15,42 @@ @Mixin(LivingEntity.class) public class FabricLivingEntityMixin { - @Unique - private BlockState hex$cachedParticleState; + @Unique private BlockState hex$cachedParticleState; - @ModifyVariable(method = "checkFallDamage", at = @At(value = "LOAD", ordinal = 0), argsOnly = true) - private BlockState overwrite(BlockState state, double d, boolean bl, BlockState _ignored, BlockPos pos) { - LivingEntity entity = (LivingEntity) (Object) this; + @ModifyVariable( + method = "checkFallDamage", + at = @At(value = "LOAD", ordinal = 0), + argsOnly = true) + private BlockState overwrite( + BlockState state, double d, boolean bl, BlockState _ignored, BlockPos pos) { + LivingEntity entity = (LivingEntity) (Object) this; - if (state.getBlock() instanceof IForgeLikeBlock forgeLike) { - float dist = (float) Mth.ceil(entity.fallDistance - 3.0F); - double e = Math.min(0.2F + dist / 15.0F, 2.5D); - int i = (int)(150.0D * e); - if (forgeLike.addLandingEffects(state, (ServerLevel) entity.level(), pos, entity, i)) { - hex$cachedParticleState = state; - return Blocks.AIR.defaultBlockState(); - } - } + if (state.getBlock() instanceof IForgeLikeBlock forgeLike) { + float dist = (float) Mth.ceil(entity.fallDistance - 3.0F); + double e = Math.min(0.2F + dist / 15.0F, 2.5D); + int i = (int) (150.0D * e); + if (forgeLike.addLandingEffects(state, (ServerLevel) entity.level(), pos, entity, i)) { + hex$cachedParticleState = state; + return Blocks.AIR.defaultBlockState(); + } + } - return state; - } + return state; + } - @ModifyArg(method = "checkFallDamage", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;checkFallDamage(DZLnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;)V")) - private BlockState restore(BlockState state) { - if (hex$cachedParticleState != null) { - BlockState cached = hex$cachedParticleState; - hex$cachedParticleState = null; - return cached; - } - return state; - } + @ModifyArg( + method = "checkFallDamage", + at = + @At( + value = "INVOKE", + target = + "Lnet/minecraft/world/entity/Entity;checkFallDamage(DZLnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;)V")) + private BlockState restore(BlockState state) { + if (hex$cachedParticleState != null) { + BlockState cached = hex$cachedParticleState; + hex$cachedParticleState = null; + return cached; + } + return state; + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricMixinReloadableServerResources.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricMixinReloadableServerResources.java index 70b6bc2113..cdc8f79055 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricMixinReloadableServerResources.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricMixinReloadableServerResources.java @@ -3,6 +3,8 @@ import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.fabric.loot.FabricHexLootModJankery; import at.petrak.hexcasting.mixin.accessor.AccessorLootTable; +import java.util.Arrays; +import java.util.concurrent.CompletableFuture; import net.minecraft.server.ReloadableServerResources; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.storage.loot.LootDataId; @@ -13,28 +15,37 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.Arrays; -import java.util.concurrent.CompletableFuture; - @Mixin(ReloadableServerResources.class) public class FabricMixinReloadableServerResources { - // Add the amethyst shard - @Inject(method = "loadResources", at = @At("RETURN"), cancellable = true) - private static void onLoadResources(CallbackInfoReturnable<CompletableFuture<ReloadableServerResources>> cir) { - cir.setReturnValue(cir.getReturnValue().thenApply((rsr) -> { - var amethystTable = rsr.getLootData().getLootTable(Blocks.AMETHYST_CLUSTER.getLootTable()); - var theCoolerAmethystTable = (AccessorLootTable) amethystTable; - var oldFuncs = theCoolerAmethystTable.hex$getFunctions(); - var newFuncs = Arrays.copyOf(oldFuncs, oldFuncs.length + 1); - var shardReducer = rsr.getLootData().getElement(new LootDataId<>(LootDataType.MODIFIER, FabricHexLootModJankery.FUNC_AMETHYST_SHARD_REDUCER)); - if (shardReducer != null) { - newFuncs[newFuncs.length - 1] = shardReducer; - theCoolerAmethystTable.hex$setFunctions(newFuncs); - theCoolerAmethystTable.hex$setCompositeFunction(LootItemFunctions.compose(newFuncs)); - } else { - HexAPI.LOGGER.warn("{} was not found?", FabricHexLootModJankery.FUNC_AMETHYST_SHARD_REDUCER); - } - return rsr; - })); - } + // Add the amethyst shard + @Inject(method = "loadResources", at = @At("RETURN"), cancellable = true) + private static void onLoadResources( + CallbackInfoReturnable<CompletableFuture<ReloadableServerResources>> cir) { + cir.setReturnValue( + cir.getReturnValue() + .thenApply( + (rsr) -> { + var amethystTable = + rsr.getLootData().getLootTable(Blocks.AMETHYST_CLUSTER.getLootTable()); + var theCoolerAmethystTable = (AccessorLootTable) amethystTable; + var oldFuncs = theCoolerAmethystTable.hex$getFunctions(); + var newFuncs = Arrays.copyOf(oldFuncs, oldFuncs.length + 1); + var shardReducer = + rsr.getLootData() + .getElement( + new LootDataId<>( + LootDataType.MODIFIER, + FabricHexLootModJankery.FUNC_AMETHYST_SHARD_REDUCER)); + if (shardReducer != null) { + newFuncs[newFuncs.length - 1] = shardReducer; + theCoolerAmethystTable.hex$setFunctions(newFuncs); + theCoolerAmethystTable.hex$setCompositeFunction( + LootItemFunctions.compose(newFuncs)); + } else { + HexAPI.LOGGER.warn( + "{} was not found?", FabricHexLootModJankery.FUNC_AMETHYST_SHARD_REDUCER); + } + return rsr; + })); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricMobMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricMobMixin.java index e2464313fa..29e2e2dba6 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricMobMixin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricMobMixin.java @@ -10,12 +10,13 @@ @Mixin(Mob.class) public class FabricMobMixin { - @Inject(method = "convertTo", at = @At("RETURN")) - public <T extends Mob> void onThunderHit(EntityType<T> entityType, boolean bl, CallbackInfoReturnable<T> cir) { - var self = (Mob) (Object) this; - var mob = cir.getReturnValue(); - if (mob != null) { - VillagerConversionCallback.EVENT.invoker().interact(self, mob); - } - } + @Inject(method = "convertTo", at = @At("RETURN")) + public <T extends Mob> void onThunderHit( + EntityType<T> entityType, boolean bl, CallbackInfoReturnable<T> cir) { + var self = (Mob) (Object) this; + var mob = cir.getReturnValue(); + if (mob != null) { + VillagerConversionCallback.EVENT.invoker().interact(self, mob); + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricPlayerMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricPlayerMixin.java index 2c7584663f..364c3be874 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricPlayerMixin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricPlayerMixin.java @@ -13,14 +13,14 @@ @Mixin(Player.class) public abstract class FabricPlayerMixin extends LivingEntity { - protected FabricPlayerMixin(EntityType<? extends LivingEntity> entityType, Level level) { - super(entityType, level); - } + protected FabricPlayerMixin(EntityType<? extends LivingEntity> entityType, Level level) { + super(entityType, level); + } - @Inject(at = @At("RETURN"), method = "createAttributes") - private static void hex$addAttributes(CallbackInfoReturnable<AttributeSupplier.Builder> cir) { - var out = cir.getReturnValue(); - out.add(HexAttributes.GRID_ZOOM); - out.add(HexAttributes.SCRY_SIGHT); - } + @Inject(at = @At("RETURN"), method = "createAttributes") + private static void hex$addAttributes(CallbackInfoReturnable<AttributeSupplier.Builder> cir) { + var out = cir.getReturnValue(); + out.add(HexAttributes.GRID_ZOOM); + out.add(HexAttributes.SCRY_SIGHT); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricVillagerTurnIntoWitchMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricVillagerTurnIntoWitchMixin.java index c91af28360..95c5bd531d 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricVillagerTurnIntoWitchMixin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/FabricVillagerTurnIntoWitchMixin.java @@ -13,9 +13,17 @@ @Mixin(Villager.class) public class FabricVillagerTurnIntoWitchMixin { - @Inject(method = "thunderHit", locals = LocalCapture.CAPTURE_FAILSOFT, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V")) - public void onThunderHit(ServerLevel serverLevel, LightningBolt lightningBolt, CallbackInfo ci, Witch newWitch) { - var self = (Villager) (Object) this; - VillagerConversionCallback.EVENT.invoker().interact(self, newWitch); - } + @Inject( + method = "thunderHit", + locals = LocalCapture.CAPTURE_FAILSOFT, + at = + @At( + value = "INVOKE", + target = + "Lnet/minecraft/server/level/ServerLevel;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V")) + public void onThunderHit( + ServerLevel serverLevel, LightningBolt lightningBolt, CallbackInfo ci, Witch newWitch) { + var self = (Villager) (Object) this; + VillagerConversionCallback.EVENT.invoker().interact(self, newWitch); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricAbstractTextureMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricAbstractTextureMixin.java index 41dedaaab4..362c20cf3d 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricAbstractTextureMixin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricAbstractTextureMixin.java @@ -8,30 +8,26 @@ @Mixin(AbstractTexture.class) public abstract class FabricAbstractTextureMixin implements ExtendedTexture { - @Shadow - protected boolean blur; + @Shadow protected boolean blur; - @Shadow - protected boolean mipmap; + @Shadow protected boolean mipmap; - @Shadow - public abstract void setFilter(boolean bilinear, boolean mipmap); + @Shadow + public abstract void setFilter(boolean bilinear, boolean mipmap); - @Unique - private boolean lastBilinear; + @Unique private boolean lastBilinear; - @Unique - private boolean lastMipmap; + @Unique private boolean lastMipmap; - @Override - public void setFilterSave(boolean bilinear, boolean mipmap) { - this.lastBilinear = this.blur; - this.lastMipmap = this.mipmap; - setFilter(bilinear, mipmap); - } + @Override + public void setFilterSave(boolean bilinear, boolean mipmap) { + this.lastBilinear = this.blur; + this.lastMipmap = this.mipmap; + setFilter(bilinear, mipmap); + } - @Override - public void restoreLastFilter() { - setFilter(this.lastBilinear, this.lastMipmap); - } + @Override + public void restoreLastFilter() { + setFilter(this.lastBilinear, this.lastMipmap); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricLevelRendererMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricLevelRendererMixin.java index d6f1ff127b..6d70b00108 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricLevelRendererMixin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricLevelRendererMixin.java @@ -18,17 +18,34 @@ @Mixin(LevelRenderer.class) public class FabricLevelRendererMixin { - @SuppressWarnings("InvalidInjectorMethodSignature") - @Inject( - method = "renderLevel", - at = @At( - value = "INVOKE", target = "Lnet/minecraft/client/renderer/FogRenderer;levelFogColor()V", - ordinal = 0), - locals = LocalCapture.CAPTURE_FAILSOFT) - private void snagFrustumFromLevelRenderer(PoseStack poseStack, float f, long arg2, boolean bl, Camera camera, - GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, CallbackInfo ci, - ProfilerFiller profilerFiller, boolean bl2, Vec3 vec3, double d, double e, double g, Matrix4f matrix4f2, - boolean bl3, Frustum frustum) { - FabricClientXplatImpl.LEVEL_RENDERER_FRUSTUM = frustum; - } + @SuppressWarnings("InvalidInjectorMethodSignature") + @Inject( + method = "renderLevel", + at = + @At( + value = "INVOKE", + target = "Lnet/minecraft/client/renderer/FogRenderer;levelFogColor()V", + ordinal = 0), + locals = LocalCapture.CAPTURE_FAILSOFT) + private void snagFrustumFromLevelRenderer( + PoseStack poseStack, + float f, + long arg2, + boolean bl, + Camera camera, + GameRenderer gameRenderer, + LightTexture lightTexture, + Matrix4f matrix4f, + CallbackInfo ci, + ProfilerFiller profilerFiller, + boolean bl2, + Vec3 vec3, + double d, + double e, + double g, + Matrix4f matrix4f2, + boolean bl3, + Frustum frustum) { + FabricClientXplatImpl.LEVEL_RENDERER_FRUSTUM = frustum; + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricMixinGameRenderer.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricMixinGameRenderer.java index b16f82eec5..80dd0cd2e1 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricMixinGameRenderer.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricMixinGameRenderer.java @@ -3,6 +3,9 @@ import at.petrak.hexcasting.client.render.shader.HexShaders; import com.mojang.blaze3d.shaders.Program; import com.mojang.datafixers.util.Pair; +import java.io.IOException; +import java.util.List; +import java.util.function.Consumer; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.server.packs.resources.ResourceProvider; @@ -12,27 +15,25 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import java.io.IOException; -import java.util.List; -import java.util.function.Consumer; - // https://github.com/VazkiiMods/Botania/blob/b1f1cf80e10b1c739b0188171b367d9cefc4d3c7/Fabric/src/main/java/vazkii/botania/fabric/mixin/client/FabricMixinGameRenderer.java @Mixin(GameRenderer.class) public class FabricMixinGameRenderer { - @SuppressWarnings("InvalidInjectorMethodSignature") - @Inject( - method = "reloadShaders", - at = @At( - value = "INVOKE_ASSIGN", - target = "Lcom/google/common/collect/Lists;newArrayListWithCapacity(I)Ljava/util/ArrayList;", - remap = false - ), - locals = LocalCapture.CAPTURE_FAILHARD - ) - private void loadShaders(ResourceProvider resourceProvider, CallbackInfo ci, - List<Program> _programsToClose, - List<Pair<ShaderInstance, Consumer<ShaderInstance>>> shadersToLoad) - throws IOException { - HexShaders.init(resourceProvider, shadersToLoad::add); - } + @SuppressWarnings("InvalidInjectorMethodSignature") + @Inject( + method = "reloadShaders", + at = + @At( + value = "INVOKE_ASSIGN", + target = + "Lcom/google/common/collect/Lists;newArrayListWithCapacity(I)Ljava/util/ArrayList;", + remap = false), + locals = LocalCapture.CAPTURE_FAILHARD) + private void loadShaders( + ResourceProvider resourceProvider, + CallbackInfo ci, + List<Program> _programsToClose, + List<Pair<ShaderInstance, Consumer<ShaderInstance>>> shadersToLoad) + throws IOException { + HexShaders.init(resourceProvider, shadersToLoad::add); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricModelManagerMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricModelManagerMixin.java index b644801a83..a61dd3a925 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricModelManagerMixin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricModelManagerMixin.java @@ -1,11 +1,11 @@ package at.petrak.hexcasting.fabric.mixin.client; import at.petrak.hexcasting.client.RegisterClientStuff; +import java.util.Map; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.ModelBakery; import net.minecraft.client.resources.model.ModelManager; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.util.profiling.ProfilerFiller; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -14,21 +14,29 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import java.util.Map; - // https://github.com/VazkiiMods/Botania/blob/986dff2e8cd9f40f7e4d6ed7b30c98944bdb3b87/Fabric/src/main/java/vazkii/botania/fabric/mixin/client/ModelManagerFabricMixin.java#L34 @Mixin(ModelManager.class) public class FabricModelManagerMixin { - @Shadow - private Map<ResourceLocation, BakedModel> bakedRegistry; + @Shadow private Map<ResourceLocation, BakedModel> bakedRegistry; - @Inject(at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/client/resources/model/ModelBakery;" + - "getBakedTopLevelModels()Ljava/util/Map;", shift = At.Shift.AFTER), - method = "Lnet/minecraft/client/resources/model/ModelManager;apply(" + - "Lnet/minecraft/client/resources/model/ModelManager$ReloadState;" + - "Lnet/minecraft/util/profiling/ProfilerFiller;)V", - locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void onModelBake(ModelManager.ReloadState reloadState, ProfilerFiller profiler, CallbackInfo ci, ModelBakery modelLoader) { - RegisterClientStuff.onModelBake(modelLoader, this.bakedRegistry); - } + @Inject( + at = + @At( + value = "INVOKE_ASSIGN", + target = + "Lnet/minecraft/client/resources/model/ModelBakery;" + + "getBakedTopLevelModels()Ljava/util/Map;", + shift = At.Shift.AFTER), + method = + "Lnet/minecraft/client/resources/model/ModelManager;apply(" + + "Lnet/minecraft/client/resources/model/ModelManager$ReloadState;" + + "Lnet/minecraft/util/profiling/ProfilerFiller;)V", + locals = LocalCapture.CAPTURE_FAILEXCEPTION) + private void onModelBake( + ModelManager.ReloadState reloadState, + ProfilerFiller profiler, + CallbackInfo ci, + ModelBakery modelLoader) { + RegisterClientStuff.onModelBake(modelLoader, this.bakedRegistry); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricMouseHandlerMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricMouseHandlerMixin.java index 66e7bf3fc9..ffd84a6c2f 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricMouseHandlerMixin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricMouseHandlerMixin.java @@ -10,11 +10,16 @@ @Mixin(MouseHandler.class) public class FabricMouseHandlerMixin { - @Inject(method = "onScroll", cancellable = true, locals = LocalCapture.CAPTURE_FAILSOFT, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;isSpectator()Z")) - private void onScroll(long winptr, double xOff, double yOff, CallbackInfo ci, double delta) { - var cancel = MouseScrollCallback.EVENT.invoker().interact(delta); - if (cancel) { - ci.cancel(); - } - } + @Inject( + method = "onScroll", + cancellable = true, + locals = LocalCapture.CAPTURE_FAILSOFT, + at = + @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;isSpectator()Z")) + private void onScroll(long winptr, double xOff, double yOff, CallbackInfo ci, double delta) { + var cancel = MouseScrollCallback.EVENT.invoker().interact(delta); + if (cancel) { + ci.cancel(); + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricParticleEngineMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricParticleEngineMixin.java index 41eb3934f5..8671f4d007 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricParticleEngineMixin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricParticleEngineMixin.java @@ -2,6 +2,7 @@ import at.petrak.hexcasting.client.particles.ConjureParticle; import com.google.common.collect.ImmutableList; +import java.util.List; import net.minecraft.client.particle.ParticleEngine; import net.minecraft.client.particle.ParticleRenderType; import org.spongepowered.asm.mixin.Final; @@ -12,19 +13,16 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.List; - @Mixin(ParticleEngine.class) public class FabricParticleEngineMixin { - @Mutable - @Final - @Shadow - private static List<ParticleRenderType> RENDER_ORDER; + @Mutable @Final @Shadow private static List<ParticleRenderType> RENDER_ORDER; - @Inject(at = @At("RETURN"), method = "<clinit>") - private static void addTypes(CallbackInfo ci) { - RENDER_ORDER = ImmutableList.<ParticleRenderType>builder().addAll(RENDER_ORDER) - .add(ConjureParticle.CONJURE_RENDER_TYPE, ConjureParticle.CONJURE_RENDER_TYPE) - .build(); - } + @Inject(at = @At("RETURN"), method = "<clinit>") + private static void addTypes(CallbackInfo ci) { + RENDER_ORDER = + ImmutableList.<ParticleRenderType>builder() + .addAll(RENDER_ORDER) + .add(ConjureParticle.CONJURE_RENDER_TYPE, ConjureParticle.CONJURE_RENDER_TYPE) + .build(); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricPlayerRendererMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricPlayerRendererMixin.java index ec5bd74371..149ae0cd39 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricPlayerRendererMixin.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricPlayerRendererMixin.java @@ -12,13 +12,17 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(PlayerRenderer.class) -public abstract class FabricPlayerRendererMixin extends LivingEntityRenderer<AbstractClientPlayer, PlayerModel<AbstractClientPlayer>> { - public FabricPlayerRendererMixin(EntityRendererProvider.Context context, PlayerModel<AbstractClientPlayer> entityModel, float f) { - super(context, entityModel, f); - } +public abstract class FabricPlayerRendererMixin + extends LivingEntityRenderer<AbstractClientPlayer, PlayerModel<AbstractClientPlayer>> { + public FabricPlayerRendererMixin( + EntityRendererProvider.Context context, + PlayerModel<AbstractClientPlayer> entityModel, + float f) { + super(context, entityModel, f); + } - @Inject(method = "<init>", at = @At("TAIL")) - private void addAltiora(EntityRendererProvider.Context ctx, boolean bl, CallbackInfo ci) { - this.addLayer(new AltioraLayer<>((PlayerRenderer)(Object)this, ctx.getModelSet())); - } + @Inject(method = "<init>", at = @At("TAIL")) + private void addAltiora(EntityRendererProvider.Context ctx, boolean bl, CallbackInfo ci) { + this.addLayer(new AltioraLayer<>((PlayerRenderer) (Object) this, ctx.getModelSet())); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/network/FabricPacketHandler.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/network/FabricPacketHandler.java index 3a6b1af179..db8d2aca3d 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/network/FabricPacketHandler.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/network/FabricPacketHandler.java @@ -1,6 +1,8 @@ package at.petrak.hexcasting.fabric.network; import at.petrak.hexcasting.common.msgs.*; +import java.util.function.Consumer; +import java.util.function.Function; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.network.FriendlyByteBuf; @@ -8,45 +10,55 @@ import net.minecraft.server.level.ServerPlayer; import org.apache.logging.log4j.util.TriConsumer; -import java.util.function.Consumer; -import java.util.function.Function; - public class FabricPacketHandler { - public static void init() { - ServerPlayNetworking.registerGlobalReceiver(MsgNewSpellPatternC2S.ID, - makeServerBoundHandler(MsgNewSpellPatternC2S::deserialize, MsgNewSpellPatternC2S::handle)); - ServerPlayNetworking.registerGlobalReceiver( - MsgShiftScrollC2S.ID, makeServerBoundHandler(MsgShiftScrollC2S::deserialize, MsgShiftScrollC2S::handle)); - } + public static void init() { + ServerPlayNetworking.registerGlobalReceiver( + MsgNewSpellPatternC2S.ID, + makeServerBoundHandler(MsgNewSpellPatternC2S::deserialize, MsgNewSpellPatternC2S::handle)); + ServerPlayNetworking.registerGlobalReceiver( + MsgShiftScrollC2S.ID, + makeServerBoundHandler(MsgShiftScrollC2S::deserialize, MsgShiftScrollC2S::handle)); + } - private static <T> ServerPlayNetworking.PlayChannelHandler makeServerBoundHandler( - Function<FriendlyByteBuf, T> decoder, TriConsumer<T, MinecraftServer, ServerPlayer> handle) { - return (server, player, _handler, buf, _responseSender) -> handle.accept(decoder.apply(buf), server, player); - } + private static <T> ServerPlayNetworking.PlayChannelHandler makeServerBoundHandler( + Function<FriendlyByteBuf, T> decoder, TriConsumer<T, MinecraftServer, ServerPlayer> handle) { + return (server, player, _handler, buf, _responseSender) -> + handle.accept(decoder.apply(buf), server, player); + } - public static void initClient() { - ClientPlayNetworking.registerGlobalReceiver(MsgNewSpellPatternS2C.ID, - makeClientBoundHandler(MsgNewSpellPatternS2C::deserialize, MsgNewSpellPatternS2C::handle)); - ClientPlayNetworking.registerGlobalReceiver( - MsgBlinkS2C.ID, makeClientBoundHandler(MsgBlinkS2C::deserialize, MsgBlinkS2C::handle)); - ClientPlayNetworking.registerGlobalReceiver(MsgCastParticleS2C.ID, - makeClientBoundHandler(MsgCastParticleS2C::deserialize, MsgCastParticleS2C::handle)); - ClientPlayNetworking.registerGlobalReceiver(MsgOpenSpellGuiS2C.ID, - makeClientBoundHandler(MsgOpenSpellGuiS2C::deserialize, MsgOpenSpellGuiS2C::handle)); - ClientPlayNetworking.registerGlobalReceiver(MsgBeepS2C.ID, - makeClientBoundHandler(MsgBeepS2C::deserialize, MsgBeepS2C::handle)); - ClientPlayNetworking.registerGlobalReceiver(MsgNewWallScrollS2C.ID, - makeClientBoundHandler(MsgNewWallScrollS2C::deserialize, MsgNewWallScrollS2C::handle)); - ClientPlayNetworking.registerGlobalReceiver(MsgRecalcWallScrollDisplayS2C.ID, - makeClientBoundHandler(MsgRecalcWallScrollDisplayS2C::deserialize, MsgRecalcWallScrollDisplayS2C::handle)); - ClientPlayNetworking.registerGlobalReceiver(MsgNewSpiralPatternsS2C.ID, - makeClientBoundHandler(MsgNewSpiralPatternsS2C::deserialize, MsgNewSpiralPatternsS2C::handle)); - ClientPlayNetworking.registerGlobalReceiver(MsgClearSpiralPatternsS2C.ID, - makeClientBoundHandler(MsgClearSpiralPatternsS2C::deserialize, MsgClearSpiralPatternsS2C::handle)); - } + public static void initClient() { + ClientPlayNetworking.registerGlobalReceiver( + MsgNewSpellPatternS2C.ID, + makeClientBoundHandler(MsgNewSpellPatternS2C::deserialize, MsgNewSpellPatternS2C::handle)); + ClientPlayNetworking.registerGlobalReceiver( + MsgBlinkS2C.ID, makeClientBoundHandler(MsgBlinkS2C::deserialize, MsgBlinkS2C::handle)); + ClientPlayNetworking.registerGlobalReceiver( + MsgCastParticleS2C.ID, + makeClientBoundHandler(MsgCastParticleS2C::deserialize, MsgCastParticleS2C::handle)); + ClientPlayNetworking.registerGlobalReceiver( + MsgOpenSpellGuiS2C.ID, + makeClientBoundHandler(MsgOpenSpellGuiS2C::deserialize, MsgOpenSpellGuiS2C::handle)); + ClientPlayNetworking.registerGlobalReceiver( + MsgBeepS2C.ID, makeClientBoundHandler(MsgBeepS2C::deserialize, MsgBeepS2C::handle)); + ClientPlayNetworking.registerGlobalReceiver( + MsgNewWallScrollS2C.ID, + makeClientBoundHandler(MsgNewWallScrollS2C::deserialize, MsgNewWallScrollS2C::handle)); + ClientPlayNetworking.registerGlobalReceiver( + MsgRecalcWallScrollDisplayS2C.ID, + makeClientBoundHandler( + MsgRecalcWallScrollDisplayS2C::deserialize, MsgRecalcWallScrollDisplayS2C::handle)); + ClientPlayNetworking.registerGlobalReceiver( + MsgNewSpiralPatternsS2C.ID, + makeClientBoundHandler( + MsgNewSpiralPatternsS2C::deserialize, MsgNewSpiralPatternsS2C::handle)); + ClientPlayNetworking.registerGlobalReceiver( + MsgClearSpiralPatternsS2C.ID, + makeClientBoundHandler( + MsgClearSpiralPatternsS2C::deserialize, MsgClearSpiralPatternsS2C::handle)); + } - private static <T> ClientPlayNetworking.PlayChannelHandler makeClientBoundHandler( - Function<FriendlyByteBuf, T> decoder, Consumer<T> handler) { - return (_client, _handler, buf, _responseSender) -> handler.accept(decoder.apply(buf)); - } + private static <T> ClientPlayNetworking.PlayChannelHandler makeClientBoundHandler( + Function<FriendlyByteBuf, T> decoder, Consumer<T> handler) { + return (_client, _handler, buf, _responseSender) -> handler.accept(decoder.apply(buf)); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/recipe/FabricModConditionalIngredient.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/recipe/FabricModConditionalIngredient.java index a25fdea847..1dfba7f0c8 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/recipe/FabricModConditionalIngredient.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/recipe/FabricModConditionalIngredient.java @@ -1,114 +1,116 @@ package at.petrak.hexcasting.fabric.recipe; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import io.github.tropheusj.serialization_hooks.ingredient.BaseCustomIngredient; import io.github.tropheusj.serialization_hooks.ingredient.IngredientDeserializer; +import java.util.Arrays; +import java.util.Objects; +import javax.annotation.Nullable; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import org.jetbrains.annotations.NotNull; -import javax.annotation.Nullable; -import java.util.Arrays; -import java.util.Objects; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class FabricModConditionalIngredient extends BaseCustomIngredient { - public static final ResourceLocation ID = modLoc("mod_conditional"); - - private final Ingredient main; - private final String modid; - private final Ingredient ifModLoaded; - - private final Ingredient toUse; - - protected FabricModConditionalIngredient(Ingredient main, String modid, Ingredient ifModLoaded) { - super(IXplatAbstractions.INSTANCE.isModPresent(modid) ? Arrays.stream(ifModLoaded.values) : Arrays.stream(main.values)); - this.main = main; - this.modid = modid; - this.ifModLoaded = ifModLoaded; - - this.toUse = IXplatAbstractions.INSTANCE.isModPresent(modid) ? ifModLoaded : main; - } - - /** - * Creates a new ingredient matching the given stack - */ - public static FabricModConditionalIngredient of(Ingredient main, String modid, Ingredient ifModLoaded) { - return new FabricModConditionalIngredient(main, modid, ifModLoaded); - } - - @Override - public boolean test(@Nullable ItemStack input) { - return toUse.test(input); - } - - @Override - public @NotNull JsonElement toJson() { - JsonObject json = new JsonObject(); - json.addProperty("type", Objects.toString(ID)); - json.add("default", main.toJson()); - json.addProperty("modid", modid); - json.add("if_loaded", ifModLoaded.toJson()); - return json; - } - - @Override - public IngredientDeserializer getDeserializer() { - return Deserializer.INSTANCE; - } - - public static Ingredient fromNetwork(FriendlyByteBuf friendlyByteBuf) { - return Ingredient.fromNetwork(friendlyByteBuf); // Just send the actual ingredient - } - - public static Ingredient fromJson(JsonElement element) { - if (element == null || element.isJsonNull() || !element.isJsonObject()) - return null; - - JsonObject object = element.getAsJsonObject(); - - if (object.has("type") && object.getAsJsonPrimitive("type").getAsString().equals(ID.toString())) { - if (object.has("modid") && IXplatAbstractions.INSTANCE.isModPresent(object.getAsJsonPrimitive("modid").getAsString())) { - try { - Ingredient ingredient = Ingredient.fromJson(object.get("if_loaded")); - if (!ingredient.isEmpty()) { - return ingredient; - } - } catch (JsonParseException e) { - // NO-OP - } - } - - return Ingredient.fromJson(object.get("default")); - } - - return null; - } - - @Override - public void toNetwork(@NotNull FriendlyByteBuf friendlyByteBuf) { - friendlyByteBuf.writeResourceLocation(ID); - toUse.toNetwork(friendlyByteBuf); - } - - public static class Deserializer implements IngredientDeserializer { - public static final Deserializer INSTANCE = new Deserializer(); - - @Override - public Ingredient fromNetwork(FriendlyByteBuf buffer) { - return FabricModConditionalIngredient.fromNetwork(buffer); - } - - @Nullable - @Override - public Ingredient fromJson(JsonObject object) { - return FabricModConditionalIngredient.fromJson(object); - } - } + public static final ResourceLocation ID = modLoc("mod_conditional"); + + private final Ingredient main; + private final String modid; + private final Ingredient ifModLoaded; + + private final Ingredient toUse; + + protected FabricModConditionalIngredient(Ingredient main, String modid, Ingredient ifModLoaded) { + super( + IXplatAbstractions.INSTANCE.isModPresent(modid) + ? Arrays.stream(ifModLoaded.values) + : Arrays.stream(main.values)); + this.main = main; + this.modid = modid; + this.ifModLoaded = ifModLoaded; + + this.toUse = IXplatAbstractions.INSTANCE.isModPresent(modid) ? ifModLoaded : main; + } + + /** Creates a new ingredient matching the given stack */ + public static FabricModConditionalIngredient of( + Ingredient main, String modid, Ingredient ifModLoaded) { + return new FabricModConditionalIngredient(main, modid, ifModLoaded); + } + + @Override + public boolean test(@Nullable ItemStack input) { + return toUse.test(input); + } + + @Override + public @NotNull JsonElement toJson() { + JsonObject json = new JsonObject(); + json.addProperty("type", Objects.toString(ID)); + json.add("default", main.toJson()); + json.addProperty("modid", modid); + json.add("if_loaded", ifModLoaded.toJson()); + return json; + } + + @Override + public IngredientDeserializer getDeserializer() { + return Deserializer.INSTANCE; + } + + public static Ingredient fromNetwork(FriendlyByteBuf friendlyByteBuf) { + return Ingredient.fromNetwork(friendlyByteBuf); // Just send the actual ingredient + } + + public static Ingredient fromJson(JsonElement element) { + if (element == null || element.isJsonNull() || !element.isJsonObject()) return null; + + JsonObject object = element.getAsJsonObject(); + + if (object.has("type") + && object.getAsJsonPrimitive("type").getAsString().equals(ID.toString())) { + if (object.has("modid") + && IXplatAbstractions.INSTANCE.isModPresent( + object.getAsJsonPrimitive("modid").getAsString())) { + try { + Ingredient ingredient = Ingredient.fromJson(object.get("if_loaded")); + if (!ingredient.isEmpty()) { + return ingredient; + } + } catch (JsonParseException e) { + // NO-OP + } + } + + return Ingredient.fromJson(object.get("default")); + } + + return null; + } + + @Override + public void toNetwork(@NotNull FriendlyByteBuf friendlyByteBuf) { + friendlyByteBuf.writeResourceLocation(ID); + toUse.toNetwork(friendlyByteBuf); + } + + public static class Deserializer implements IngredientDeserializer { + public static final Deserializer INSTANCE = new Deserializer(); + + @Override + public Ingredient fromNetwork(FriendlyByteBuf buffer) { + return FabricModConditionalIngredient.fromNetwork(buffer); + } + + @Nullable @Override + public Ingredient fromJson(JsonObject object) { + return FabricModConditionalIngredient.fromJson(object); + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/recipe/FabricUnsealedIngredient.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/recipe/FabricUnsealedIngredient.java index 267b7e8ebe..46dc11607b 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/recipe/FabricUnsealedIngredient.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/recipe/FabricUnsealedIngredient.java @@ -1,11 +1,16 @@ package at.petrak.hexcasting.fabric.recipe; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.item.IotaHolderItem; import at.petrak.hexcasting.api.utils.NBTHelper; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.github.tropheusj.serialization_hooks.ingredient.BaseCustomIngredient; import io.github.tropheusj.serialization_hooks.ingredient.IngredientDeserializer; +import java.util.Objects; +import java.util.stream.Stream; +import javax.annotation.Nullable; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; @@ -14,93 +19,85 @@ import net.minecraft.world.item.crafting.ShapedRecipe; import org.jetbrains.annotations.NotNull; -import javax.annotation.Nullable; -import java.util.Objects; -import java.util.stream.Stream; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class FabricUnsealedIngredient extends BaseCustomIngredient { - public static final ResourceLocation ID = modLoc("unsealed"); - - private final ItemStack stack; - - private static ItemStack createStack(ItemStack base) { - ItemStack newStack = base.copy(); - NBTHelper.putString(newStack, IotaHolderItem.TAG_OVERRIDE_VISUALLY, "any"); - return newStack; - } - - protected FabricUnsealedIngredient(ItemStack stack) { - super(Stream.of(new Ingredient.ItemValue(createStack(stack)))); - this.stack = stack; - } - - /** - * Creates a new ingredient matching the given stack - */ - public static FabricUnsealedIngredient of(ItemStack stack) { - return new FabricUnsealedIngredient(stack); - } - - @Override - public boolean test(@Nullable ItemStack input) { - if (input == null) { - return false; - } - - return false; - } - - @Override - public @NotNull JsonElement toJson() { - JsonObject json = new JsonObject(); - json.addProperty("type", Objects.toString(ID)); - json.addProperty("item", Objects.toString(BuiltInRegistries.ITEM.getKey(this.stack.getItem()))); - return json; - } - - @Override - public IngredientDeserializer getDeserializer() { - return Deserializer.INSTANCE; - } - - public static Ingredient fromNetwork(FriendlyByteBuf friendlyByteBuf) { - return new FabricUnsealedIngredient(friendlyByteBuf.readItem()); - } - - public static Ingredient fromJson(JsonElement element) { - if (element == null || element.isJsonNull() || !element.isJsonObject()) { - return null; - } - - JsonObject object = element.getAsJsonObject(); - - if (object.has("type") && object.getAsJsonPrimitive("type").getAsString().equals(ID.toString())) { - return new FabricUnsealedIngredient(new ItemStack(ShapedRecipe.itemFromJson(object))); - } - - return null; - } - - @Override - public void toNetwork(FriendlyByteBuf friendlyByteBuf) { - friendlyByteBuf.writeResourceLocation(ID); - friendlyByteBuf.writeItem(stack); - } - - public static class Deserializer implements IngredientDeserializer { - public static final Deserializer INSTANCE = new Deserializer(); - - @Override - public Ingredient fromNetwork(FriendlyByteBuf buffer) { - return FabricUnsealedIngredient.fromNetwork(buffer); - } - - @Nullable - @Override - public Ingredient fromJson(JsonObject object) { - return FabricUnsealedIngredient.fromJson(object); - } - } + public static final ResourceLocation ID = modLoc("unsealed"); + + private final ItemStack stack; + + private static ItemStack createStack(ItemStack base) { + ItemStack newStack = base.copy(); + NBTHelper.putString(newStack, IotaHolderItem.TAG_OVERRIDE_VISUALLY, "any"); + return newStack; + } + + protected FabricUnsealedIngredient(ItemStack stack) { + super(Stream.of(new Ingredient.ItemValue(createStack(stack)))); + this.stack = stack; + } + + /** Creates a new ingredient matching the given stack */ + public static FabricUnsealedIngredient of(ItemStack stack) { + return new FabricUnsealedIngredient(stack); + } + + @Override + public boolean test(@Nullable ItemStack input) { + if (input == null) { + return false; + } + + return false; + } + + @Override + public @NotNull JsonElement toJson() { + JsonObject json = new JsonObject(); + json.addProperty("type", Objects.toString(ID)); + json.addProperty("item", Objects.toString(BuiltInRegistries.ITEM.getKey(this.stack.getItem()))); + return json; + } + + @Override + public IngredientDeserializer getDeserializer() { + return Deserializer.INSTANCE; + } + + public static Ingredient fromNetwork(FriendlyByteBuf friendlyByteBuf) { + return new FabricUnsealedIngredient(friendlyByteBuf.readItem()); + } + + public static Ingredient fromJson(JsonElement element) { + if (element == null || element.isJsonNull() || !element.isJsonObject()) { + return null; + } + + JsonObject object = element.getAsJsonObject(); + + if (object.has("type") + && object.getAsJsonPrimitive("type").getAsString().equals(ID.toString())) { + return new FabricUnsealedIngredient(new ItemStack(ShapedRecipe.itemFromJson(object))); + } + + return null; + } + + @Override + public void toNetwork(FriendlyByteBuf friendlyByteBuf) { + friendlyByteBuf.writeResourceLocation(ID); + friendlyByteBuf.writeItem(stack); + } + + public static class Deserializer implements IngredientDeserializer { + public static final Deserializer INSTANCE = new Deserializer(); + + @Override + public Ingredient fromNetwork(FriendlyByteBuf buffer) { + return FabricUnsealedIngredient.fromNetwork(buffer); + } + + @Nullable @Override + public Ingredient fromJson(JsonObject object) { + return FabricUnsealedIngredient.fromJson(object); + } + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/storage/FabricImpetusStorage.kt b/Fabric/src/main/java/at/petrak/hexcasting/fabric/storage/FabricImpetusStorage.kt index 3b8acafb58..02388ca452 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/storage/FabricImpetusStorage.kt +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/storage/FabricImpetusStorage.kt @@ -9,61 +9,75 @@ import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext import net.minecraft.world.item.ItemStack @Suppress("UnstableApiUsage") -class FabricImpetusStorage(val impetus: BlockEntityAbstractImpetus) : SingleSlotStorage<ItemVariant> { - companion object { - fun registerStorage() { - ItemStorage.SIDED.registerForBlocks({ _, _, _, blockEntity, _ -> - (blockEntity as? BlockEntityAbstractImpetus)?.let(::FabricImpetusStorage) - }, HexBlocks.IMPETUS_RIGHTCLICK, HexBlocks.IMPETUS_LOOK, HexBlocks.IMPETUS_REDSTONE) - } - } +class FabricImpetusStorage(val impetus: BlockEntityAbstractImpetus) : + SingleSlotStorage<ItemVariant> { + companion object { + fun registerStorage() { + ItemStorage.SIDED.registerForBlocks( + { _, _, _, blockEntity, _ -> + (blockEntity as? BlockEntityAbstractImpetus)?.let(::FabricImpetusStorage) + }, + HexBlocks.IMPETUS_RIGHTCLICK, + HexBlocks.IMPETUS_LOOK, + HexBlocks.IMPETUS_REDSTONE + ) + } + } - override fun insert(resource: ItemVariant, maxAmount: Long, transaction: TransactionContext): Long { - val stackCount = maxAmount / 64 - val remainder = (maxAmount % 64).toInt() - var mediaToTake = impetus.remainingMediaCapacity() - var itemsConsumed = 0L + override fun insert( + resource: ItemVariant, + maxAmount: Long, + transaction: TransactionContext + ): Long { + val stackCount = maxAmount / 64 + val remainder = (maxAmount % 64).toInt() + var mediaToTake = impetus.remainingMediaCapacity() + var itemsConsumed = 0L - fun insertStack(stack: ItemStack, transaction: TransactionContext) { - val copied = stack.copy() - val size = stack.count - val extractable = impetus.extractMediaFromInsertedItem(stack, false) - mediaToTake -= extractable - val taken = size - stack.count - itemsConsumed += taken.toLong() - copied.count = taken + fun insertStack(stack: ItemStack, transaction: TransactionContext) { + val copied = stack.copy() + val size = stack.count + val extractable = impetus.extractMediaFromInsertedItem(stack, false) + mediaToTake -= extractable + val taken = size - stack.count + itemsConsumed += taken.toLong() + copied.count = taken - if (taken > 0) { - transaction.addOuterCloseCallback { - if (it.wasCommitted()) { - impetus.insertMedia(copied) - } - } - } - } - for (i in 0 until stackCount) { - val stack = resource.toStack(64) - insertStack(stack, transaction) - if (mediaToTake <= 0) { - return itemsConsumed - } - } - if (remainder > 0) { - val remainderStack = resource.toStack(remainder) - insertStack(remainderStack, transaction) - } - return itemsConsumed - } + if (taken > 0) { + transaction.addOuterCloseCallback { + if (it.wasCommitted()) { + impetus.insertMedia(copied) + } + } + } + } + for (i in 0 until stackCount) { + val stack = resource.toStack(64) + insertStack(stack, transaction) + if (mediaToTake <= 0) { + return itemsConsumed + } + } + if (remainder > 0) { + val remainderStack = resource.toStack(remainder) + insertStack(remainderStack, transaction) + } + return itemsConsumed + } - override fun supportsExtraction(): Boolean = false + override fun supportsExtraction(): Boolean = false - override fun extract(resource: ItemVariant, maxAmount: Long, transaction: TransactionContext): Long = 0 + override fun extract( + resource: ItemVariant, + maxAmount: Long, + transaction: TransactionContext + ): Long = 0 - override fun isResourceBlank(): Boolean = true + override fun isResourceBlank(): Boolean = true - override fun getResource(): ItemVariant = ItemVariant.blank() + override fun getResource(): ItemVariant = ItemVariant.blank() - override fun getAmount(): Long = 0 + override fun getAmount(): Long = 0 - override fun getCapacity(): Long = 64 + override fun getCapacity(): Long = 64 } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricClientXplatImpl.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricClientXplatImpl.java index c5738b03f3..6fb5fa7c19 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricClientXplatImpl.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricClientXplatImpl.java @@ -31,71 +31,73 @@ import org.jetbrains.annotations.Nullable; public class FabricClientXplatImpl implements IClientXplatAbstractions { - @Override - public void sendPacketToServer(IMessage packet) { - ClientPlayNetworking.send(packet.getFabricId(), packet.toBuf()); - } + @Override + public void sendPacketToServer(IMessage packet) { + ClientPlayNetworking.send(packet.getFabricId(), packet.toBuf()); + } - @Override - public void setRenderLayer(Block block, RenderType type) { - BlockRenderLayerMap.INSTANCE.putBlock(block, type); - } + @Override + public void setRenderLayer(Block block, RenderType type) { + BlockRenderLayerMap.INSTANCE.putBlock(block, type); + } - @Override - public void initPlatformSpecific() { - if (IXplatAbstractions.INSTANCE.isModPresent(HexInterop.Fabric.TRINKETS_API_ID)) { - TrinketsApiInterop.clientInit(); - } - } + @Override + public void initPlatformSpecific() { + if (IXplatAbstractions.INSTANCE.isModPresent(HexInterop.Fabric.TRINKETS_API_ID)) { + TrinketsApiInterop.clientInit(); + } + } - @Override - public <T extends Entity> void registerEntityRenderer(EntityType<? extends T> type, - EntityRendererProvider<T> renderer) { - EntityRendererRegistry.register(type, renderer); - } + @Override + public <T extends Entity> void registerEntityRenderer( + EntityType<? extends T> type, EntityRendererProvider<T> renderer) { + EntityRendererRegistry.register(type, renderer); + } - // suck it fabric trying to be "safe" - private record UnclampedClampedItemPropFunc(ItemPropertyFunction inner) implements ClampedItemPropertyFunction { - @Override - public float unclampedCall(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, - int seed) { - return inner.call(stack, level, entity, seed); - } + // suck it fabric trying to be "safe" + private record UnclampedClampedItemPropFunc(ItemPropertyFunction inner) + implements ClampedItemPropertyFunction { + @Override + public float unclampedCall( + ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) { + return inner.call(stack, level, entity, seed); + } - @Override - public float call(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) { - return this.unclampedCall(stack, level, entity, seed); - } - } + @Override + public float call( + ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) { + return this.unclampedCall(stack, level, entity, seed); + } + } - @Override - public void registerItemProperty(Item item, ResourceLocation id, ItemPropertyFunction func) { - ItemProperties.register(item, id, new UnclampedClampedItemPropFunc(func)); - } + @Override + public void registerItemProperty(Item item, ResourceLocation id, ItemPropertyFunction func) { + ItemProperties.register(item, id, new UnclampedClampedItemPropFunc(func)); + } - @Override - public ClientCastingStack getClientCastingStack(Player player) { - return HexCardinalComponents.CLIENT_CASTING_STACK.get(player).getClientCastingStack(); - } + @Override + public ClientCastingStack getClientCastingStack(Player player) { + return HexCardinalComponents.CLIENT_CASTING_STACK.get(player).getClientCastingStack(); + } - @Override - public void setFilterSave(AbstractTexture texture, boolean filter, boolean mipmap) { - ((ExtendedTexture) texture).setFilterSave(filter, mipmap); - } + @Override + public void setFilterSave(AbstractTexture texture, boolean filter, boolean mipmap) { + ((ExtendedTexture) texture).setFilterSave(filter, mipmap); + } - @Override - public void restoreLastFilter(AbstractTexture texture) { - ((ExtendedTexture) texture).restoreLastFilter(); - } + @Override + public void restoreLastFilter(AbstractTexture texture) { + ((ExtendedTexture) texture).restoreLastFilter(); + } - // Set by FabricLevelRendererMixin - public static Frustum LEVEL_RENDERER_FRUSTUM = null; + // Set by FabricLevelRendererMixin + public static Frustum LEVEL_RENDERER_FRUSTUM = null; - @Override - public boolean fabricAdditionalQuenchFrustumCheck(AABB aabb) { - if (LEVEL_RENDERER_FRUSTUM == null) { - return true; // fail safe - } - return LEVEL_RENDERER_FRUSTUM.isVisible(aabb); - } + @Override + public boolean fabricAdditionalQuenchFrustumCheck(AABB aabb) { + if (LEVEL_RENDERER_FRUSTUM == null) { + return true; // fail safe + } + return LEVEL_RENDERER_FRUSTUM.isVisible(aabb); + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricXplatImpl.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricXplatImpl.java index da6a443908..e92bedd07e 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricXplatImpl.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/xplat/FabricXplatImpl.java @@ -33,6 +33,12 @@ import at.petrak.hexcasting.xplat.Platform; import com.google.common.base.Suppliers; import com.mojang.serialization.Lifecycle; +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.Supplier; +import java.util.stream.Stream; import net.fabricmc.api.EnvType; import net.fabricmc.fabric.api.entity.FakePlayer; import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents; @@ -81,447 +87,456 @@ import org.jetbrains.annotations.Nullable; import virtuoel.pehkui.api.ScaleTypes; -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import java.util.function.BiFunction; -import java.util.function.Supplier; -import java.util.stream.Stream; - public class FabricXplatImpl implements IXplatAbstractions { - @Override - public Platform platform() { - return Platform.FABRIC; - } - - @Override - public boolean isPhysicalClient() { - return FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT; - } - - @Override - public boolean isModPresent(String id) { - return FabricLoader.getInstance().isModLoaded(id); - } - - @Override - public void initPlatformSpecific() { - if (this.isModPresent(HexInterop.Fabric.TRINKETS_API_ID)) { - TrinketsApiInterop.init(); - } - } - -// @Override -// public double getReachDistance(Player player) { -// return ReachEntityAttributes.getReachDistance(player, 5.0); -// } - - @Override - public void sendPacketToPlayer(ServerPlayer target, IMessage packet) { - ServerPlayNetworking.send(target, packet.getFabricId(), packet.toBuf()); - } - - @Override - public void sendPacketNear(Vec3 pos, double radius, ServerLevel dimension, IMessage packet) { - sendPacketToPlayers(PlayerLookup.around(dimension, pos, radius), packet); - } - - @Override - public void sendPacketTracking(Entity entity, IMessage packet) { - sendPacketToPlayers(PlayerLookup.tracking(entity), packet); - } - - private void sendPacketToPlayers(Collection<ServerPlayer> players, IMessage packet) { - var pkt = ServerPlayNetworking.createS2CPacket(packet.getFabricId(), packet.toBuf()); - for (var p : players) { - p.connection.send(pkt); - } - } - - @Override - public Packet<ClientGamePacketListener> toVanillaClientboundPacket(IMessage message) { - return ServerPlayNetworking.createS2CPacket(message.getFabricId(), message.toBuf()); - } - - @Override - public void setBrainsweepAddlData(Mob mob) { - var cc = HexCardinalComponents.BRAINSWEPT.get(mob); - cc.setBrainswept(true); - // CC API does the syncing for us - } - - @Override - public @Nullable FrozenPigment setPigment(Player target, @Nullable FrozenPigment pigment) { - var cc = HexCardinalComponents.FAVORED_PIGMENT.get(target); - var old = cc.getPigment(); - cc.setPigment(pigment); - return old; - } - - @Override - public void setSentinel(Player target, @Nullable Sentinel sentinel) { - var cc = HexCardinalComponents.SENTINEL.get(target); - cc.setSentinel(sentinel); - } - - @Override - public void setFlight(ServerPlayer target, FlightAbility flight) { - var cc = HexCardinalComponents.FLIGHT.get(target); - cc.setFlight(flight); - } - - public void setAltiora(Player target, @Nullable AltioraAbility altiora) { - var cc = HexCardinalComponents.ALTIORA.get(target); - cc.setAltiora(altiora); - } - - public void setStaffcastImage(ServerPlayer target, CastingImage image) { - var cc = HexCardinalComponents.STAFFCAST_IMAGE.get(target); - cc.setImage(image); - } - - @Override - public void setPatterns(ServerPlayer target, List<ResolvedPattern> patterns) { - var cc = HexCardinalComponents.PATTERNS.get(target); - cc.setPatterns(patterns); - } - - @Override - public boolean isBrainswept(Mob mob) { - var cc = HexCardinalComponents.BRAINSWEPT.get(mob); - return cc.isBrainswept(); - } - - @Override - public @Nullable FlightAbility getFlight(ServerPlayer player) { - var cc = HexCardinalComponents.FLIGHT.get(player); - return cc.getFlight(); - } - - @Override - public @Nullable AltioraAbility getAltiora(Player player) { - var cc = HexCardinalComponents.ALTIORA.get(player); - return cc.getAltiora(); - } - - @Override - public FrozenPigment getPigment(Player player) { - var cc = HexCardinalComponents.FAVORED_PIGMENT.get(player); - return cc.getPigment(); - } - - @Override - public Sentinel getSentinel(Player player) { - var cc = HexCardinalComponents.SENTINEL.get(player); - return cc.getSentinel(); - } - - @Override - public CastingVM getStaffcastVM(ServerPlayer player, InteractionHand hand) { - var cc = HexCardinalComponents.STAFFCAST_IMAGE.get(player); - return cc.getVM(hand); - } - - @Override - public List<ResolvedPattern> getPatternsSavedInUi(ServerPlayer player) { - var cc = HexCardinalComponents.PATTERNS.get(player); - return cc.getPatterns(); - } - - @Override - public void clearCastingData(ServerPlayer player) { - this.setStaffcastImage(player, null); - this.setPatterns(player, List.of()); - } - - @Override - public @Nullable - ADMediaHolder findMediaHolder(ItemStack stack) { - var cc = HexCardinalComponents.MEDIA_HOLDER.maybeGet(stack); - return cc.orElse(null); - } - - @Override - public @Nullable ADMediaHolder findMediaHolder(ServerPlayer player) { - var cc = HexCardinalComponents.MEDIA_HOLDER.maybeGet(player); - return cc.orElse(null); - } - - @Override - public @Nullable - ADIotaHolder findDataHolder(ItemStack stack) { - var cc = HexCardinalComponents.IOTA_HOLDER.maybeGet(stack); - return cc.orElse(null); - } - - @Override - public @Nullable - ADIotaHolder findDataHolder(Entity entity) { - var cc = HexCardinalComponents.IOTA_HOLDER.maybeGet(entity); - return cc.orElse(null); - } - - @Override - public @Nullable - ADHexHolder findHexHolder(ItemStack stack) { - var cc = HexCardinalComponents.HEX_HOLDER.maybeGet(stack); - return cc.orElse(null); - } - - @Override - public @Nullable ADVariantItem findVariantHolder(ItemStack stack) { - var cc = HexCardinalComponents.VARIANT_ITEM.maybeGet(stack); - return cc.orElse(null); - } - - @Override - public boolean isPigment(ItemStack stack) { - return HexCardinalComponents.PIGMENT.isProvidedBy(stack); - } - - @Override - public ColorProvider getColorProvider(FrozenPigment pigment) { - var cc = HexCardinalComponents.PIGMENT.maybeGet(pigment.item()); - return cc.map(col -> col.provideColor(pigment.owner())).orElse(ColorProvider.MISSING); - } - - @Override - public <T extends BlockEntity> BlockEntityType<T> createBlockEntityType(BiFunction<BlockPos, BlockState, T> func, - Block... blocks) { - return FabricBlockEntityTypeBuilder.create(func::apply, blocks).build(); - } - - @Override - @SuppressWarnings("UnstableApiUsage") - public boolean tryPlaceFluid(Level level, InteractionHand hand, BlockPos pos, Fluid fluid) { - Storage<FluidVariant> target = FluidStorage.SIDED.find(level, pos, Direction.UP); - if (target == null) { - return false; - } - try (Transaction transaction = Transaction.openOuter()) { - long insertedAmount = target.insert(FluidVariant.of(fluid), FluidConstants.BUCKET, transaction); - if (insertedAmount > 0) { - transaction.commit(); - return true; - } - } - return false; - } - - @Override - @SuppressWarnings("UnstableApiUsage") - public boolean drainAllFluid(Level level, BlockPos pos) { - Storage<FluidVariant> target = FluidStorage.SIDED.find(level, pos, Direction.UP); - if (target == null) { - return false; - } - try (Transaction transaction = Transaction.openOuter()) { - boolean any = false; - for (var view : target) { - long extracted = view.extract(view.getResource(), view.getAmount(), transaction); - if (extracted > 0) { - any = true; - } - } - - if (any) { - transaction.commit(); - return true; - } - } - return false; - } - - @Override - public Ingredient getUnsealedIngredient(ItemStack stack) { - return FabricUnsealedIngredient.of(stack); - } - - // do a stupid hack from botania - private static List<ItemStack> stacks(Item... items) { - return Stream.of(items).map(ItemStack::new).toList(); - } - - private static final List<List<ItemStack>> HARVEST_TOOLS_BY_LEVEL = List.of( - stacks(Items.WOODEN_PICKAXE, Items.WOODEN_AXE, Items.WOODEN_HOE, Items.WOODEN_SHOVEL), - stacks(Items.STONE_PICKAXE, Items.STONE_AXE, Items.STONE_HOE, Items.STONE_SHOVEL), - stacks(Items.IRON_PICKAXE, Items.IRON_AXE, Items.IRON_HOE, Items.IRON_SHOVEL), - stacks(Items.DIAMOND_PICKAXE, Items.DIAMOND_AXE, Items.DIAMOND_HOE, Items.DIAMOND_SHOVEL), - stacks(Items.NETHERITE_PICKAXE, Items.NETHERITE_AXE, Items.NETHERITE_HOE, Items.NETHERITE_SHOVEL) - ); - - @Override - public boolean isCorrectTierForDrops(Tier tier, BlockState bs) { - if (!bs.requiresCorrectToolForDrops()) { - return true; - } - - int level = HexConfig.server() - .opBreakHarvestLevelBecauseForgeThoughtItWasAGoodIdeaToImplementHarvestTiersUsingAnHonestToGodTopoSort(); - for (var tool : HARVEST_TOOLS_BY_LEVEL.get(level)) { - if (tool.isCorrectToolForDrops(bs)) { - return true; - } - } - - return false; - } - - @Override - public Item.Properties addEquipSlotFabric(EquipmentSlot slot) { - return new FabricItemSettings().equipmentSlot(s -> slot); - } - - private static final IXplatTags TAGS = new IXplatTags() { - @Override - public TagKey<Item> amethystDust() { - return HexTags.Items.create(new ResourceLocation("c", "amethyst_dusts")); - } - - @Override - public TagKey<Item> gems() { - return HexTags.Items.create(new ResourceLocation("c", "gems")); - } - }; - - @Override - public IXplatTags tags() { - return TAGS; - } - - @Override - public LootItemCondition.Builder isShearsCondition() { - return AnyOfCondition.anyOf( - MatchTool.toolMatches(ItemPredicate.Builder.item().of(Items.SHEARS)), - MatchTool.toolMatches(ItemPredicate.Builder.item().of( - HexTags.Items.create(new ResourceLocation("c", "shears")))) - ); - } - - @Override - public String getModName(String namespace) { - if (namespace.equals("c")) { - return "Common"; - } - Optional<ModContainer> container = FabricLoader.getInstance().getModContainer(namespace); - if (container.isPresent()) { - return container.get().getMetadata().getName(); - } - return namespace; - } - - private static final Supplier<Registry<ActionRegistryEntry>> ACTION_REGISTRY = Suppliers.memoize(() -> - FabricRegistryBuilder.from(new MappedRegistry<>( - HexRegistries.ACTION, - Lifecycle.stable())) - .buildAndRegister() - ); - private static final Supplier<Registry<SpecialHandler.Factory<?>>> SPECIAL_HANDLER_REGISTRY = - Suppliers.memoize(() -> - FabricRegistryBuilder.from(new MappedRegistry<>( - HexRegistries.SPECIAL_HANDLER, - Lifecycle.stable())) - .buildAndRegister() - ); - private static final Supplier<Registry<IotaType<?>>> IOTA_TYPE_REGISTRY = Suppliers.memoize(() -> - FabricRegistryBuilder.from(new DefaultedMappedRegistry<>( - HexAPI.MOD_ID + ":null", HexRegistries.IOTA_TYPE, - Lifecycle.stable(), false)) - .buildAndRegister() - ); - - private static final Supplier<Registry<Arithmetic>> ARITHMETIC_REGISTRY = Suppliers.memoize(() -> - FabricRegistryBuilder.from(new MappedRegistry<>( - HexRegistries.ARITHMETIC, - Lifecycle.stable())) - .buildAndRegister() - ); - - private static final Supplier<Registry<ContinuationFrame.Type<?>>> CONTINUATION_TYPE_REGISTRY = Suppliers.memoize(() -> - FabricRegistryBuilder.from(new DefaultedMappedRegistry<>( - HexAPI.MOD_ID + ":end", HexRegistries.CONTINUATION_TYPE, - Lifecycle.stable(), false)) - .buildAndRegister() - ); - - private static final Supplier<Registry<EvalSound>> EVAL_SOUNDS_REGISTRY = Suppliers.memoize(() -> - FabricRegistryBuilder.from(new DefaultedMappedRegistry<>( - HexAPI.MOD_ID + ":nothing", HexRegistries.EVAL_SOUND, - Lifecycle.stable(), false)) - .buildAndRegister() - ); - - @Override - public Registry<ActionRegistryEntry> getActionRegistry() { - return ACTION_REGISTRY.get(); - } - - @Override - public Registry<SpecialHandler.Factory<?>> getSpecialHandlerRegistry() { - return SPECIAL_HANDLER_REGISTRY.get(); - } - - @Override - public Registry<IotaType<?>> getIotaTypeRegistry() { - return IOTA_TYPE_REGISTRY.get(); - } - - @Override - public Registry<Arithmetic> getArithmeticRegistry() { - return ARITHMETIC_REGISTRY.get(); - } - - @Override - public Registry<ContinuationFrame.Type<?>> getContinuationTypeRegistry() { - return CONTINUATION_TYPE_REGISTRY.get(); - } - - @Override - public Registry<EvalSound> getEvalSoundRegistry() { - return EVAL_SOUNDS_REGISTRY.get(); - } - - @Override - public boolean isBreakingAllowed(ServerLevel world, BlockPos pos, BlockState state, @Nullable Player player) { - if (player == null) - player = FakePlayer.get(world, HEXCASTING); - return PlayerBlockBreakEvents.BEFORE.invoker() - .beforeBlockBreak(world, player, pos, state, world.getBlockEntity(pos)); - } - - @Override - public boolean isPlacingAllowed(ServerLevel world, BlockPos pos, ItemStack blockStack, @Nullable Player player) { - if (player == null) - player = FakePlayer.get(world, HEXCASTING); - ItemStack cached = player.getMainHandItem(); - player.setItemInHand(InteractionHand.MAIN_HAND, blockStack.copy()); - var success = UseItemCallback.EVENT.invoker().interact(player, world, InteractionHand.MAIN_HAND); - player.setItemInHand(InteractionHand.MAIN_HAND, cached); - return success.getResult() == InteractionResult.PASS; // No other mod tried to consume this - } - - private static PehkuiInterop.ApiAbstraction PEHKUI_API = null; - - @Override - public PehkuiInterop.ApiAbstraction getPehkuiApi() { - if (!this.isModPresent(HexInterop.PEHKUI_ID)) { - throw new IllegalArgumentException("cannot get the pehkui api without pehkui"); - } - - if (PEHKUI_API == null) { - PEHKUI_API = new PehkuiInterop.ApiAbstraction() { - @Override - public float getScale(Entity e) { - return ScaleTypes.BASE.getScaleData(e).getScale(); - } - - @Override - public void setScale(Entity e, float scale) { - ScaleTypes.BASE.getScaleData(e).setScale(scale); - } - }; - } - return PEHKUI_API; - } - + @Override + public Platform platform() { + return Platform.FABRIC; + } + + @Override + public boolean isPhysicalClient() { + return FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT; + } + + @Override + public boolean isModPresent(String id) { + return FabricLoader.getInstance().isModLoaded(id); + } + + @Override + public void initPlatformSpecific() { + if (this.isModPresent(HexInterop.Fabric.TRINKETS_API_ID)) { + TrinketsApiInterop.init(); + } + } + + // @Override + // public double getReachDistance(Player player) { + // return ReachEntityAttributes.getReachDistance(player, 5.0); + // } + + @Override + public void sendPacketToPlayer(ServerPlayer target, IMessage packet) { + ServerPlayNetworking.send(target, packet.getFabricId(), packet.toBuf()); + } + + @Override + public void sendPacketNear(Vec3 pos, double radius, ServerLevel dimension, IMessage packet) { + sendPacketToPlayers(PlayerLookup.around(dimension, pos, radius), packet); + } + + @Override + public void sendPacketTracking(Entity entity, IMessage packet) { + sendPacketToPlayers(PlayerLookup.tracking(entity), packet); + } + + private void sendPacketToPlayers(Collection<ServerPlayer> players, IMessage packet) { + var pkt = ServerPlayNetworking.createS2CPacket(packet.getFabricId(), packet.toBuf()); + for (var p : players) { + p.connection.send(pkt); + } + } + + @Override + public Packet<ClientGamePacketListener> toVanillaClientboundPacket(IMessage message) { + return ServerPlayNetworking.createS2CPacket(message.getFabricId(), message.toBuf()); + } + + @Override + public void setBrainsweepAddlData(Mob mob) { + var cc = HexCardinalComponents.BRAINSWEPT.get(mob); + cc.setBrainswept(true); + // CC API does the syncing for us + } + + @Override + public @Nullable FrozenPigment setPigment(Player target, @Nullable FrozenPigment pigment) { + var cc = HexCardinalComponents.FAVORED_PIGMENT.get(target); + var old = cc.getPigment(); + cc.setPigment(pigment); + return old; + } + + @Override + public void setSentinel(Player target, @Nullable Sentinel sentinel) { + var cc = HexCardinalComponents.SENTINEL.get(target); + cc.setSentinel(sentinel); + } + + @Override + public void setFlight(ServerPlayer target, FlightAbility flight) { + var cc = HexCardinalComponents.FLIGHT.get(target); + cc.setFlight(flight); + } + + public void setAltiora(Player target, @Nullable AltioraAbility altiora) { + var cc = HexCardinalComponents.ALTIORA.get(target); + cc.setAltiora(altiora); + } + + public void setStaffcastImage(ServerPlayer target, CastingImage image) { + var cc = HexCardinalComponents.STAFFCAST_IMAGE.get(target); + cc.setImage(image); + } + + @Override + public void setPatterns(ServerPlayer target, List<ResolvedPattern> patterns) { + var cc = HexCardinalComponents.PATTERNS.get(target); + cc.setPatterns(patterns); + } + + @Override + public boolean isBrainswept(Mob mob) { + var cc = HexCardinalComponents.BRAINSWEPT.get(mob); + return cc.isBrainswept(); + } + + @Override + public @Nullable FlightAbility getFlight(ServerPlayer player) { + var cc = HexCardinalComponents.FLIGHT.get(player); + return cc.getFlight(); + } + + @Override + public @Nullable AltioraAbility getAltiora(Player player) { + var cc = HexCardinalComponents.ALTIORA.get(player); + return cc.getAltiora(); + } + + @Override + public FrozenPigment getPigment(Player player) { + var cc = HexCardinalComponents.FAVORED_PIGMENT.get(player); + return cc.getPigment(); + } + + @Override + public Sentinel getSentinel(Player player) { + var cc = HexCardinalComponents.SENTINEL.get(player); + return cc.getSentinel(); + } + + @Override + public CastingVM getStaffcastVM(ServerPlayer player, InteractionHand hand) { + var cc = HexCardinalComponents.STAFFCAST_IMAGE.get(player); + return cc.getVM(hand); + } + + @Override + public List<ResolvedPattern> getPatternsSavedInUi(ServerPlayer player) { + var cc = HexCardinalComponents.PATTERNS.get(player); + return cc.getPatterns(); + } + + @Override + public void clearCastingData(ServerPlayer player) { + this.setStaffcastImage(player, null); + this.setPatterns(player, List.of()); + } + + @Override + public @Nullable ADMediaHolder findMediaHolder(ItemStack stack) { + var cc = HexCardinalComponents.MEDIA_HOLDER.maybeGet(stack); + return cc.orElse(null); + } + + @Override + public @Nullable ADMediaHolder findMediaHolder(ServerPlayer player) { + var cc = HexCardinalComponents.MEDIA_HOLDER.maybeGet(player); + return cc.orElse(null); + } + + @Override + public @Nullable ADIotaHolder findDataHolder(ItemStack stack) { + var cc = HexCardinalComponents.IOTA_HOLDER.maybeGet(stack); + return cc.orElse(null); + } + + @Override + public @Nullable ADIotaHolder findDataHolder(Entity entity) { + var cc = HexCardinalComponents.IOTA_HOLDER.maybeGet(entity); + return cc.orElse(null); + } + + @Override + public @Nullable ADHexHolder findHexHolder(ItemStack stack) { + var cc = HexCardinalComponents.HEX_HOLDER.maybeGet(stack); + return cc.orElse(null); + } + + @Override + public @Nullable ADVariantItem findVariantHolder(ItemStack stack) { + var cc = HexCardinalComponents.VARIANT_ITEM.maybeGet(stack); + return cc.orElse(null); + } + + @Override + public boolean isPigment(ItemStack stack) { + return HexCardinalComponents.PIGMENT.isProvidedBy(stack); + } + + @Override + public ColorProvider getColorProvider(FrozenPigment pigment) { + var cc = HexCardinalComponents.PIGMENT.maybeGet(pigment.item()); + return cc.map(col -> col.provideColor(pigment.owner())).orElse(ColorProvider.MISSING); + } + + @Override + public <T extends BlockEntity> BlockEntityType<T> createBlockEntityType( + BiFunction<BlockPos, BlockState, T> func, Block... blocks) { + return FabricBlockEntityTypeBuilder.create(func::apply, blocks).build(); + } + + @Override + @SuppressWarnings("UnstableApiUsage") + public boolean tryPlaceFluid(Level level, InteractionHand hand, BlockPos pos, Fluid fluid) { + Storage<FluidVariant> target = FluidStorage.SIDED.find(level, pos, Direction.UP); + if (target == null) { + return false; + } + try (Transaction transaction = Transaction.openOuter()) { + long insertedAmount = + target.insert(FluidVariant.of(fluid), FluidConstants.BUCKET, transaction); + if (insertedAmount > 0) { + transaction.commit(); + return true; + } + } + return false; + } + + @Override + @SuppressWarnings("UnstableApiUsage") + public boolean drainAllFluid(Level level, BlockPos pos) { + Storage<FluidVariant> target = FluidStorage.SIDED.find(level, pos, Direction.UP); + if (target == null) { + return false; + } + try (Transaction transaction = Transaction.openOuter()) { + boolean any = false; + for (var view : target) { + long extracted = view.extract(view.getResource(), view.getAmount(), transaction); + if (extracted > 0) { + any = true; + } + } + + if (any) { + transaction.commit(); + return true; + } + } + return false; + } + + @Override + public Ingredient getUnsealedIngredient(ItemStack stack) { + return FabricUnsealedIngredient.of(stack); + } + + // do a stupid hack from botania + private static List<ItemStack> stacks(Item... items) { + return Stream.of(items).map(ItemStack::new).toList(); + } + + private static final List<List<ItemStack>> HARVEST_TOOLS_BY_LEVEL = + List.of( + stacks(Items.WOODEN_PICKAXE, Items.WOODEN_AXE, Items.WOODEN_HOE, Items.WOODEN_SHOVEL), + stacks(Items.STONE_PICKAXE, Items.STONE_AXE, Items.STONE_HOE, Items.STONE_SHOVEL), + stacks(Items.IRON_PICKAXE, Items.IRON_AXE, Items.IRON_HOE, Items.IRON_SHOVEL), + stacks(Items.DIAMOND_PICKAXE, Items.DIAMOND_AXE, Items.DIAMOND_HOE, Items.DIAMOND_SHOVEL), + stacks( + Items.NETHERITE_PICKAXE, + Items.NETHERITE_AXE, + Items.NETHERITE_HOE, + Items.NETHERITE_SHOVEL)); + + @Override + public boolean isCorrectTierForDrops(Tier tier, BlockState bs) { + if (!bs.requiresCorrectToolForDrops()) { + return true; + } + + int level = + HexConfig.server() + .opBreakHarvestLevelBecauseForgeThoughtItWasAGoodIdeaToImplementHarvestTiersUsingAnHonestToGodTopoSort(); + for (var tool : HARVEST_TOOLS_BY_LEVEL.get(level)) { + if (tool.isCorrectToolForDrops(bs)) { + return true; + } + } + + return false; + } + + @Override + public Item.Properties addEquipSlotFabric(EquipmentSlot slot) { + return new FabricItemSettings().equipmentSlot(s -> slot); + } + + private static final IXplatTags TAGS = + new IXplatTags() { + @Override + public TagKey<Item> amethystDust() { + return HexTags.Items.create(new ResourceLocation("c", "amethyst_dusts")); + } + + @Override + public TagKey<Item> gems() { + return HexTags.Items.create(new ResourceLocation("c", "gems")); + } + }; + + @Override + public IXplatTags tags() { + return TAGS; + } + + @Override + public LootItemCondition.Builder isShearsCondition() { + return AnyOfCondition.anyOf( + MatchTool.toolMatches(ItemPredicate.Builder.item().of(Items.SHEARS)), + MatchTool.toolMatches( + ItemPredicate.Builder.item() + .of(HexTags.Items.create(new ResourceLocation("c", "shears"))))); + } + + @Override + public String getModName(String namespace) { + if (namespace.equals("c")) { + return "Common"; + } + Optional<ModContainer> container = FabricLoader.getInstance().getModContainer(namespace); + if (container.isPresent()) { + return container.get().getMetadata().getName(); + } + return namespace; + } + + private static final Supplier<Registry<ActionRegistryEntry>> ACTION_REGISTRY = + Suppliers.memoize( + () -> + FabricRegistryBuilder.from( + new MappedRegistry<>(HexRegistries.ACTION, Lifecycle.stable())) + .buildAndRegister()); + private static final Supplier<Registry<SpecialHandler.Factory<?>>> SPECIAL_HANDLER_REGISTRY = + Suppliers.memoize( + () -> + FabricRegistryBuilder.from( + new MappedRegistry<>(HexRegistries.SPECIAL_HANDLER, Lifecycle.stable())) + .buildAndRegister()); + private static final Supplier<Registry<IotaType<?>>> IOTA_TYPE_REGISTRY = + Suppliers.memoize( + () -> + FabricRegistryBuilder.from( + new DefaultedMappedRegistry<>( + HexAPI.MOD_ID + ":null", + HexRegistries.IOTA_TYPE, + Lifecycle.stable(), + false)) + .buildAndRegister()); + + private static final Supplier<Registry<Arithmetic>> ARITHMETIC_REGISTRY = + Suppliers.memoize( + () -> + FabricRegistryBuilder.from( + new MappedRegistry<>(HexRegistries.ARITHMETIC, Lifecycle.stable())) + .buildAndRegister()); + + private static final Supplier<Registry<ContinuationFrame.Type<?>>> CONTINUATION_TYPE_REGISTRY = + Suppliers.memoize( + () -> + FabricRegistryBuilder.from( + new DefaultedMappedRegistry<>( + HexAPI.MOD_ID + ":end", + HexRegistries.CONTINUATION_TYPE, + Lifecycle.stable(), + false)) + .buildAndRegister()); + + private static final Supplier<Registry<EvalSound>> EVAL_SOUNDS_REGISTRY = + Suppliers.memoize( + () -> + FabricRegistryBuilder.from( + new DefaultedMappedRegistry<>( + HexAPI.MOD_ID + ":nothing", + HexRegistries.EVAL_SOUND, + Lifecycle.stable(), + false)) + .buildAndRegister()); + + @Override + public Registry<ActionRegistryEntry> getActionRegistry() { + return ACTION_REGISTRY.get(); + } + + @Override + public Registry<SpecialHandler.Factory<?>> getSpecialHandlerRegistry() { + return SPECIAL_HANDLER_REGISTRY.get(); + } + + @Override + public Registry<IotaType<?>> getIotaTypeRegistry() { + return IOTA_TYPE_REGISTRY.get(); + } + + @Override + public Registry<Arithmetic> getArithmeticRegistry() { + return ARITHMETIC_REGISTRY.get(); + } + + @Override + public Registry<ContinuationFrame.Type<?>> getContinuationTypeRegistry() { + return CONTINUATION_TYPE_REGISTRY.get(); + } + + @Override + public Registry<EvalSound> getEvalSoundRegistry() { + return EVAL_SOUNDS_REGISTRY.get(); + } + + @Override + public boolean isBreakingAllowed( + ServerLevel world, BlockPos pos, BlockState state, @Nullable Player player) { + if (player == null) player = FakePlayer.get(world, HEXCASTING); + return PlayerBlockBreakEvents.BEFORE + .invoker() + .beforeBlockBreak(world, player, pos, state, world.getBlockEntity(pos)); + } + + @Override + public boolean isPlacingAllowed( + ServerLevel world, BlockPos pos, ItemStack blockStack, @Nullable Player player) { + if (player == null) player = FakePlayer.get(world, HEXCASTING); + ItemStack cached = player.getMainHandItem(); + player.setItemInHand(InteractionHand.MAIN_HAND, blockStack.copy()); + var success = + UseItemCallback.EVENT.invoker().interact(player, world, InteractionHand.MAIN_HAND); + player.setItemInHand(InteractionHand.MAIN_HAND, cached); + return success.getResult() == InteractionResult.PASS; // No other mod tried to consume this + } + + private static PehkuiInterop.ApiAbstraction PEHKUI_API = null; + + @Override + public PehkuiInterop.ApiAbstraction getPehkuiApi() { + if (!this.isModPresent(HexInterop.PEHKUI_ID)) { + throw new IllegalArgumentException("cannot get the pehkui api without pehkui"); + } + + if (PEHKUI_API == null) { + PEHKUI_API = + new PehkuiInterop.ApiAbstraction() { + @Override + public float getScale(Entity e) { + return ScaleTypes.BASE.getScaleData(e).getScale(); + } + + @Override + public void setScale(Entity e, float scale) { + ScaleTypes.BASE.getScaleData(e).setScale(scale); + } + }; + } + return PEHKUI_API; + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexClientInitializer.java b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexClientInitializer.java index 30e0e2a53e..ff7457ea48 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexClientInitializer.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexClientInitializer.java @@ -12,10 +12,11 @@ import at.petrak.hexcasting.common.lib.HexParticles; import at.petrak.hexcasting.common.misc.PatternTooltip; import at.petrak.hexcasting.interop.HexInterop; +import java.io.IOException; +import java.util.function.Function; import net.minecraft.client.Minecraft; import net.minecraft.client.color.block.BlockColors; import net.minecraft.client.color.item.ItemColors; -import net.minecraft.client.model.EntityModel; import net.minecraft.client.model.PlayerModel; import net.minecraft.client.particle.ParticleProvider; import net.minecraft.client.particle.SpriteSet; @@ -29,111 +30,120 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; -import java.io.IOException; -import java.util.function.Function; - // This is Java because I can't kotlin-fu some of the consumers public class ForgeHexClientInitializer { - // We copy Fabric's example; it mixes in on the return of the initializer and sticks it in a global variable. - // So here's our global. - public static ItemColors GLOBAL_ITEM_COLORS; - public static BlockColors GLOBAL_BLOCK_COLORS; - - @SubscribeEvent - public static void clientInit(FMLClientSetupEvent evt) { - evt.enqueueWork(() -> { - RegisterClientStuff.init(); - RegisterClientStuff.registerColorProviders( - (colorizer, item) -> GLOBAL_ITEM_COLORS.register(colorizer, item), - (colorizer, block) -> GLOBAL_BLOCK_COLORS.register(colorizer, block)); - }); - - var evBus = MinecraftForge.EVENT_BUS; - - evBus.addListener((ClientPlayerNetworkEvent.LoggingIn e) -> - PatternRegistryManifest.processRegistry(null)); - - evBus.addListener((RenderLevelStageEvent e) -> { - if (e.getStage().equals(RenderLevelStageEvent.Stage.AFTER_PARTICLES)) { - HexAdditionalRenderers.overlayLevel(e.getPoseStack(), e.getPartialTick()); - } - }); - - evBus.addListener((RenderGuiEvent.Post e) -> { - HexAdditionalRenderers.overlayGui(e.getGuiGraphics(), e.getPartialTick()); - }); - - - evBus.addListener((TickEvent.RenderTickEvent e) -> { - if (e.phase == TickEvent.Phase.START) { - ClientTickCounter.renderTickStart(e.renderTickTime); - } - }); - - evBus.addListener((TickEvent.ClientTickEvent e) -> { - if (e.phase == TickEvent.Phase.END) { - ClientTickCounter.clientTickEnd(); - ShiftScrollListener.clientTickEnd(); - } - }); - - evBus.addListener((InputEvent.MouseScrollingEvent e) -> { - var cancel = ShiftScrollListener.onScrollInGameplay(e.getScrollDelta()); - e.setCanceled(cancel); - }); - - HexInterop.clientInit(); - } - - @SubscribeEvent - public static void registerShaders(RegisterShadersEvent evt) throws IOException { - HexShaders.init(evt.getResourceProvider(), p -> evt.registerShader(p.getFirst(), p.getSecond())); - } - - // https://github.com/VazkiiMods/Botania/blob/1.19.x/Forge/src/main/java/vazkii/botania/forge/client/ForgeClientInitializer.java#L225 - @SubscribeEvent - public static void registerParticles(RegisterParticleProvidersEvent evt) { - HexParticles.FactoryHandler.registerFactories(new HexParticles.FactoryHandler.Consumer() { - @Override - public <T extends ParticleOptions> void register(ParticleType<T> type, Function<SpriteSet, - ParticleProvider<T>> constructor) { - evt.registerSpriteSet(type, constructor::apply); - } - }); - } - - @SubscribeEvent - public static void registerRenderers(EntityRenderersEvent.RegisterRenderers evt) { - RegisterClientStuff.registerBlockEntityRenderers(evt::registerBlockEntityRenderer); - } - - @SubscribeEvent - public static void registerTooltipComponents(RegisterClientTooltipComponentFactoriesEvent evt) { - evt.register(PatternTooltip.class, PatternTooltipComponent::new); - } - - @SubscribeEvent - public static void onModelRegister(ModelEvent.RegisterAdditional evt) { - var recMan = Minecraft.getInstance().getResourceManager(); - RegisterClientStuff.onModelRegister(recMan, evt::register); - } - - @SubscribeEvent - public static void onModelBake(ModelEvent.BakingCompleted evt) { - RegisterClientStuff.onModelBake(evt.getModelBakery(), evt.getModels()); - } - - @SubscribeEvent - public static void registerEntityLayers(EntityRenderersEvent.RegisterLayerDefinitions evt) { - HexModelLayers.init(evt::registerLayerDefinition); - } - - @SubscribeEvent - public static void addPlayerLayers(EntityRenderersEvent.AddLayers evt) { - evt.getSkins().forEach(skinName -> { - var skin = (LivingEntityRenderer<AbstractClientPlayer, PlayerModel<AbstractClientPlayer>>) evt.getSkin(skinName); - - skin.addLayer(new AltioraLayer<>(skin, evt.getEntityModels())); - }); - } + // We copy Fabric's example; it mixes in on the return of the initializer and sticks it in a + // global variable. + // So here's our global. + public static ItemColors GLOBAL_ITEM_COLORS; + public static BlockColors GLOBAL_BLOCK_COLORS; + + @SubscribeEvent + public static void clientInit(FMLClientSetupEvent evt) { + evt.enqueueWork( + () -> { + RegisterClientStuff.init(); + RegisterClientStuff.registerColorProviders( + (colorizer, item) -> GLOBAL_ITEM_COLORS.register(colorizer, item), + (colorizer, block) -> GLOBAL_BLOCK_COLORS.register(colorizer, block)); + }); + + var evBus = MinecraftForge.EVENT_BUS; + + evBus.addListener( + (ClientPlayerNetworkEvent.LoggingIn e) -> PatternRegistryManifest.processRegistry(null)); + + evBus.addListener( + (RenderLevelStageEvent e) -> { + if (e.getStage().equals(RenderLevelStageEvent.Stage.AFTER_PARTICLES)) { + HexAdditionalRenderers.overlayLevel(e.getPoseStack(), e.getPartialTick()); + } + }); + + evBus.addListener( + (RenderGuiEvent.Post e) -> { + HexAdditionalRenderers.overlayGui(e.getGuiGraphics(), e.getPartialTick()); + }); + + evBus.addListener( + (TickEvent.RenderTickEvent e) -> { + if (e.phase == TickEvent.Phase.START) { + ClientTickCounter.renderTickStart(e.renderTickTime); + } + }); + + evBus.addListener( + (TickEvent.ClientTickEvent e) -> { + if (e.phase == TickEvent.Phase.END) { + ClientTickCounter.clientTickEnd(); + ShiftScrollListener.clientTickEnd(); + } + }); + + evBus.addListener( + (InputEvent.MouseScrollingEvent e) -> { + var cancel = ShiftScrollListener.onScrollInGameplay(e.getScrollDelta()); + e.setCanceled(cancel); + }); + + HexInterop.clientInit(); + } + + @SubscribeEvent + public static void registerShaders(RegisterShadersEvent evt) throws IOException { + HexShaders.init( + evt.getResourceProvider(), p -> evt.registerShader(p.getFirst(), p.getSecond())); + } + + // https://github.com/VazkiiMods/Botania/blob/1.19.x/Forge/src/main/java/vazkii/botania/forge/client/ForgeClientInitializer.java#L225 + @SubscribeEvent + public static void registerParticles(RegisterParticleProvidersEvent evt) { + HexParticles.FactoryHandler.registerFactories( + new HexParticles.FactoryHandler.Consumer() { + @Override + public <T extends ParticleOptions> void register( + ParticleType<T> type, Function<SpriteSet, ParticleProvider<T>> constructor) { + evt.registerSpriteSet(type, constructor::apply); + } + }); + } + + @SubscribeEvent + public static void registerRenderers(EntityRenderersEvent.RegisterRenderers evt) { + RegisterClientStuff.registerBlockEntityRenderers(evt::registerBlockEntityRenderer); + } + + @SubscribeEvent + public static void registerTooltipComponents(RegisterClientTooltipComponentFactoriesEvent evt) { + evt.register(PatternTooltip.class, PatternTooltipComponent::new); + } + + @SubscribeEvent + public static void onModelRegister(ModelEvent.RegisterAdditional evt) { + var recMan = Minecraft.getInstance().getResourceManager(); + RegisterClientStuff.onModelRegister(recMan, evt::register); + } + + @SubscribeEvent + public static void onModelBake(ModelEvent.BakingCompleted evt) { + RegisterClientStuff.onModelBake(evt.getModelBakery(), evt.getModels()); + } + + @SubscribeEvent + public static void registerEntityLayers(EntityRenderersEvent.RegisterLayerDefinitions evt) { + HexModelLayers.init(evt::registerLayerDefinition); + } + + @SubscribeEvent + public static void addPlayerLayers(EntityRenderersEvent.AddLayers evt) { + evt.getSkins() + .forEach( + skinName -> { + var skin = + (LivingEntityRenderer<AbstractClientPlayer, PlayerModel<AbstractClientPlayer>>) + evt.getSkin(skinName); + + skin.addLayer(new AltioraLayer<>(skin, evt.getEntityModels())); + }); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java index bf219312fc..df5f1e23b3 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java @@ -1,234 +1,277 @@ package at.petrak.hexcasting.forge; +import static at.petrak.hexcasting.api.mod.HexConfig.noneMatch; + import at.petrak.hexcasting.api.mod.HexConfig; +import java.util.List; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraftforge.common.ForgeConfigSpec; -import java.util.List; - -import static at.petrak.hexcasting.api.mod.HexConfig.noneMatch; - public class ForgeHexConfig implements HexConfig.CommonConfigAccess { - private static ForgeConfigSpec.LongValue dustMediaAmount; - private static ForgeConfigSpec.LongValue shardMediaAmount; - private static ForgeConfigSpec.LongValue chargedCrystalMediaAmount; - private static ForgeConfigSpec.DoubleValue mediaToHealthRate; - - private static ForgeConfigSpec.IntValue cypherCooldown; - private static ForgeConfigSpec.IntValue trinketCooldown; - private static ForgeConfigSpec.IntValue artifactCooldown; - - public ForgeHexConfig(ForgeConfigSpec.Builder builder) { - builder.push("Media Amounts"); - dustMediaAmount = builder.comment("How much media a single Amethyst Dust item is worth") - .defineInRange("dustMediaAmount", DEFAULT_DUST_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); - shardMediaAmount = builder.comment("How much media a single Amethyst Shard item is worth") - .defineInRange("shardMediaAmount", DEFAULT_SHARD_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); - chargedCrystalMediaAmount = builder.comment("How much media a single Charged Amethyst Crystal item is worth") - .defineInRange("chargedCrystalMediaAmount", DEFAULT_CHARGED_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); - mediaToHealthRate = builder.comment("How many points of media a half-heart is worth when casting from HP") - .defineInRange("mediaToHealthRate", DEFAULT_MEDIA_TO_HEALTH_RATE, 0.0, Double.POSITIVE_INFINITY); - builder.pop(); - - builder.push("Cooldowns"); - cypherCooldown = builder.comment("Cooldown in ticks of a cypher") - .defineInRange("cypherCooldown", DEFAULT_CYPHER_COOLDOWN, 0, Integer.MAX_VALUE); - trinketCooldown = builder.comment("Cooldown in ticks of a trinket") - .defineInRange("trinketCooldown", DEFAULT_TRINKET_COOLDOWN, 0, Integer.MAX_VALUE); - artifactCooldown = builder.comment("Cooldown in ticks of a artifact") - .defineInRange("artifactCooldown", DEFAULT_ARTIFACT_COOLDOWN, 0, Integer.MAX_VALUE); - builder.pop(); - } - - @Override - public long dustMediaAmount() { - return dustMediaAmount.get(); - } - - @Override - public long shardMediaAmount() { - return shardMediaAmount.get(); - } - - @Override - public long chargedCrystalMediaAmount() { - return chargedCrystalMediaAmount.get(); - } - - @Override - public double mediaToHealthRate() { - return mediaToHealthRate.get(); - } - - @Override - public int cypherCooldown() { - return cypherCooldown.get(); - } - - @Override - public int trinketCooldown() { - return trinketCooldown.get(); - } - - @Override - public int artifactCooldown() { - return artifactCooldown.get(); - } - - public static class Client implements HexConfig.ClientConfigAccess { - private static ForgeConfigSpec.BooleanValue ctrlTogglesOffStrokeOrder; - private static ForgeConfigSpec.BooleanValue invertSpellbookScrollDirection; - private static ForgeConfigSpec.BooleanValue invertAbacusScrollDirection; - private static ForgeConfigSpec.DoubleValue gridSnapThreshold; - private static ForgeConfigSpec.BooleanValue clickingTogglesDrawing; - - public Client(ForgeConfigSpec.Builder builder) { - ctrlTogglesOffStrokeOrder = builder.comment( - "Whether the ctrl key will instead turn *off* the color gradient on patterns") - .define("ctrlTogglesOffStrokeOrder", DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER); - invertSpellbookScrollDirection = builder.comment( - "Whether scrolling up (as opposed to down) will increase the page index of the spellbook, and " + - "vice versa") - .define("invertSpellbookScrollDirection", DEFAULT_INVERT_SPELLBOOK_SCROLL); - invertAbacusScrollDirection = builder.comment( - "Whether scrolling up (as opposed to down) will increase the value of the abacus, and vice versa") - .define("invertAbacusScrollDirection", DEFAULT_INVERT_ABACUS_SCROLL); - gridSnapThreshold = builder.comment( - "When using a staff, the distance from one dot you have to go to snap to the next dot, where 0.5 " + - "means 50% of the way.") - .defineInRange("gridSnapThreshold", DEFAULT_GRID_SNAP_THRESHOLD, 0.5, 1.0); - clickingTogglesDrawing = builder.comment( - "Whether you click to start and stop drawing instead of clicking and dragging") - .define("clickingTogglesDrawing", DEFAULT_CLICKING_TOGGLES_DRAWING); - } - - @Override - public boolean invertSpellbookScrollDirection() { - return invertSpellbookScrollDirection.get(); - } - - @Override - public boolean invertAbacusScrollDirection() { - return invertAbacusScrollDirection.get(); - } - - @Override - public boolean ctrlTogglesOffStrokeOrder() { - return ctrlTogglesOffStrokeOrder.get(); - } - - @Override - public double gridSnapThreshold() { - return gridSnapThreshold.get(); - } - - @Override - public boolean clickingTogglesDrawing() { - return clickingTogglesDrawing.get(); - } - } - - public static class Server implements HexConfig.ServerConfigAccess { - private static ForgeConfigSpec.IntValue opBreakHarvestLevel; - private static ForgeConfigSpec.IntValue maxOpCount; - - private static ForgeConfigSpec.IntValue maxSpellCircleLength; - - private static ForgeConfigSpec.ConfigValue<List<? extends String>> actionDenyList; - private static ForgeConfigSpec.ConfigValue<List<? extends String>> circleActionDenyList; - - private static ForgeConfigSpec.BooleanValue villagersOffendedByMindMurder; - - private static ForgeConfigSpec.ConfigValue<List<? extends String>> tpDimDenyList; - - private static ForgeConfigSpec.BooleanValue doesTrueNameHaveAmbit; - - private static ForgeConfigSpec.ConfigValue<List<? extends String>> fewScrollTables; - private static ForgeConfigSpec.ConfigValue<List<? extends String>> someScrollTables; - private static ForgeConfigSpec.ConfigValue<List<? extends String>> manyScrollTables; - - - public Server(ForgeConfigSpec.Builder builder) { - builder.push("Spells"); - maxOpCount = builder.comment("The maximum number of actions that can be executed in one tick, to avoid " + - "hanging the server.") - .defineInRange("maxOpCount", DEFAULT_MAX_OP_COUNT, 0, Integer.MAX_VALUE); - opBreakHarvestLevel = builder.comment( - "The harvest level of the Break Block spell.", - "0 = wood, 1 = stone, 2 = iron, 3 = diamond, 4 = netherite." - ).defineInRange("opBreakHarvestLevel", DEFAULT_OP_BREAK_HARVEST_LEVEL, 0, 4); - builder.pop(); - - builder.push("Spell Circles"); - maxSpellCircleLength = builder.comment("The maximum number of slates in a spell circle") - .defineInRange("maxSpellCircleLength", DEFAULT_MAX_SPELL_CIRCLE_LENGTH, 4, Integer.MAX_VALUE); - - circleActionDenyList = builder.comment( - "Resource locations of disallowed actions within circles. Trying to cast one of these in a circle" + - " will result in a mishap. For example: hexcasting:get_caster will prevent Mind's Reflection.") - .defineList("circleActionDenyList", List.of(), Server::isValidReslocArg); - builder.pop(); - - actionDenyList = builder.comment( - "Resource locations of disallowed actions. Trying to cast one of these will result in a mishap.") - .defineList("actionDenyList", List.of(), Server::isValidReslocArg); - - villagersOffendedByMindMurder = builder.comment( - "Should villagers take offense when you flay the mind of their fellow villagers?") - .define("villagersOffendedByMindMurder", true); - - tpDimDenyList = builder.comment("Resource locations of dimensions you can't Blink or Greater Teleport in.") - .defineList("tpDimDenyList", DEFAULT_DIM_TP_DENYLIST, Server::isValidReslocArg); - - doesTrueNameHaveAmbit = builder.comment( - "when false makes player reference iotas behave as normal entity reference iotas") - .define("doesTrueNameHaveAmbit", DEFAULT_TRUE_NAME_HAS_AMBIT); - } - - @Override - public int opBreakHarvestLevelBecauseForgeThoughtItWasAGoodIdeaToImplementHarvestTiersUsingAnHonestToGodTopoSort() { - return opBreakHarvestLevel.get(); - } - - @Override - public int maxOpCount() { - return maxOpCount.get(); - } - - @Override - public int maxSpellCircleLength() { - return maxSpellCircleLength.get(); - } - - @Override - public boolean isActionAllowed(ResourceLocation actionID) { - return noneMatch(actionDenyList.get(), actionID); - } - - @Override - public boolean isActionAllowedInCircles(ResourceLocation actionID) { - return noneMatch(circleActionDenyList.get(), actionID); - } - - @Override - public boolean doVillagersTakeOffenseAtMindMurder() { - return villagersOffendedByMindMurder.get(); - } - - @Override - public boolean canTeleportInThisDimension(ResourceKey<Level> dimension) { - return noneMatch(tpDimDenyList.get(), dimension.location()); - } - - @Override - public boolean trueNameHasAmbit() { - return doesTrueNameHaveAmbit.get(); - } - - private static boolean isValidReslocArg(Object o) { - return o instanceof String s && ResourceLocation.isValidResourceLocation(s); - } - } + private static ForgeConfigSpec.LongValue dustMediaAmount; + private static ForgeConfigSpec.LongValue shardMediaAmount; + private static ForgeConfigSpec.LongValue chargedCrystalMediaAmount; + private static ForgeConfigSpec.DoubleValue mediaToHealthRate; + + private static ForgeConfigSpec.IntValue cypherCooldown; + private static ForgeConfigSpec.IntValue trinketCooldown; + private static ForgeConfigSpec.IntValue artifactCooldown; + + public ForgeHexConfig(ForgeConfigSpec.Builder builder) { + builder.push("Media Amounts"); + dustMediaAmount = + builder + .comment("How much media a single Amethyst Dust item is worth") + .defineInRange("dustMediaAmount", DEFAULT_DUST_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); + shardMediaAmount = + builder + .comment("How much media a single Amethyst Shard item is worth") + .defineInRange("shardMediaAmount", DEFAULT_SHARD_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); + chargedCrystalMediaAmount = + builder + .comment("How much media a single Charged Amethyst Crystal item is worth") + .defineInRange( + "chargedCrystalMediaAmount", DEFAULT_CHARGED_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); + mediaToHealthRate = + builder + .comment("How many points of media a half-heart is worth when casting from HP") + .defineInRange( + "mediaToHealthRate", DEFAULT_MEDIA_TO_HEALTH_RATE, 0.0, Double.POSITIVE_INFINITY); + builder.pop(); + + builder.push("Cooldowns"); + cypherCooldown = + builder + .comment("Cooldown in ticks of a cypher") + .defineInRange("cypherCooldown", DEFAULT_CYPHER_COOLDOWN, 0, Integer.MAX_VALUE); + trinketCooldown = + builder + .comment("Cooldown in ticks of a trinket") + .defineInRange("trinketCooldown", DEFAULT_TRINKET_COOLDOWN, 0, Integer.MAX_VALUE); + artifactCooldown = + builder + .comment("Cooldown in ticks of a artifact") + .defineInRange("artifactCooldown", DEFAULT_ARTIFACT_COOLDOWN, 0, Integer.MAX_VALUE); + builder.pop(); + } + + @Override + public long dustMediaAmount() { + return dustMediaAmount.get(); + } + + @Override + public long shardMediaAmount() { + return shardMediaAmount.get(); + } + + @Override + public long chargedCrystalMediaAmount() { + return chargedCrystalMediaAmount.get(); + } + + @Override + public double mediaToHealthRate() { + return mediaToHealthRate.get(); + } + + @Override + public int cypherCooldown() { + return cypherCooldown.get(); + } + + @Override + public int trinketCooldown() { + return trinketCooldown.get(); + } + + @Override + public int artifactCooldown() { + return artifactCooldown.get(); + } + + public static class Client implements HexConfig.ClientConfigAccess { + private static ForgeConfigSpec.BooleanValue ctrlTogglesOffStrokeOrder; + private static ForgeConfigSpec.BooleanValue invertSpellbookScrollDirection; + private static ForgeConfigSpec.BooleanValue invertAbacusScrollDirection; + private static ForgeConfigSpec.DoubleValue gridSnapThreshold; + private static ForgeConfigSpec.BooleanValue clickingTogglesDrawing; + + public Client(ForgeConfigSpec.Builder builder) { + ctrlTogglesOffStrokeOrder = + builder + .comment( + "Whether the ctrl key will instead turn *off* the color gradient on patterns") + .define("ctrlTogglesOffStrokeOrder", DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER); + invertSpellbookScrollDirection = + builder + .comment( + "Whether scrolling up (as opposed to down) will increase the page index of the spellbook, and " + + "vice versa") + .define("invertSpellbookScrollDirection", DEFAULT_INVERT_SPELLBOOK_SCROLL); + invertAbacusScrollDirection = + builder + .comment( + "Whether scrolling up (as opposed to down) will increase the value of the abacus, and vice versa") + .define("invertAbacusScrollDirection", DEFAULT_INVERT_ABACUS_SCROLL); + gridSnapThreshold = + builder + .comment( + "When using a staff, the distance from one dot you have to go to snap to the next dot, where 0.5 " + + "means 50% of the way.") + .defineInRange("gridSnapThreshold", DEFAULT_GRID_SNAP_THRESHOLD, 0.5, 1.0); + clickingTogglesDrawing = + builder + .comment( + "Whether you click to start and stop drawing instead of clicking and dragging") + .define("clickingTogglesDrawing", DEFAULT_CLICKING_TOGGLES_DRAWING); + } + + @Override + public boolean invertSpellbookScrollDirection() { + return invertSpellbookScrollDirection.get(); + } + + @Override + public boolean invertAbacusScrollDirection() { + return invertAbacusScrollDirection.get(); + } + + @Override + public boolean ctrlTogglesOffStrokeOrder() { + return ctrlTogglesOffStrokeOrder.get(); + } + + @Override + public double gridSnapThreshold() { + return gridSnapThreshold.get(); + } + + @Override + public boolean clickingTogglesDrawing() { + return clickingTogglesDrawing.get(); + } + } + + public static class Server implements HexConfig.ServerConfigAccess { + private static ForgeConfigSpec.IntValue opBreakHarvestLevel; + private static ForgeConfigSpec.IntValue maxOpCount; + + private static ForgeConfigSpec.IntValue maxSpellCircleLength; + + private static ForgeConfigSpec.ConfigValue<List<? extends String>> actionDenyList; + private static ForgeConfigSpec.ConfigValue<List<? extends String>> circleActionDenyList; + + private static ForgeConfigSpec.BooleanValue villagersOffendedByMindMurder; + + private static ForgeConfigSpec.ConfigValue<List<? extends String>> tpDimDenyList; + + private static ForgeConfigSpec.BooleanValue doesTrueNameHaveAmbit; + + private static ForgeConfigSpec.ConfigValue<List<? extends String>> fewScrollTables; + private static ForgeConfigSpec.ConfigValue<List<? extends String>> someScrollTables; + private static ForgeConfigSpec.ConfigValue<List<? extends String>> manyScrollTables; + + public Server(ForgeConfigSpec.Builder builder) { + builder.push("Spells"); + maxOpCount = + builder + .comment( + "The maximum number of actions that can be executed in one tick, to avoid " + + "hanging the server.") + .defineInRange("maxOpCount", DEFAULT_MAX_OP_COUNT, 0, Integer.MAX_VALUE); + opBreakHarvestLevel = + builder + .comment( + "The harvest level of the Break Block spell.", + "0 = wood, 1 = stone, 2 = iron, 3 = diamond, 4 = netherite.") + .defineInRange("opBreakHarvestLevel", DEFAULT_OP_BREAK_HARVEST_LEVEL, 0, 4); + builder.pop(); + + builder.push("Spell Circles"); + maxSpellCircleLength = + builder + .comment("The maximum number of slates in a spell circle") + .defineInRange( + "maxSpellCircleLength", DEFAULT_MAX_SPELL_CIRCLE_LENGTH, 4, Integer.MAX_VALUE); + + circleActionDenyList = + builder + .comment( + "Resource locations of disallowed actions within circles. Trying to cast one of these in a circle" + + " will result in a mishap. For example: hexcasting:get_caster will prevent Mind's Reflection.") + .defineList("circleActionDenyList", List.of(), Server::isValidReslocArg); + builder.pop(); + + actionDenyList = + builder + .comment( + "Resource locations of disallowed actions. Trying to cast one of these will result in a mishap.") + .defineList("actionDenyList", List.of(), Server::isValidReslocArg); + + villagersOffendedByMindMurder = + builder + .comment( + "Should villagers take offense when you flay the mind of their fellow villagers?") + .define("villagersOffendedByMindMurder", true); + + tpDimDenyList = + builder + .comment("Resource locations of dimensions you can't Blink or Greater Teleport in.") + .defineList("tpDimDenyList", DEFAULT_DIM_TP_DENYLIST, Server::isValidReslocArg); + + doesTrueNameHaveAmbit = + builder + .comment( + "when false makes player reference iotas behave as normal entity reference iotas") + .define("doesTrueNameHaveAmbit", DEFAULT_TRUE_NAME_HAS_AMBIT); + } + + @Override + public int + opBreakHarvestLevelBecauseForgeThoughtItWasAGoodIdeaToImplementHarvestTiersUsingAnHonestToGodTopoSort() { + return opBreakHarvestLevel.get(); + } + + @Override + public int maxOpCount() { + return maxOpCount.get(); + } + + @Override + public int maxSpellCircleLength() { + return maxSpellCircleLength.get(); + } + + @Override + public boolean isActionAllowed(ResourceLocation actionID) { + return noneMatch(actionDenyList.get(), actionID); + } + + @Override + public boolean isActionAllowedInCircles(ResourceLocation actionID) { + return noneMatch(circleActionDenyList.get(), actionID); + } + + @Override + public boolean doVillagersTakeOffenseAtMindMurder() { + return villagersOffendedByMindMurder.get(); + } + + @Override + public boolean canTeleportInThisDimension(ResourceKey<Level> dimension) { + return noneMatch(tpDimDenyList.get(), dimension.location()); + } + + @Override + public boolean trueNameHasAmbit() { + return doesTrueNameHaveAmbit.get(); + } + + private static boolean isValidReslocArg(Object o) { + return o instanceof String s && ResourceLocation.isValidResourceLocation(s); + } + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java index 8fa6affec6..bc61de5c07 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java @@ -32,6 +32,8 @@ import at.petrak.hexcasting.forge.recipe.ForgeUnsealedIngredient; import at.petrak.hexcasting.interop.HexInterop; import at.petrak.hexcasting.xplat.IXplatAbstractions; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import net.minecraft.core.MappedRegistry; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; @@ -73,223 +75,247 @@ import net.minecraftforge.registries.RegisterEvent; import thedarkcolour.kotlinforforge.KotlinModLoadingContext; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - @Mod(HexAPI.MOD_ID) public class ForgeHexInitializer { - public ForgeHexInitializer() { - initConfig(); - initRegistries(); - initRegistry(); - initListeners(); - } - - private static void initConfig() { - var config = new ForgeConfigSpec.Builder().configure(ForgeHexConfig::new); - var clientConfig = new ForgeConfigSpec.Builder().configure(ForgeHexConfig.Client::new); - var serverConfig = new ForgeConfigSpec.Builder().configure(ForgeHexConfig.Server::new); - HexConfig.setCommon(config.getLeft()); - HexConfig.setClient(clientConfig.getLeft()); - HexConfig.setServer(serverConfig.getLeft()); - var mlc = ModLoadingContext.get(); - mlc.registerConfig(ModConfig.Type.COMMON, config.getRight()); - mlc.registerConfig(ModConfig.Type.CLIENT, clientConfig.getRight()); - mlc.registerConfig(ModConfig.Type.SERVER, serverConfig.getRight()); - } - - public static void initRegistries() { - if (!(BuiltInRegistries.REGISTRY instanceof MappedRegistry<?> rootRegistry)) return; - rootRegistry.unfreeze(); - - IXplatAbstractions.INSTANCE.getActionRegistry(); - IXplatAbstractions.INSTANCE.getSpecialHandlerRegistry(); - IXplatAbstractions.INSTANCE.getIotaTypeRegistry(); - IXplatAbstractions.INSTANCE.getArithmeticRegistry(); - IXplatAbstractions.INSTANCE.getContinuationTypeRegistry(); - IXplatAbstractions.INSTANCE.getEvalSoundRegistry(); - - rootRegistry.freeze(); - } - - private static void initRegistry() { - bind(Registries.SOUND_EVENT, HexSounds::registerSounds); - - HexBlockSetTypes.registerBlocks(BlockSetType::register); - - bind(Registries.CREATIVE_MODE_TAB, HexCreativeTabs::registerCreativeTabs); - - bind(Registries.BLOCK, HexBlocks::registerBlocks); - bind(Registries.ITEM, HexBlocks::registerBlockItems); - bind(Registries.BLOCK_ENTITY_TYPE, HexBlockEntities::registerTiles); - bind(Registries.ITEM, HexItems::registerItems); - - bind(Registries.RECIPE_SERIALIZER, HexRecipeStuffRegistry::registerSerializers); - bind(Registries.RECIPE_TYPE, HexRecipeStuffRegistry::registerTypes); - - bind(Registries.ENTITY_TYPE, HexEntities::registerEntities); - bind(Registries.ATTRIBUTE, HexAttributes::register); - bind(Registries.MOB_EFFECT, HexMobEffects::register); - bind(Registries.POTION, HexPotions::register); - HexPotions.addRecipes(); - - bind(Registries.PARTICLE_TYPE, HexParticles::registerParticles); - - bind(HexRegistries.IOTA_TYPE, HexIotaTypes::registerTypes); - bind(HexRegistries.ACTION, HexActions::register); - bind(HexRegistries.SPECIAL_HANDLER, HexSpecialHandlers::register); - bind(HexRegistries.ARITHMETIC, HexArithmetics::register); - bind(HexRegistries.CONTINUATION_TYPE, HexContinuationTypes::registerContinuations); - bind(HexRegistries.EVAL_SOUND, HexEvalSounds::register); - - ForgeHexArgumentTypeRegistry.ARGUMENT_TYPES.register(getModEventBus()); - ForgeHexLootMods.REGISTRY.register(getModEventBus()); - - HexAdvancementTriggers.registerTriggers(); - - RegisterMisc.register(); - } - - // https://github.com/VazkiiMods/Botania/blob/1.18.x/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java - private static <T> void bind(ResourceKey<? extends Registry<T>> registry, - Consumer<BiConsumer<T, ResourceLocation>> source) { - getModEventBus().addListener((RegisterEvent event) -> { - if (registry.equals(event.getRegistryKey())) { - source.accept((t, rl) -> event.register(registry, rl, () -> t)); - } - }); - } - - private static void initListeners() { - var modBus = getModEventBus(); - var evBus = MinecraftForge.EVENT_BUS; - - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> modBus.register(ForgeHexClientInitializer.class)); - - modBus.addListener((FMLCommonSetupEvent evt) -> - evt.enqueueWork(() -> { - ForgePacketHandler.init(); - HexComposting.setup(); - HexStrippables.init(); - // Forge does not strictly require TreeGrowers to initialize during early game stages, unlike Fabric - // and Quilt. - // However, all launcher panic if the same resource is registered twice. But do need blocks and - // items to be completely initialized. - // Explicitly calling here avoids potential confusion, or reliance on tricks that may fail under - // compiler optimization. - AkashicTreeGrower.init(); - - HexInterop.init(); - })); - - modBus.addListener((BuildCreativeModeTabContentsEvent evt) -> { - HexBlocks.registerBlockCreativeTab(evt::accept, evt.getTab()); - HexItems.registerItemCreativeTab(evt, evt.getTab()); - }); - - - // We have to do these at some point when the registries are still open - modBus.addListener((RegisterEvent evt) -> { - if (evt.getRegistryKey().equals(Registries.ITEM)) { - CraftingHelper.register(ForgeUnsealedIngredient.ID, ForgeUnsealedIngredient.Serializer.INSTANCE); - CraftingHelper.register(ForgeModConditionalIngredient.ID, - ForgeModConditionalIngredient.Serializer.INSTANCE); - HexStatistics.register(); - HexLootFunctions.registerSerializers((lift, id) -> - Registry.register(BuiltInRegistries.LOOT_FUNCTION_TYPE, id, lift)); - } - }); - - evBus.register(CapClientCastingStack.class); - - evBus.addListener((PlayerInteractEvent.EntityInteract evt) -> { - var res = BrainsweepingEvents.interactWithBrainswept( - evt.getEntity(), evt.getLevel(), evt.getHand(), evt.getTarget(), null); - if (res.consumesAction()) { - evt.setCanceled(true); - evt.setCancellationResult(res); - } - }); - evBus.addListener((LivingConversionEvent.Post evt) -> - BrainsweepingEvents.copyBrainsweepPostTransformation(evt.getEntity(), evt.getOutcome())); - - evBus.addListener((LivingEvent.LivingTickEvent evt) -> { - if (evt.getEntity() instanceof ServerPlayer splayer) { - OpFlight.tickDownFlight(splayer); - OpAltiora.checkPlayerCollision(splayer); - } - }); - - evBus.addListener((TickEvent.LevelTickEvent evt) -> { - if (evt.phase == TickEvent.Phase.END && evt.level instanceof ServerLevel world) { - PlayerPositionRecorder.updateAllPlayers(world); - } - }); - - evBus.addListener((ServerStartedEvent evt) -> - PatternRegistryManifest.processRegistry(evt.getServer().overworld())); - - evBus.addListener((RegisterCommandsEvent evt) -> HexCommands.register(evt.getDispatcher())); - - evBus.addListener((PlayerEvent.BreakSpeed evt) -> { - var pos = evt.getPosition(); - // tracing the dataflow, this is only empty if someone is calling a deprecated function for the - // break speed. This will probably not ever hapen, but hey! i will never complain about correctness - // enforced at the type level. - if (pos.isEmpty()) { - return; - } - evt.setCanceled(ItemJewelerHammer.shouldFailToBreak(evt.getEntity(), evt.getState(), pos.get())); - }); - - // === Events implemented in other ways on Fabric - - // On Fabric this should be auto-synced - evBus.addListener((PlayerEvent.StartTracking evt) -> { - Entity target = evt.getTarget(); - if (evt.getTarget() instanceof ServerPlayer serverPlayer && - target instanceof Mob mob && IXplatAbstractions.INSTANCE.isBrainswept(mob)) { - ForgePacketHandler.getNetwork() - .send(PacketDistributor.PLAYER.with(() -> serverPlayer), MsgBrainsweepAck.of(mob)); - } - }); - - // Implemented with a mixin on Farbc - evBus.addListener((BlockEvent.BlockToolModificationEvent evt) -> { - if (!evt.isSimulated() && evt.getToolAction() == ToolActions.AXE_STRIP) { - BlockState bs = evt.getState(); - var output = HexStrippables.STRIPPABLES.get(bs.getBlock()); - if (output != null) { - evt.setFinalState(output.withPropertiesOf(bs)); - } - } - }); - - // Caps are cardinal components on farbc - modBus.addListener(ForgeCapabilityHandler::registerCaps); - evBus.addGenericListener(ItemStack.class, ForgeCapabilityHandler::attachItemCaps); - evBus.addGenericListener(BlockEntity.class, ForgeCapabilityHandler::attachBlockEntityCaps); - evBus.addGenericListener(Entity.class, ForgeCapabilityHandler::attachEntityCaps); - - modBus.register(ForgeHexDataGenerators.class); - modBus.register(ForgeCapabilityHandler.class); - evBus.register(CapSyncers.class); - - modBus.addListener((EntityAttributeModificationEvent e) -> { - e.add(EntityType.PLAYER, HexAttributes.GRID_ZOOM); - e.add(EntityType.PLAYER, HexAttributes.SCRY_SIGHT); - }); - - if (ModList.get().isLoaded(HexInterop.Forge.CURIOS_API_ID)) { - modBus.addListener(CuriosApiInterop::onInterModEnqueue); - modBus.addListener(CuriosApiInterop::onClientSetup); - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, - () -> () -> modBus.addListener(CuriosRenderers::onLayerRegister)); - } - } - - // aaaauughhg - private static IEventBus getModEventBus() { - return KotlinModLoadingContext.Companion.get().getKEventBus(); - } + public ForgeHexInitializer() { + initConfig(); + initRegistries(); + initRegistry(); + initListeners(); + } + + private static void initConfig() { + var config = new ForgeConfigSpec.Builder().configure(ForgeHexConfig::new); + var clientConfig = new ForgeConfigSpec.Builder().configure(ForgeHexConfig.Client::new); + var serverConfig = new ForgeConfigSpec.Builder().configure(ForgeHexConfig.Server::new); + HexConfig.setCommon(config.getLeft()); + HexConfig.setClient(clientConfig.getLeft()); + HexConfig.setServer(serverConfig.getLeft()); + var mlc = ModLoadingContext.get(); + mlc.registerConfig(ModConfig.Type.COMMON, config.getRight()); + mlc.registerConfig(ModConfig.Type.CLIENT, clientConfig.getRight()); + mlc.registerConfig(ModConfig.Type.SERVER, serverConfig.getRight()); + } + + public static void initRegistries() { + if (!(BuiltInRegistries.REGISTRY instanceof MappedRegistry<?> rootRegistry)) return; + rootRegistry.unfreeze(); + + IXplatAbstractions.INSTANCE.getActionRegistry(); + IXplatAbstractions.INSTANCE.getSpecialHandlerRegistry(); + IXplatAbstractions.INSTANCE.getIotaTypeRegistry(); + IXplatAbstractions.INSTANCE.getArithmeticRegistry(); + IXplatAbstractions.INSTANCE.getContinuationTypeRegistry(); + IXplatAbstractions.INSTANCE.getEvalSoundRegistry(); + + rootRegistry.freeze(); + } + + private static void initRegistry() { + bind(Registries.SOUND_EVENT, HexSounds::registerSounds); + + HexBlockSetTypes.registerBlocks(BlockSetType::register); + + bind(Registries.CREATIVE_MODE_TAB, HexCreativeTabs::registerCreativeTabs); + + bind(Registries.BLOCK, HexBlocks::registerBlocks); + bind(Registries.ITEM, HexBlocks::registerBlockItems); + bind(Registries.BLOCK_ENTITY_TYPE, HexBlockEntities::registerTiles); + bind(Registries.ITEM, HexItems::registerItems); + + bind(Registries.RECIPE_SERIALIZER, HexRecipeStuffRegistry::registerSerializers); + bind(Registries.RECIPE_TYPE, HexRecipeStuffRegistry::registerTypes); + + bind(Registries.ENTITY_TYPE, HexEntities::registerEntities); + bind(Registries.ATTRIBUTE, HexAttributes::register); + bind(Registries.MOB_EFFECT, HexMobEffects::register); + bind(Registries.POTION, HexPotions::register); + HexPotions.addRecipes(); + + bind(Registries.PARTICLE_TYPE, HexParticles::registerParticles); + + bind(HexRegistries.IOTA_TYPE, HexIotaTypes::registerTypes); + bind(HexRegistries.ACTION, HexActions::register); + bind(HexRegistries.SPECIAL_HANDLER, HexSpecialHandlers::register); + bind(HexRegistries.ARITHMETIC, HexArithmetics::register); + bind(HexRegistries.CONTINUATION_TYPE, HexContinuationTypes::registerContinuations); + bind(HexRegistries.EVAL_SOUND, HexEvalSounds::register); + + ForgeHexArgumentTypeRegistry.ARGUMENT_TYPES.register(getModEventBus()); + ForgeHexLootMods.REGISTRY.register(getModEventBus()); + + HexAdvancementTriggers.registerTriggers(); + + RegisterMisc.register(); + } + + // https://github.com/VazkiiMods/Botania/blob/1.18.x/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java + private static <T> void bind( + ResourceKey<? extends Registry<T>> registry, + Consumer<BiConsumer<T, ResourceLocation>> source) { + getModEventBus() + .addListener( + (RegisterEvent event) -> { + if (registry.equals(event.getRegistryKey())) { + source.accept((t, rl) -> event.register(registry, rl, () -> t)); + } + }); + } + + private static void initListeners() { + var modBus = getModEventBus(); + var evBus = MinecraftForge.EVENT_BUS; + + DistExecutor.unsafeRunWhenOn( + Dist.CLIENT, () -> () -> modBus.register(ForgeHexClientInitializer.class)); + + modBus.addListener( + (FMLCommonSetupEvent evt) -> + evt.enqueueWork( + () -> { + ForgePacketHandler.init(); + HexComposting.setup(); + HexStrippables.init(); + // Forge does not strictly require TreeGrowers to initialize during early game + // stages, unlike Fabric + // and Quilt. + // However, all launcher panic if the same resource is registered twice. But do + // need blocks and + // items to be completely initialized. + // Explicitly calling here avoids potential confusion, or reliance on tricks that + // may fail under + // compiler optimization. + AkashicTreeGrower.init(); + + HexInterop.init(); + })); + + modBus.addListener( + (BuildCreativeModeTabContentsEvent evt) -> { + HexBlocks.registerBlockCreativeTab(evt::accept, evt.getTab()); + HexItems.registerItemCreativeTab(evt, evt.getTab()); + }); + + // We have to do these at some point when the registries are still open + modBus.addListener( + (RegisterEvent evt) -> { + if (evt.getRegistryKey().equals(Registries.ITEM)) { + CraftingHelper.register( + ForgeUnsealedIngredient.ID, ForgeUnsealedIngredient.Serializer.INSTANCE); + CraftingHelper.register( + ForgeModConditionalIngredient.ID, + ForgeModConditionalIngredient.Serializer.INSTANCE); + HexStatistics.register(); + HexLootFunctions.registerSerializers( + (lift, id) -> Registry.register(BuiltInRegistries.LOOT_FUNCTION_TYPE, id, lift)); + } + }); + + evBus.register(CapClientCastingStack.class); + + evBus.addListener( + (PlayerInteractEvent.EntityInteract evt) -> { + var res = + BrainsweepingEvents.interactWithBrainswept( + evt.getEntity(), evt.getLevel(), evt.getHand(), evt.getTarget(), null); + if (res.consumesAction()) { + evt.setCanceled(true); + evt.setCancellationResult(res); + } + }); + evBus.addListener( + (LivingConversionEvent.Post evt) -> + BrainsweepingEvents.copyBrainsweepPostTransformation( + evt.getEntity(), evt.getOutcome())); + + evBus.addListener( + (LivingEvent.LivingTickEvent evt) -> { + if (evt.getEntity() instanceof ServerPlayer splayer) { + OpFlight.tickDownFlight(splayer); + OpAltiora.checkPlayerCollision(splayer); + } + }); + + evBus.addListener( + (TickEvent.LevelTickEvent evt) -> { + if (evt.phase == TickEvent.Phase.END && evt.level instanceof ServerLevel world) { + PlayerPositionRecorder.updateAllPlayers(world); + } + }); + + evBus.addListener( + (ServerStartedEvent evt) -> + PatternRegistryManifest.processRegistry(evt.getServer().overworld())); + + evBus.addListener((RegisterCommandsEvent evt) -> HexCommands.register(evt.getDispatcher())); + + evBus.addListener( + (PlayerEvent.BreakSpeed evt) -> { + var pos = evt.getPosition(); + // tracing the dataflow, this is only empty if someone is calling a deprecated function + // for the + // break speed. This will probably not ever hapen, but hey! i will never complain about + // correctness + // enforced at the type level. + if (pos.isEmpty()) { + return; + } + evt.setCanceled( + ItemJewelerHammer.shouldFailToBreak(evt.getEntity(), evt.getState(), pos.get())); + }); + + // === Events implemented in other ways on Fabric + + // On Fabric this should be auto-synced + evBus.addListener( + (PlayerEvent.StartTracking evt) -> { + Entity target = evt.getTarget(); + if (evt.getTarget() instanceof ServerPlayer serverPlayer + && target instanceof Mob mob + && IXplatAbstractions.INSTANCE.isBrainswept(mob)) { + ForgePacketHandler.getNetwork() + .send(PacketDistributor.PLAYER.with(() -> serverPlayer), MsgBrainsweepAck.of(mob)); + } + }); + + // Implemented with a mixin on Farbc + evBus.addListener( + (BlockEvent.BlockToolModificationEvent evt) -> { + if (!evt.isSimulated() && evt.getToolAction() == ToolActions.AXE_STRIP) { + BlockState bs = evt.getState(); + var output = HexStrippables.STRIPPABLES.get(bs.getBlock()); + if (output != null) { + evt.setFinalState(output.withPropertiesOf(bs)); + } + } + }); + + // Caps are cardinal components on farbc + modBus.addListener(ForgeCapabilityHandler::registerCaps); + evBus.addGenericListener(ItemStack.class, ForgeCapabilityHandler::attachItemCaps); + evBus.addGenericListener(BlockEntity.class, ForgeCapabilityHandler::attachBlockEntityCaps); + evBus.addGenericListener(Entity.class, ForgeCapabilityHandler::attachEntityCaps); + + modBus.register(ForgeHexDataGenerators.class); + modBus.register(ForgeCapabilityHandler.class); + evBus.register(CapSyncers.class); + + modBus.addListener( + (EntityAttributeModificationEvent e) -> { + e.add(EntityType.PLAYER, HexAttributes.GRID_ZOOM); + e.add(EntityType.PLAYER, HexAttributes.SCRY_SIGHT); + }); + + if (ModList.get().isLoaded(HexInterop.Forge.CURIOS_API_ID)) { + modBus.addListener(CuriosApiInterop::onInterModEnqueue); + modBus.addListener(CuriosApiInterop::onClientSetup); + DistExecutor.unsafeRunWhenOn( + Dist.CLIENT, () -> () -> modBus.addListener(CuriosRenderers::onLayerRegister)); + } + } + + // aaaauughhg + private static IEventBus getModEventBus() { + return KotlinModLoadingContext.Companion.get().getKEventBus(); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/CapSyncers.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/CapSyncers.java index 89e26d4474..939247f902 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/CapSyncers.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/CapSyncers.java @@ -10,63 +10,63 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; public class CapSyncers { - @SubscribeEvent - public static void copyDataOnDeath(PlayerEvent.Clone evt) { - var eitherSidePlayer = evt.getEntity(); - // this apparently defines it in outside scope. the more you know. - if (!(eitherSidePlayer instanceof ServerPlayer player)) { - return; - } + @SubscribeEvent + public static void copyDataOnDeath(PlayerEvent.Clone evt) { + var eitherSidePlayer = evt.getEntity(); + // this apparently defines it in outside scope. the more you know. + if (!(eitherSidePlayer instanceof ServerPlayer player)) { + return; + } - var eitherSideProto = evt.getOriginal(); - if (!(eitherSideProto instanceof ServerPlayer proto)) { - return; - } + var eitherSideProto = evt.getOriginal(); + if (!(eitherSideProto instanceof ServerPlayer proto)) { + return; + } - // Copy data from this to new player - var x = IXplatAbstractions.INSTANCE; - x.setFlight(player, x.getFlight(proto)); - x.setAltiora(player, x.getAltiora(proto)); - x.setSentinel(player, x.getSentinel(proto)); - x.setPigment(player, x.getPigment(proto)); - x.setStaffcastImage(player, x.getStaffcastVM(proto, InteractionHand.MAIN_HAND).getImage()); - x.setPatterns(player, x.getPatternsSavedInUi(proto)); - } + // Copy data from this to new player + var x = IXplatAbstractions.INSTANCE; + x.setFlight(player, x.getFlight(proto)); + x.setAltiora(player, x.getAltiora(proto)); + x.setSentinel(player, x.getSentinel(proto)); + x.setPigment(player, x.getPigment(proto)); + x.setStaffcastImage(player, x.getStaffcastVM(proto, InteractionHand.MAIN_HAND).getImage()); + x.setPatterns(player, x.getPatternsSavedInUi(proto)); + } - @SubscribeEvent - public static void syncDataOnLogin(PlayerEvent.PlayerLoggedInEvent evt) { - if (!(evt.getEntity() instanceof ServerPlayer player)) { - return; - } + @SubscribeEvent + public static void syncDataOnLogin(PlayerEvent.PlayerLoggedInEvent evt) { + if (!(evt.getEntity() instanceof ServerPlayer player)) { + return; + } - syncSentinel(player); - syncPigment(player); - syncAltiora(player); - } + syncSentinel(player); + syncPigment(player); + syncAltiora(player); + } - @SubscribeEvent - public static void syncDataOnRejoin(PlayerEvent.PlayerRespawnEvent evt) { - if (!(evt.getEntity() instanceof ServerPlayer player)) { - return; - } + @SubscribeEvent + public static void syncDataOnRejoin(PlayerEvent.PlayerRespawnEvent evt) { + if (!(evt.getEntity() instanceof ServerPlayer player)) { + return; + } - syncSentinel(player); - syncPigment(player); - syncAltiora(player); - } + syncSentinel(player); + syncPigment(player); + syncAltiora(player); + } - public static void syncSentinel(ServerPlayer player) { - IXplatAbstractions.INSTANCE.sendPacketToPlayer(player, - new MsgSentinelStatusUpdateAck(IXplatAbstractions.INSTANCE.getSentinel(player))); - } + public static void syncSentinel(ServerPlayer player) { + IXplatAbstractions.INSTANCE.sendPacketToPlayer( + player, new MsgSentinelStatusUpdateAck(IXplatAbstractions.INSTANCE.getSentinel(player))); + } - public static void syncPigment(ServerPlayer player) { - IXplatAbstractions.INSTANCE.sendPacketToPlayer(player, - new MsgPigmentUpdateAck(IXplatAbstractions.INSTANCE.getPigment(player))); - } + public static void syncPigment(ServerPlayer player) { + IXplatAbstractions.INSTANCE.sendPacketToPlayer( + player, new MsgPigmentUpdateAck(IXplatAbstractions.INSTANCE.getPigment(player))); + } - public static void syncAltiora(ServerPlayer player) { - IXplatAbstractions.INSTANCE.sendPacketToPlayer(player, - new MsgAltioraUpdateAck(IXplatAbstractions.INSTANCE.getAltiora(player))); - } + public static void syncAltiora(ServerPlayer player) { + IXplatAbstractions.INSTANCE.sendPacketToPlayer( + player, new MsgAltioraUpdateAck(IXplatAbstractions.INSTANCE.getAltiora(player))); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/ForgeCapabilityHandler.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/ForgeCapabilityHandler.java index 502357ab3a..368867cae8 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/ForgeCapabilityHandler.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/ForgeCapabilityHandler.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.forge.cap; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.addldata.*; import at.petrak.hexcasting.api.casting.circles.BlockEntityAbstractImpetus; import at.petrak.hexcasting.api.casting.iota.DoubleIota; @@ -15,6 +17,8 @@ import at.petrak.hexcasting.forge.interop.curios.CuriosApiInterop; import at.petrak.hexcasting.interop.HexInterop; import at.petrak.hexcasting.xplat.IXplatAbstractions; +import java.util.function.BooleanSupplier; +import java.util.function.Function; import net.minecraft.core.Direction; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; @@ -34,183 +38,225 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.function.BooleanSupplier; -import java.util.function.Function; +public class ForgeCapabilityHandler { + /** Items that store an iota to their tag. */ + public static final ResourceLocation IOTA_STORAGE_CAP = modLoc("iota_holder"); -import static at.petrak.hexcasting.api.HexAPI.modLoc; + /** Items that intrinsically store an iota. */ + public static final ResourceLocation IOTA_STATIC_CAP = modLoc("iota_item"); -public class ForgeCapabilityHandler { - /** - * Items that store an iota to their tag. - */ - public static final ResourceLocation IOTA_STORAGE_CAP = modLoc("iota_holder"); - /** - * Items that intrinsically store an iota. - */ - public static final ResourceLocation IOTA_STATIC_CAP = modLoc("iota_item"); - /** - * Items that store a variable amount of media to their tag. - */ - public static final ResourceLocation MEDIA_STORAGE_CAP = modLoc("media_holder"); - /** - * Items that statically provide media. - */ - public static final ResourceLocation MEDIA_STATIC_CAP = modLoc("media_item"); - /** - * Items that store a packaged Hex. - */ - public static final ResourceLocation HEX_HOLDER_CAP = modLoc("hex_item"); - /** - * Items that have multiple visual variants. - */ - public static final ResourceLocation VARIANT_ITEM_CAP = modLoc("variant_item"); - /** - * Items that work as pigments. - */ - public static final ResourceLocation PIGMENT_CAP = modLoc("pigment"); - public static final ResourceLocation CURIO_CAP = modLoc("curio"); - - public static final ResourceLocation IMPETUS_HANDLER = modLoc("impetus_items"); - - /** - * Used to render the pattern spiral around players while casting. - */ - public static final ResourceLocation PATTERN_SPIRAL = modLoc("pattern_spiral"); - - public static void registerCaps(RegisterCapabilitiesEvent evt) { - evt.register(ADMediaHolder.class); - evt.register(ADIotaHolder.class); - evt.register(ADHexHolder.class); - evt.register(ADPigment.class); - } - - public static void attachItemCaps(AttachCapabilitiesEvent<ItemStack> evt) { - ItemStack stack = evt.getObject(); - - if (stack.getItem() instanceof MediaHolderItem holder) { - evt.addCapability(MEDIA_STORAGE_CAP, - provide(stack, HexCapabilities.MEDIA, () -> new CapItemMediaHolder(holder, stack))); - } else if (stack.is(HexItems.AMETHYST_DUST)) { - evt.addCapability(MEDIA_STATIC_CAP, provide(stack, HexCapabilities.MEDIA, () -> - new CapStaticMediaHolder(HexConfig.common()::dustMediaAmount, ADMediaHolder.AMETHYST_DUST_PRIORITY, - stack))); - } else if (stack.is(Items.AMETHYST_SHARD)) { - evt.addCapability(MEDIA_STATIC_CAP, provide(stack, HexCapabilities.MEDIA, () -> new CapStaticMediaHolder( - HexConfig.common()::shardMediaAmount, ADMediaHolder.AMETHYST_SHARD_PRIORITY, stack))); - } else if (stack.is(HexItems.CHARGED_AMETHYST)) { - evt.addCapability(MEDIA_STATIC_CAP, - provide(stack, HexCapabilities.MEDIA, () -> new CapStaticMediaHolder( - HexConfig.common()::chargedCrystalMediaAmount, ADMediaHolder.CHARGED_AMETHYST_PRIORITY, stack))); - } else if (stack.is(HexItems.QUENCHED_SHARD)) { - // no one uses the config - evt.addCapability(MEDIA_STATIC_CAP, - provide(stack, HexCapabilities.MEDIA, () -> new CapStaticMediaHolder( - () -> MediaConstants.QUENCHED_SHARD_UNIT, ADMediaHolder.QUENCHED_SHARD_PRIORITY, stack))); - } else if (stack.is(HexBlocks.QUENCHED_ALLAY.asItem())) { - // no one uses the config - evt.addCapability(MEDIA_STATIC_CAP, - provide(stack, HexCapabilities.MEDIA, () -> new CapStaticMediaHolder( - () -> MediaConstants.QUENCHED_BLOCK_UNIT, ADMediaHolder.QUENCHED_ALLAY_PRIORITY, stack))); - } - - if (stack.getItem() instanceof IotaHolderItem holder) { - evt.addCapability(IOTA_STORAGE_CAP, - provide(stack, HexCapabilities.IOTA, () -> new CapItemIotaHolder(holder, stack))); - } else if (stack.is(Items.PUMPKIN_PIE)) { - // haha yes - evt.addCapability(IOTA_STATIC_CAP, provide(stack, HexCapabilities.IOTA, () -> - new CapStaticIotaHolder((s) -> new DoubleIota(Math.PI * s.getCount()), stack))); - } - - if (stack.getItem() instanceof HexHolderItem holder) { - evt.addCapability(HEX_HOLDER_CAP, - provide(stack, HexCapabilities.STORED_HEX, () -> new CapItemHexHolder(holder, stack))); - } - if (stack.getItem() instanceof VariantItem variantItem) { - evt.addCapability(VARIANT_ITEM_CAP, - provide(stack, HexCapabilities.VARIANT_ITEM, () -> new CapItemVariantItem(variantItem, stack))); - } - - if (stack.getItem() instanceof PigmentItem pigment) { - evt.addCapability(PIGMENT_CAP, - provide(stack, HexCapabilities.COLOR, () -> new CapItemPigment(pigment, stack))); - } - - if (IXplatAbstractions.INSTANCE.isModPresent(HexInterop.Forge.CURIOS_API_ID) - && stack.getItem() instanceof HexBaubleItem) { - evt.addCapability(CURIO_CAP, CuriosApiInterop.curioCap(stack)); - } - } - - public static void attachEntityCaps(AttachCapabilitiesEvent<Entity> evt) { - var entity = evt.getObject(); - if (entity instanceof ItemEntity item) { - evt.addCapability(IOTA_STORAGE_CAP, wrapItemEntityDelegate(item, - ItemDelegatingEntityIotaHolder.ToItemEntity::new)); - } else if (entity instanceof ItemFrame frame) { - evt.addCapability(IOTA_STORAGE_CAP, wrapItemEntityDelegate(frame, - ItemDelegatingEntityIotaHolder.ToItemFrame::new)); - } else if (entity instanceof EntityWallScroll scroll) { - evt.addCapability(IOTA_STORAGE_CAP, wrapItemEntityDelegate(scroll, - ItemDelegatingEntityIotaHolder.ToWallScroll::new)); - } else if (entity instanceof Player player) { - evt.addCapability(PATTERN_SPIRAL, provide(player, HexCapabilities.CLIENT_CASTING_STACK, - () -> new CapClientCastingStack(player, new ClientCastingStack()))); - } - } - - public static void attachBlockEntityCaps(AttachCapabilitiesEvent<BlockEntity> evt) { - if (evt.getObject() instanceof BlockEntityAbstractImpetus impetus) { - evt.addCapability(IMPETUS_HANDLER, provide(impetus, ForgeCapabilities.ITEM_HANDLER, - () -> new ForgeImpetusCapability(impetus))); - } - } - - // i do not know why we need super here - private static <E extends Entity> SimpleProvider<? super CapEntityIotaHolder.Wrapper> wrapItemEntityDelegate(E entity, - Function<E, ItemDelegatingEntityIotaHolder> make) { - return provide(entity, HexCapabilities.IOTA, - () -> new CapEntityIotaHolder.Wrapper(make.apply(entity))); - } - - private static <CAP> SimpleProvider<CAP> provide(Entity entity, Capability<CAP> capability, - NonNullSupplier<CAP> supplier) { - return provide(entity::isRemoved, capability, supplier); - } - - private static <CAP> SimpleProvider<CAP> provide(BlockEntity be, Capability<CAP> capability, - NonNullSupplier<CAP> supplier) { - return provide(be::isRemoved, capability, supplier); - } - - public static <CAP> SimpleProvider<CAP> provide(ItemStack stack, Capability<CAP> capability, - NonNullSupplier<CAP> supplier) { - return provide(stack::isEmpty, capability, supplier); - } - - private static <CAP> SimpleProvider<CAP> provide(BooleanSupplier invalidated, Capability<CAP> capability, - NonNullSupplier<CAP> supplier) { - return new SimpleProvider<>(invalidated, capability, LazyOptional.of(supplier)); - } - - public static <T, U extends T> ICapabilityProvider makeProvider(Capability<T> cap, U instance) { - LazyOptional<T> lazyInstanceButNotReally = LazyOptional.of(() -> instance); - return new SimpleProvider<>(() -> false, cap, lazyInstanceButNotReally); - } - - public record SimpleProvider<CAP>(BooleanSupplier invalidated, - Capability<CAP> capability, - LazyOptional<CAP> instance) implements ICapabilityProvider { - - @NotNull - @Override - public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) { - if (invalidated.getAsBoolean()) { - return LazyOptional.empty(); - } - - return cap == capability ? instance.cast() : LazyOptional.empty(); - } - } + /** Items that store a variable amount of media to their tag. */ + public static final ResourceLocation MEDIA_STORAGE_CAP = modLoc("media_holder"); + + /** Items that statically provide media. */ + public static final ResourceLocation MEDIA_STATIC_CAP = modLoc("media_item"); + + /** Items that store a packaged Hex. */ + public static final ResourceLocation HEX_HOLDER_CAP = modLoc("hex_item"); + + /** Items that have multiple visual variants. */ + public static final ResourceLocation VARIANT_ITEM_CAP = modLoc("variant_item"); + + /** Items that work as pigments. */ + public static final ResourceLocation PIGMENT_CAP = modLoc("pigment"); + + public static final ResourceLocation CURIO_CAP = modLoc("curio"); + + public static final ResourceLocation IMPETUS_HANDLER = modLoc("impetus_items"); + + /** Used to render the pattern spiral around players while casting. */ + public static final ResourceLocation PATTERN_SPIRAL = modLoc("pattern_spiral"); + + public static void registerCaps(RegisterCapabilitiesEvent evt) { + evt.register(ADMediaHolder.class); + evt.register(ADIotaHolder.class); + evt.register(ADHexHolder.class); + evt.register(ADPigment.class); + } + + public static void attachItemCaps(AttachCapabilitiesEvent<ItemStack> evt) { + ItemStack stack = evt.getObject(); + + if (stack.getItem() instanceof MediaHolderItem holder) { + evt.addCapability( + MEDIA_STORAGE_CAP, + provide(stack, HexCapabilities.MEDIA, () -> new CapItemMediaHolder(holder, stack))); + } else if (stack.is(HexItems.AMETHYST_DUST)) { + evt.addCapability( + MEDIA_STATIC_CAP, + provide( + stack, + HexCapabilities.MEDIA, + () -> + new CapStaticMediaHolder( + HexConfig.common()::dustMediaAmount, + ADMediaHolder.AMETHYST_DUST_PRIORITY, + stack))); + } else if (stack.is(Items.AMETHYST_SHARD)) { + evt.addCapability( + MEDIA_STATIC_CAP, + provide( + stack, + HexCapabilities.MEDIA, + () -> + new CapStaticMediaHolder( + HexConfig.common()::shardMediaAmount, + ADMediaHolder.AMETHYST_SHARD_PRIORITY, + stack))); + } else if (stack.is(HexItems.CHARGED_AMETHYST)) { + evt.addCapability( + MEDIA_STATIC_CAP, + provide( + stack, + HexCapabilities.MEDIA, + () -> + new CapStaticMediaHolder( + HexConfig.common()::chargedCrystalMediaAmount, + ADMediaHolder.CHARGED_AMETHYST_PRIORITY, + stack))); + } else if (stack.is(HexItems.QUENCHED_SHARD)) { + // no one uses the config + evt.addCapability( + MEDIA_STATIC_CAP, + provide( + stack, + HexCapabilities.MEDIA, + () -> + new CapStaticMediaHolder( + () -> MediaConstants.QUENCHED_SHARD_UNIT, + ADMediaHolder.QUENCHED_SHARD_PRIORITY, + stack))); + } else if (stack.is(HexBlocks.QUENCHED_ALLAY.asItem())) { + // no one uses the config + evt.addCapability( + MEDIA_STATIC_CAP, + provide( + stack, + HexCapabilities.MEDIA, + () -> + new CapStaticMediaHolder( + () -> MediaConstants.QUENCHED_BLOCK_UNIT, + ADMediaHolder.QUENCHED_ALLAY_PRIORITY, + stack))); + } + + if (stack.getItem() instanceof IotaHolderItem holder) { + evt.addCapability( + IOTA_STORAGE_CAP, + provide(stack, HexCapabilities.IOTA, () -> new CapItemIotaHolder(holder, stack))); + } else if (stack.is(Items.PUMPKIN_PIE)) { + // haha yes + evt.addCapability( + IOTA_STATIC_CAP, + provide( + stack, + HexCapabilities.IOTA, + () -> new CapStaticIotaHolder((s) -> new DoubleIota(Math.PI * s.getCount()), stack))); + } + + if (stack.getItem() instanceof HexHolderItem holder) { + evt.addCapability( + HEX_HOLDER_CAP, + provide(stack, HexCapabilities.STORED_HEX, () -> new CapItemHexHolder(holder, stack))); + } + if (stack.getItem() instanceof VariantItem variantItem) { + evt.addCapability( + VARIANT_ITEM_CAP, + provide( + stack, + HexCapabilities.VARIANT_ITEM, + () -> new CapItemVariantItem(variantItem, stack))); + } + + if (stack.getItem() instanceof PigmentItem pigment) { + evt.addCapability( + PIGMENT_CAP, + provide(stack, HexCapabilities.COLOR, () -> new CapItemPigment(pigment, stack))); + } + + if (IXplatAbstractions.INSTANCE.isModPresent(HexInterop.Forge.CURIOS_API_ID) + && stack.getItem() instanceof HexBaubleItem) { + evt.addCapability(CURIO_CAP, CuriosApiInterop.curioCap(stack)); + } + } + + public static void attachEntityCaps(AttachCapabilitiesEvent<Entity> evt) { + var entity = evt.getObject(); + if (entity instanceof ItemEntity item) { + evt.addCapability( + IOTA_STORAGE_CAP, + wrapItemEntityDelegate(item, ItemDelegatingEntityIotaHolder.ToItemEntity::new)); + } else if (entity instanceof ItemFrame frame) { + evt.addCapability( + IOTA_STORAGE_CAP, + wrapItemEntityDelegate(frame, ItemDelegatingEntityIotaHolder.ToItemFrame::new)); + } else if (entity instanceof EntityWallScroll scroll) { + evt.addCapability( + IOTA_STORAGE_CAP, + wrapItemEntityDelegate(scroll, ItemDelegatingEntityIotaHolder.ToWallScroll::new)); + } else if (entity instanceof Player player) { + evt.addCapability( + PATTERN_SPIRAL, + provide( + player, + HexCapabilities.CLIENT_CASTING_STACK, + () -> new CapClientCastingStack(player, new ClientCastingStack()))); + } + } + + public static void attachBlockEntityCaps(AttachCapabilitiesEvent<BlockEntity> evt) { + if (evt.getObject() instanceof BlockEntityAbstractImpetus impetus) { + evt.addCapability( + IMPETUS_HANDLER, + provide( + impetus, ForgeCapabilities.ITEM_HANDLER, () -> new ForgeImpetusCapability(impetus))); + } + } + + // i do not know why we need super here + private static <E extends Entity> + SimpleProvider<? super CapEntityIotaHolder.Wrapper> wrapItemEntityDelegate( + E entity, Function<E, ItemDelegatingEntityIotaHolder> make) { + return provide( + entity, HexCapabilities.IOTA, () -> new CapEntityIotaHolder.Wrapper(make.apply(entity))); + } + + private static <CAP> SimpleProvider<CAP> provide( + Entity entity, Capability<CAP> capability, NonNullSupplier<CAP> supplier) { + return provide(entity::isRemoved, capability, supplier); + } + + private static <CAP> SimpleProvider<CAP> provide( + BlockEntity be, Capability<CAP> capability, NonNullSupplier<CAP> supplier) { + return provide(be::isRemoved, capability, supplier); + } + + public static <CAP> SimpleProvider<CAP> provide( + ItemStack stack, Capability<CAP> capability, NonNullSupplier<CAP> supplier) { + return provide(stack::isEmpty, capability, supplier); + } + + private static <CAP> SimpleProvider<CAP> provide( + BooleanSupplier invalidated, Capability<CAP> capability, NonNullSupplier<CAP> supplier) { + return new SimpleProvider<>(invalidated, capability, LazyOptional.of(supplier)); + } + + public static <T, U extends T> ICapabilityProvider makeProvider(Capability<T> cap, U instance) { + LazyOptional<T> lazyInstanceButNotReally = LazyOptional.of(() -> instance); + return new SimpleProvider<>(() -> false, cap, lazyInstanceButNotReally); + } + + public record SimpleProvider<CAP>( + BooleanSupplier invalidated, Capability<CAP> capability, LazyOptional<CAP> instance) + implements ICapabilityProvider { + + @NotNull @Override + public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) { + if (invalidated.getAsBoolean()) { + return LazyOptional.empty(); + } + return cap == capability ? instance.cast() : LazyOptional.empty(); + } + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/ForgeImpetusCapability.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/ForgeImpetusCapability.java index 9da53fa9a5..58115f6ae6 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/ForgeImpetusCapability.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/ForgeImpetusCapability.java @@ -6,49 +6,47 @@ import org.jetbrains.annotations.NotNull; public record ForgeImpetusCapability(BlockEntityAbstractImpetus impetus) implements IItemHandler { - @Override - public int getSlots() { - return 1; - } - - @NotNull - @Override - public ItemStack getStackInSlot(int slot) { - return ItemStack.EMPTY; - } - - @NotNull - @Override - public ItemStack insertItem(int slot, @NotNull ItemStack originalStack, boolean simulate) { - if (!isItemValid(slot, originalStack)) { - return originalStack; - } - - ItemStack stack = originalStack.copy(); - - if (!simulate) { - impetus.insertMedia(stack); - } else { - impetus.extractMediaFromInsertedItem(stack, false); // Media goes nowhere, since nothing is actually - // being done - } - - return stack; - } - - @NotNull - @Override - public ItemStack extractItem(int slot, int amount, boolean simulate) { - return ItemStack.EMPTY; - } - - @Override - public int getSlotLimit(int slot) { - return 64; - } - - @Override - public boolean isItemValid(int slot, @NotNull ItemStack stack) { - return impetus.canPlaceItem(slot, stack); - } + @Override + public int getSlots() { + return 1; + } + + @NotNull @Override + public ItemStack getStackInSlot(int slot) { + return ItemStack.EMPTY; + } + + @NotNull @Override + public ItemStack insertItem(int slot, @NotNull ItemStack originalStack, boolean simulate) { + if (!isItemValid(slot, originalStack)) { + return originalStack; + } + + ItemStack stack = originalStack.copy(); + + if (!simulate) { + impetus.insertMedia(stack); + } else { + impetus.extractMediaFromInsertedItem( + stack, false); // Media goes nowhere, since nothing is actually + // being done + } + + return stack; + } + + @NotNull @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + return ItemStack.EMPTY; + } + + @Override + public int getSlotLimit(int slot) { + return 64; + } + + @Override + public boolean isItemValid(int slot, @NotNull ItemStack stack) { + return impetus.canPlaceItem(slot, stack); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/HexCapabilities.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/HexCapabilities.java index 9db3e48d0a..9ee085cd73 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/HexCapabilities.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/HexCapabilities.java @@ -2,24 +2,23 @@ import at.petrak.hexcasting.api.addldata.*; import at.petrak.hexcasting.api.client.ClientCastingStack; +import java.util.function.Supplier; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.capabilities.CapabilityToken; -import java.util.function.Supplier; - public final class HexCapabilities { - public static final Capability<ADMediaHolder> MEDIA = CapabilityManager.get(new CapabilityToken<>() { - }); - public static final Capability<ADIotaHolder> IOTA = CapabilityManager.get(new CapabilityToken<>() { - }); - public static final Capability<ADHexHolder> STORED_HEX = CapabilityManager.get(new CapabilityToken<>() { - }); - public static final Capability<ADVariantItem> VARIANT_ITEM = CapabilityManager.get(new CapabilityToken<>() { - }); - public static final Capability<ADPigment> COLOR = CapabilityManager.get(new CapabilityToken<>() { - }); - public static final Capability<Supplier<ClientCastingStack>> CLIENT_CASTING_STACK = CapabilityManager.get(new CapabilityToken<>() { - }); + public static final Capability<ADMediaHolder> MEDIA = + CapabilityManager.get(new CapabilityToken<>() {}); + public static final Capability<ADIotaHolder> IOTA = + CapabilityManager.get(new CapabilityToken<>() {}); + public static final Capability<ADHexHolder> STORED_HEX = + CapabilityManager.get(new CapabilityToken<>() {}); + public static final Capability<ADVariantItem> VARIANT_ITEM = + CapabilityManager.get(new CapabilityToken<>() {}); + public static final Capability<ADPigment> COLOR = + CapabilityManager.get(new CapabilityToken<>() {}); + public static final Capability<Supplier<ClientCastingStack>> CLIENT_CASTING_STACK = + CapabilityManager.get(new CapabilityToken<>() {}); } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapClientCastingStack.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapClientCastingStack.java index bdba8678ca..8237c14bc7 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapClientCastingStack.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapClientCastingStack.java @@ -2,23 +2,25 @@ import at.petrak.hexcasting.api.client.ClientCastingStack; import at.petrak.hexcasting.forge.cap.HexCapabilities; +import java.util.function.Supplier; import net.minecraft.world.entity.player.Player; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.LogicalSide; -import java.util.function.Supplier; - -public record CapClientCastingStack(Player player, ClientCastingStack clientCastingStack) implements Supplier<ClientCastingStack> { - @Override - public ClientCastingStack get() { - return clientCastingStack; - } +public record CapClientCastingStack(Player player, ClientCastingStack clientCastingStack) + implements Supplier<ClientCastingStack> { + @Override + public ClientCastingStack get() { + return clientCastingStack; + } - @SubscribeEvent - public static void tickClientPlayer(TickEvent.PlayerTickEvent evt) { - if (evt.side == LogicalSide.CLIENT && !evt.player.isDeadOrDying()) - evt.player.getCapability(HexCapabilities.CLIENT_CASTING_STACK).resolve() - .ifPresent(CastingStack -> CastingStack.get().tick()); - } + @SubscribeEvent + public static void tickClientPlayer(TickEvent.PlayerTickEvent evt) { + if (evt.side == LogicalSide.CLIENT && !evt.player.isDeadOrDying()) + evt.player + .getCapability(HexCapabilities.CLIENT_CASTING_STACK) + .resolve() + .ifPresent(CastingStack -> CastingStack.get().tick()); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapEntityIotaHolder.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapEntityIotaHolder.java index a8623e6249..8f1843c689 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapEntityIotaHolder.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapEntityIotaHolder.java @@ -8,37 +8,36 @@ import org.jetbrains.annotations.Nullable; public abstract class CapEntityIotaHolder implements ADIotaHolder { - public static class Wrapper extends CapEntityIotaHolder { - private final ItemDelegatingEntityIotaHolder inner; - - public Wrapper(ItemDelegatingEntityIotaHolder inner) { - this.inner = inner; - } - - - @Override - public @Nullable CompoundTag readIotaTag() { - return inner.readIotaTag(); - } - - @Override - public boolean writeable() { - return inner.writeable(); - } - - @Override - public boolean writeIota(@Nullable Iota iota, boolean simulate) { - return inner.writeIota(iota, simulate); - } - - @Override - public @Nullable Iota readIota(ServerLevel world) { - return inner.readIota(world); - } - - @Override - public @Nullable Iota emptyIota() { - return inner.emptyIota(); - } - } + public static class Wrapper extends CapEntityIotaHolder { + private final ItemDelegatingEntityIotaHolder inner; + + public Wrapper(ItemDelegatingEntityIotaHolder inner) { + this.inner = inner; + } + + @Override + public @Nullable CompoundTag readIotaTag() { + return inner.readIotaTag(); + } + + @Override + public boolean writeable() { + return inner.writeable(); + } + + @Override + public boolean writeIota(@Nullable Iota iota, boolean simulate) { + return inner.writeIota(iota, simulate); + } + + @Override + public @Nullable Iota readIota(ServerLevel world) { + return inner.readIota(world); + } + + @Override + public @Nullable Iota emptyIota() { + return inner.emptyIota(); + } + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemHexHolder.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemHexHolder.java index 6fb0f0b1d6..a1fb9462a6 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemHexHolder.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemHexHolder.java @@ -1,45 +1,43 @@ package at.petrak.hexcasting.forge.cap.adimpl; import at.petrak.hexcasting.api.addldata.ADHexHolder; -import at.petrak.hexcasting.api.item.HexHolderItem; import at.petrak.hexcasting.api.casting.iota.Iota; +import at.petrak.hexcasting.api.item.HexHolderItem; import at.petrak.hexcasting.api.pigment.FrozenPigment; +import java.util.List; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Nullable; -import java.util.List; - -public record CapItemHexHolder(HexHolderItem holder, - ItemStack stack) implements ADHexHolder { - - @Override - public boolean canDrawMediaFromInventory() { - return holder.canDrawMediaFromInventory(stack); - } - - @Override - public boolean hasHex() { - return holder.hasHex(stack); - } - - @Override - public @Nullable List<Iota> getHex(ServerLevel level) { - return holder.getHex(stack, level); - } - - @Override - public void writeHex(List<Iota> patterns, @Nullable FrozenPigment pigment, long media) { - holder.writeHex(stack, patterns, pigment, media); - } - - @Override - public void clearHex() { - holder.clearHex(stack); - } - - @Override - public @Nullable FrozenPigment getPigment() { - return holder.getPigment(stack); - } +public record CapItemHexHolder(HexHolderItem holder, ItemStack stack) implements ADHexHolder { + + @Override + public boolean canDrawMediaFromInventory() { + return holder.canDrawMediaFromInventory(stack); + } + + @Override + public boolean hasHex() { + return holder.hasHex(stack); + } + + @Override + public @Nullable List<Iota> getHex(ServerLevel level) { + return holder.getHex(stack, level); + } + + @Override + public void writeHex(List<Iota> patterns, @Nullable FrozenPigment pigment, long media) { + holder.writeHex(stack, patterns, pigment, media); + } + + @Override + public void clearHex() { + holder.clearHex(stack); + } + + @Override + public @Nullable FrozenPigment getPigment() { + return holder.getPigment(stack); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemIotaHolder.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemIotaHolder.java index 29caaeb0d0..28fdd190fb 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemIotaHolder.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemIotaHolder.java @@ -1,47 +1,43 @@ package at.petrak.hexcasting.forge.cap.adimpl; import at.petrak.hexcasting.api.addldata.ADIotaHolder; -import at.petrak.hexcasting.api.item.IotaHolderItem; import at.petrak.hexcasting.api.casting.iota.Iota; +import at.petrak.hexcasting.api.item.IotaHolderItem; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Nullable; -public record CapItemIotaHolder(IotaHolderItem holder, - ItemStack stack) implements ADIotaHolder { +public record CapItemIotaHolder(IotaHolderItem holder, ItemStack stack) implements ADIotaHolder { - @Override - public @Nullable - CompoundTag readIotaTag() { - return holder.readIotaTag(stack); - } + @Override + public @Nullable CompoundTag readIotaTag() { + return holder.readIotaTag(stack); + } - @Override - public @Nullable - Iota readIota(ServerLevel world) { - return holder.readIota(stack, world); - } + @Override + public @Nullable Iota readIota(ServerLevel world) { + return holder.readIota(stack, world); + } - @Override - public @Nullable - Iota emptyIota() { - return holder.emptyIota(stack); - } + @Override + public @Nullable Iota emptyIota() { + return holder.emptyIota(stack); + } - @Override - public boolean writeIota(@Nullable Iota iota, boolean simulate) { - if (!holder.canWrite(stack, iota)) { - return false; - } - if (!simulate) { - holder.writeDatum(stack, iota); - } - return true; - } + @Override + public boolean writeIota(@Nullable Iota iota, boolean simulate) { + if (!holder.canWrite(stack, iota)) { + return false; + } + if (!simulate) { + holder.writeDatum(stack, iota); + } + return true; + } - @Override - public boolean writeable() { - return holder.writeable(stack); - } + @Override + public boolean writeable() { + return holder.writeable(stack); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemMediaHolder.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemMediaHolder.java index 7f84f1d154..9072b236fc 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemMediaHolder.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemMediaHolder.java @@ -4,54 +4,51 @@ import at.petrak.hexcasting.api.item.MediaHolderItem; import net.minecraft.world.item.ItemStack; -/** - * Things that read/write media amounts from an itemstack - */ -public record CapItemMediaHolder(MediaHolderItem holder, - ItemStack stack) implements ADMediaHolder { - - @Override - public long getMedia() { - return holder.getMedia(stack); - } - - @Override - public long getMaxMedia() { - return holder.getMaxMedia(stack); - } - - @Override - public void setMedia(long media) { - holder.setMedia(stack, media); - } - - @Override - public boolean canRecharge() { - return holder.canRecharge(stack); - } - - @Override - public boolean canProvide() { - return holder.canProvideMedia(stack); - } - - @Override - public int getConsumptionPriority() { - return holder.getConsumptionPriority(stack); - } - - @Override - public boolean canConstructBattery() { - return false; - } - - @Override - public long withdrawMedia(long cost, boolean simulate) { - return holder.withdrawMedia(stack, cost, simulate); - } - - @Override - public long insertMedia(long amount, boolean simulate) { - return holder.insertMedia(stack, amount, simulate); - } +/** Things that read/write media amounts from an itemstack */ +public record CapItemMediaHolder(MediaHolderItem holder, ItemStack stack) implements ADMediaHolder { + + @Override + public long getMedia() { + return holder.getMedia(stack); + } + + @Override + public long getMaxMedia() { + return holder.getMaxMedia(stack); + } + + @Override + public void setMedia(long media) { + holder.setMedia(stack, media); + } + + @Override + public boolean canRecharge() { + return holder.canRecharge(stack); + } + + @Override + public boolean canProvide() { + return holder.canProvideMedia(stack); + } + + @Override + public int getConsumptionPriority() { + return holder.getConsumptionPriority(stack); + } + + @Override + public boolean canConstructBattery() { + return false; + } + + @Override + public long withdrawMedia(long cost, boolean simulate) { + return holder.withdrawMedia(stack, cost, simulate); + } + + @Override + public long insertMedia(long amount, boolean simulate) { + return holder.insertMedia(stack, amount, simulate); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemPigment.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemPigment.java index 68d7eb719a..5e865ac0a9 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemPigment.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemPigment.java @@ -3,14 +3,12 @@ import at.petrak.hexcasting.api.addldata.ADPigment; import at.petrak.hexcasting.api.item.PigmentItem; import at.petrak.hexcasting.api.pigment.ColorProvider; -import net.minecraft.world.item.ItemStack; - import java.util.UUID; +import net.minecraft.world.item.ItemStack; -public record CapItemPigment(PigmentItem holder, - ItemStack stack) implements ADPigment { - @Override - public ColorProvider provideColor(UUID owner) { - return holder.provideColor(this.stack, owner); - } +public record CapItemPigment(PigmentItem holder, ItemStack stack) implements ADPigment { + @Override + public ColorProvider provideColor(UUID owner) { + return holder.provideColor(this.stack, owner); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemVariantItem.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemVariantItem.java index 19c54fea75..d71fb07b21 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemVariantItem.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemVariantItem.java @@ -4,19 +4,20 @@ import at.petrak.hexcasting.api.item.VariantItem; import net.minecraft.world.item.ItemStack; -public record CapItemVariantItem(VariantItem variantItem, ItemStack stack) implements ADVariantItem { - @Override - public int numVariants() { - return variantItem.numVariants(); - } +public record CapItemVariantItem(VariantItem variantItem, ItemStack stack) + implements ADVariantItem { + @Override + public int numVariants() { + return variantItem.numVariants(); + } - @Override - public int getVariant() { - return variantItem.getVariant(stack); - } + @Override + public int getVariant() { + return variantItem.getVariant(stack); + } - @Override - public void setVariant(int variant) { - variantItem.setVariant(stack, variant); - } + @Override + public void setVariant(int variant) { + variantItem.setVariant(stack, variant); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapStaticIotaHolder.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapStaticIotaHolder.java index f94cd93455..1178d7979d 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapStaticIotaHolder.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapStaticIotaHolder.java @@ -3,36 +3,33 @@ import at.petrak.hexcasting.api.addldata.ADIotaHolder; import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; +import java.util.function.Function; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Nullable; -import java.util.function.Function; - -public record CapStaticIotaHolder(Function<ItemStack, Iota> provider, - ItemStack stack) implements ADIotaHolder { +public record CapStaticIotaHolder(Function<ItemStack, Iota> provider, ItemStack stack) + implements ADIotaHolder { - @Override - public @Nullable - CompoundTag readIotaTag() { - var iota = provider.apply(stack); - return iota == null ? null : IotaType.serialize(iota); - } + @Override + public @Nullable CompoundTag readIotaTag() { + var iota = provider.apply(stack); + return iota == null ? null : IotaType.serialize(iota); + } - @Override - public @Nullable - Iota readIota(ServerLevel world) { - return provider.apply(stack); - } + @Override + public @Nullable Iota readIota(ServerLevel world) { + return provider.apply(stack); + } - @Override - public boolean writeable() { - return false; - } + @Override + public boolean writeable() { + return false; + } - @Override - public boolean writeIota(@Nullable Iota iota, boolean simulate) { - return false; - } + @Override + public boolean writeIota(@Nullable Iota iota, boolean simulate) { + return false; + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapStaticMediaHolder.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapStaticMediaHolder.java index e1c7f6f566..db401f7cc0 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapStaticMediaHolder.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapStaticMediaHolder.java @@ -1,62 +1,58 @@ package at.petrak.hexcasting.forge.cap.adimpl; import at.petrak.hexcasting.api.addldata.ADMediaHolder; -import net.minecraft.world.item.ItemStack; - import java.util.function.Supplier; +import net.minecraft.world.item.ItemStack; -/** - * Things that always hold a constant amount of media, like amethyst - */ -public record CapStaticMediaHolder(Supplier<Long> baseWorth, - int consumptionPriority, - ItemStack stack) implements ADMediaHolder { - @Override - public long getMedia() { - return baseWorth.get() * stack.getCount(); - } - - @Override - public long getMaxMedia() { - return getMedia(); - } - - @Override - public void setMedia(long media) { - // NO-OP - } - - @Override - public boolean canRecharge() { - return false; - } - - @Override - public boolean canProvide() { - return true; - } - - @Override - public int getConsumptionPriority() { - return consumptionPriority; - } - - @Override - public boolean canConstructBattery() { - return true; - } - - @Override - public long withdrawMedia(long cost, boolean simulate) { - long worth = baseWorth.get(); - if (cost < 0) { - cost = worth * stack.getCount(); - } - double itemsRequired = cost / (double) worth; - int itemsUsed = Math.min((int) Math.ceil(itemsRequired), stack.getCount()); - if (!simulate) { - stack.shrink(itemsUsed); - } - return itemsUsed * worth; - } +/** Things that always hold a constant amount of media, like amethyst */ +public record CapStaticMediaHolder( + Supplier<Long> baseWorth, int consumptionPriority, ItemStack stack) implements ADMediaHolder { + @Override + public long getMedia() { + return baseWorth.get() * stack.getCount(); + } + + @Override + public long getMaxMedia() { + return getMedia(); + } + + @Override + public void setMedia(long media) { + // NO-OP + } + + @Override + public boolean canRecharge() { + return false; + } + + @Override + public boolean canProvide() { + return true; + } + + @Override + public int getConsumptionPriority() { + return consumptionPriority; + } + + @Override + public boolean canConstructBattery() { + return true; + } + + @Override + public long withdrawMedia(long cost, boolean simulate) { + long worth = baseWorth.get(); + if (cost < 0) { + cost = worth * stack.getCount(); + } + double itemsRequired = cost / (double) worth; + int itemsUsed = Math.min((int) Math.ceil(itemsRequired), stack.getCount()); + if (!simulate) { + stack.shrink(itemsUsed); + } + return itemsUsed * worth; + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexConditionsBuilder.java b/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexConditionsBuilder.java index 93b1cfe529..7b4e716ebb 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexConditionsBuilder.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexConditionsBuilder.java @@ -1,6 +1,9 @@ package at.petrak.hexcasting.forge.datagen; import at.petrak.hexcasting.datagen.IXplatConditionsBuilder; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; import net.minecraft.advancements.CriterionTriggerInstance; import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.data.recipes.RecipeBuilder; @@ -12,53 +15,51 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - public class ForgeHexConditionsBuilder implements IXplatConditionsBuilder, IConditionBuilder { - private final List<ICondition> conditions = new ArrayList<>(); - private final RecipeBuilder parent; + private final List<ICondition> conditions = new ArrayList<>(); + private final RecipeBuilder parent; - public ForgeHexConditionsBuilder(RecipeBuilder parent) { - this.parent = parent; - } + public ForgeHexConditionsBuilder(RecipeBuilder parent) { + this.parent = parent; + } - @Override - public IXplatConditionsBuilder whenModLoaded(String modid) { - conditions.add(modLoaded(modid)); - return this; - } + @Override + public IXplatConditionsBuilder whenModLoaded(String modid) { + conditions.add(modLoaded(modid)); + return this; + } - @Override - public IXplatConditionsBuilder whenModMissing(String modid) { - conditions.add(not(modLoaded(modid))); - return this; - } + @Override + public IXplatConditionsBuilder whenModMissing(String modid) { + conditions.add(not(modLoaded(modid))); + return this; + } - @Override - public @NotNull RecipeBuilder unlockedBy(@NotNull String string, - @NotNull CriterionTriggerInstance criterionTriggerInstance) { - return parent.unlockedBy(string, criterionTriggerInstance); - } + @Override + public @NotNull RecipeBuilder unlockedBy( + @NotNull String string, @NotNull CriterionTriggerInstance criterionTriggerInstance) { + return parent.unlockedBy(string, criterionTriggerInstance); + } - @Override - public @NotNull RecipeBuilder group(@Nullable String string) { - return parent.group(string); - } + @Override + public @NotNull RecipeBuilder group(@Nullable String string) { + return parent.group(string); + } - @Override - public @NotNull Item getResult() { - return parent.getResult(); - } + @Override + public @NotNull Item getResult() { + return parent.getResult(); + } - @Override - public void save(@NotNull Consumer<FinishedRecipe> consumer, @NotNull ResourceLocation resourceLocation) { - var conditionalBuilder = ConditionalRecipe.builder(); - for (ICondition condition : conditions) { - conditionalBuilder.addCondition(condition); - } - conditionalBuilder.addRecipe(recipeConsumer -> parent.save(recipeConsumer, resourceLocation)) - .build(consumer, resourceLocation); - } + @Override + public void save( + @NotNull Consumer<FinishedRecipe> consumer, @NotNull ResourceLocation resourceLocation) { + var conditionalBuilder = ConditionalRecipe.builder(); + for (ICondition condition : conditions) { + conditionalBuilder.addCondition(condition); + } + conditionalBuilder + .addRecipe(recipeConsumer -> parent.save(recipeConsumer, resourceLocation)) + .build(consumer, resourceLocation); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexDataGenerators.java b/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexDataGenerators.java index c5ed351ea7..6f0debddde 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexDataGenerators.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexDataGenerators.java @@ -16,6 +16,10 @@ import at.petrak.hexcasting.forge.recipe.ForgeModConditionalIngredient; import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.google.gson.JsonObject; +import java.util.EnumMap; +import java.util.List; +import java.util.Set; +import java.util.stream.Stream; import net.minecraft.core.RegistrySetBuilder; import net.minecraft.core.registries.Registries; import net.minecraft.data.DataGenerator; @@ -35,155 +39,161 @@ import net.minecraftforge.data.event.GatherDataEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; -import java.util.EnumMap; -import java.util.List; -import java.util.Set; -import java.util.stream.Stream; - public class ForgeHexDataGenerators { - @SubscribeEvent - public static void generateData(GatherDataEvent ev) { - if (System.getProperty("hexcasting.xplat_datagen") != null) { - configureXplatDatagen(ev); - } - if (System.getProperty("hexcasting.forge_datagen") != null) { - configureForgeDatagen(ev); - } - } - - private static void configureXplatDatagen(GatherDataEvent ev) { - HexAPI.LOGGER.info("Starting cross-platform datagen"); - - DataGenerator gen = ev.getGenerator(); - var output = gen.getPackOutput(); - var lookup = ev.getLookupProvider(); - ExistingFileHelper efh = ev.getExistingFileHelper(); - - // https://docs.minecraftforge.net/en/latest/datagen/server/datapackregistries/ - // https://github.com/MinecraftForge/MinecraftForge/pull/9580 - var datapackProvider = new DatapackBuiltinEntriesProvider( - output, - lookup, - new RegistrySetBuilder() - .add(Registries.DAMAGE_TYPE, HexDamageTypes::bootstrap), - Set.of(HexAPI.MOD_ID) - ); - var datapackLookup = datapackProvider.getRegistryProvider(); - - gen.addProvider(ev.includeClient(), new HexItemModels(output, efh)); - gen.addProvider(ev.includeClient(), new HexBlockStatesAndModels(output, efh)); - gen.addProvider(ev.includeServer(), new AdvancementProvider( - output, lookup, List.of(new HexAdvancements()) - )); - gen.addProvider(ev.includeServer(), datapackProvider); - gen.addProvider(ev.includeServer(), new HexDamageTypeTagProvider(output, datapackLookup)); - } - - @SuppressWarnings({"DataFlowIssue", "UnreachableCode"}) - private static void configureForgeDatagen(GatherDataEvent ev) { - HexAPI.LOGGER.info("Starting Forge-specific datagen"); - - DataGenerator gen = ev.getGenerator(); - var output = gen.getPackOutput(); - var lookup = ev.getLookupProvider(); - ExistingFileHelper efh = ev.getExistingFileHelper(); - gen.addProvider(ev.includeServer(), new LootTableProvider( - output, Set.of(), List.of(new LootTableProvider.SubProviderEntry(HexLootTables::new, LootContextParamSets.ALL_PARAMS)) - )); - gen.addProvider(ev.includeServer(), new HexplatRecipes(output, INGREDIENTS, ForgeHexConditionsBuilder::new)); - - // TODO: refactor? - var xtags = IXplatAbstractions.INSTANCE.tags(); - var blockTagProvider = new HexBlockTagProvider(output, lookup, xtags); - ((TagsProviderEFHSetter) blockTagProvider).setEFH(efh); - gen.addProvider(ev.includeServer(), blockTagProvider); - var itemTagProvider = new HexItemTagProvider(output, lookup, blockTagProvider, IXplatAbstractions.INSTANCE.tags()); - ((TagsProviderEFHSetter) itemTagProvider).setEFH(efh); - gen.addProvider(ev.includeServer(), itemTagProvider); - var hexTagProvider = new HexActionTagProvider(output, lookup); - ((TagsProviderEFHSetter) hexTagProvider).setEFH(efh); - gen.addProvider(ev.includeServer(), hexTagProvider); - - gen.addProvider(ev.includeServer(), new ForgeHexLootModGen(output)); - } - - private static final IXplatIngredients INGREDIENTS = new IXplatIngredients() { - @Override - public Ingredient glowstoneDust() { - return Ingredient.of(Tags.Items.DUSTS_GLOWSTONE); - } - - @Override - public Ingredient leather() { - return Ingredient.of(Tags.Items.LEATHER); - } - - @Override - public Ingredient ironNugget() { - return Ingredient.of(Tags.Items.NUGGETS_IRON); - } - - @Override - public Ingredient goldNugget() { - return Ingredient.of(Tags.Items.NUGGETS_GOLD); - } - - @Override - public Ingredient copperIngot() { - return Ingredient.of(Tags.Items.INGOTS_COPPER); - } - - @Override - public Ingredient ironIngot() { - return Ingredient.of(Tags.Items.INGOTS_IRON); - } - - @Override - public Ingredient goldIngot() { - return Ingredient.of(Tags.Items.INGOTS_GOLD); - } - - @Override - public EnumMap<DyeColor, Ingredient> dyes() { - var out = new EnumMap<DyeColor, Ingredient>(DyeColor.class); - for (var col : DyeColor.values()) { - out.put(col, Ingredient.of(col.getTag())); - } - return out; - } - - @Override - public Ingredient stick() { - return Ingredient.fromValues(Stream.of( - new Ingredient.ItemValue(new ItemStack(Items.STICK)), - new Ingredient.TagValue(ItemTags.create(new ResourceLocation("forge", "rods/wooden"))) - )); - } - - @Override - public Ingredient whenModIngredient(Ingredient defaultIngredient, String modid, Ingredient modIngredient) { - return ForgeModConditionalIngredient.of(defaultIngredient, modid, modIngredient); - } - - // https://github.com/vectorwing/FarmersDelight/blob/1.18.2/src/generated/resources/data/farmersdelight/recipes/cutting/amethyst_block.json - @Override - public FarmersDelightToolIngredient axeStrip() { - return () -> { - JsonObject object = new JsonObject(); - object.addProperty("type", "farmersdelight:tool_action"); - object.addProperty("action", ToolActions.AXE_STRIP.name()); - return object; - }; - } - - @Override - public FarmersDelightToolIngredient axeDig() { - return () -> { - JsonObject object = new JsonObject(); - object.addProperty("type", "farmersdelight:tool_action"); - object.addProperty("action", ToolActions.AXE_DIG.name()); - return object; - }; - } - }; + @SubscribeEvent + public static void generateData(GatherDataEvent ev) { + if (System.getProperty("hexcasting.xplat_datagen") != null) { + configureXplatDatagen(ev); + } + if (System.getProperty("hexcasting.forge_datagen") != null) { + configureForgeDatagen(ev); + } + } + + private static void configureXplatDatagen(GatherDataEvent ev) { + HexAPI.LOGGER.info("Starting cross-platform datagen"); + + DataGenerator gen = ev.getGenerator(); + var output = gen.getPackOutput(); + var lookup = ev.getLookupProvider(); + ExistingFileHelper efh = ev.getExistingFileHelper(); + + // https://docs.minecraftforge.net/en/latest/datagen/server/datapackregistries/ + // https://github.com/MinecraftForge/MinecraftForge/pull/9580 + var datapackProvider = + new DatapackBuiltinEntriesProvider( + output, + lookup, + new RegistrySetBuilder().add(Registries.DAMAGE_TYPE, HexDamageTypes::bootstrap), + Set.of(HexAPI.MOD_ID)); + var datapackLookup = datapackProvider.getRegistryProvider(); + + gen.addProvider(ev.includeClient(), new HexItemModels(output, efh)); + gen.addProvider(ev.includeClient(), new HexBlockStatesAndModels(output, efh)); + gen.addProvider( + ev.includeServer(), + new AdvancementProvider(output, lookup, List.of(new HexAdvancements()))); + gen.addProvider(ev.includeServer(), datapackProvider); + gen.addProvider(ev.includeServer(), new HexDamageTypeTagProvider(output, datapackLookup)); + } + + @SuppressWarnings({"DataFlowIssue", "UnreachableCode"}) + private static void configureForgeDatagen(GatherDataEvent ev) { + HexAPI.LOGGER.info("Starting Forge-specific datagen"); + + DataGenerator gen = ev.getGenerator(); + var output = gen.getPackOutput(); + var lookup = ev.getLookupProvider(); + ExistingFileHelper efh = ev.getExistingFileHelper(); + gen.addProvider( + ev.includeServer(), + new LootTableProvider( + output, + Set.of(), + List.of( + new LootTableProvider.SubProviderEntry( + HexLootTables::new, LootContextParamSets.ALL_PARAMS)))); + gen.addProvider( + ev.includeServer(), + new HexplatRecipes(output, INGREDIENTS, ForgeHexConditionsBuilder::new)); + + // TODO: refactor? + var xtags = IXplatAbstractions.INSTANCE.tags(); + var blockTagProvider = new HexBlockTagProvider(output, lookup, xtags); + ((TagsProviderEFHSetter) blockTagProvider).setEFH(efh); + gen.addProvider(ev.includeServer(), blockTagProvider); + var itemTagProvider = + new HexItemTagProvider( + output, lookup, blockTagProvider, IXplatAbstractions.INSTANCE.tags()); + ((TagsProviderEFHSetter) itemTagProvider).setEFH(efh); + gen.addProvider(ev.includeServer(), itemTagProvider); + var hexTagProvider = new HexActionTagProvider(output, lookup); + ((TagsProviderEFHSetter) hexTagProvider).setEFH(efh); + gen.addProvider(ev.includeServer(), hexTagProvider); + + gen.addProvider(ev.includeServer(), new ForgeHexLootModGen(output)); + } + + private static final IXplatIngredients INGREDIENTS = + new IXplatIngredients() { + @Override + public Ingredient glowstoneDust() { + return Ingredient.of(Tags.Items.DUSTS_GLOWSTONE); + } + + @Override + public Ingredient leather() { + return Ingredient.of(Tags.Items.LEATHER); + } + + @Override + public Ingredient ironNugget() { + return Ingredient.of(Tags.Items.NUGGETS_IRON); + } + + @Override + public Ingredient goldNugget() { + return Ingredient.of(Tags.Items.NUGGETS_GOLD); + } + + @Override + public Ingredient copperIngot() { + return Ingredient.of(Tags.Items.INGOTS_COPPER); + } + + @Override + public Ingredient ironIngot() { + return Ingredient.of(Tags.Items.INGOTS_IRON); + } + + @Override + public Ingredient goldIngot() { + return Ingredient.of(Tags.Items.INGOTS_GOLD); + } + + @Override + public EnumMap<DyeColor, Ingredient> dyes() { + var out = new EnumMap<DyeColor, Ingredient>(DyeColor.class); + for (var col : DyeColor.values()) { + out.put(col, Ingredient.of(col.getTag())); + } + return out; + } + + @Override + public Ingredient stick() { + return Ingredient.fromValues( + Stream.of( + new Ingredient.ItemValue(new ItemStack(Items.STICK)), + new Ingredient.TagValue( + ItemTags.create(new ResourceLocation("forge", "rods/wooden"))))); + } + + @Override + public Ingredient whenModIngredient( + Ingredient defaultIngredient, String modid, Ingredient modIngredient) { + return ForgeModConditionalIngredient.of(defaultIngredient, modid, modIngredient); + } + + // https://github.com/vectorwing/FarmersDelight/blob/1.18.2/src/generated/resources/data/farmersdelight/recipes/cutting/amethyst_block.json + @Override + public FarmersDelightToolIngredient axeStrip() { + return () -> { + JsonObject object = new JsonObject(); + object.addProperty("type", "farmersdelight:tool_action"); + object.addProperty("action", ToolActions.AXE_STRIP.name()); + return object; + }; + } + + @Override + public FarmersDelightToolIngredient axeDig() { + return () -> { + JsonObject object = new JsonObject(); + object.addProperty("type", "farmersdelight:tool_action"); + object.addProperty("action", ToolActions.AXE_DIG.name()); + return object; + }; + } + }; } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexLootModGen.java b/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexLootModGen.java index d1a85e93e7..1ade224b8d 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexLootModGen.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexLootModGen.java @@ -12,29 +12,42 @@ import net.minecraftforge.common.loot.LootTableIdCondition; public class ForgeHexLootModGen extends GlobalLootModifierProvider { - public ForgeHexLootModGen(PackOutput output) { - super(output, HexAPI.MOD_ID); - } + public ForgeHexLootModGen(PackOutput output) { + super(output, HexAPI.MOD_ID); + } - @Override - protected void start() { - for (var injection : HexLootHandler.DEFAULT_SCROLL_INJECTS) { - var name = "scroll/%s/%s".formatted(injection.injectee().getNamespace(), injection.injectee().getPath()); - add(name, new ForgeHexScrollLootMod(new LootItemCondition[]{ - LootTableIdCondition.builder(injection.injectee()).build(), - }, injection.countRange())); - } + @Override + protected void start() { + for (var injection : HexLootHandler.DEFAULT_SCROLL_INJECTS) { + var name = + "scroll/%s/%s" + .formatted(injection.injectee().getNamespace(), injection.injectee().getPath()); + add( + name, + new ForgeHexScrollLootMod( + new LootItemCondition[] { + LootTableIdCondition.builder(injection.injectee()).build(), + }, + injection.countRange())); + } - for (var injection : HexLootHandler.DEFAULT_LORE_INJECTS) { - var name = "lore/%s/%s".formatted(injection.getNamespace(), injection.getPath()); - add(name, new ForgeHexLoreLootMod(new LootItemCondition[]{ - LootTableIdCondition.builder(injection).build(), - }, HexLootHandler.DEFAULT_LORE_CHANCE)); - } + for (var injection : HexLootHandler.DEFAULT_LORE_INJECTS) { + var name = "lore/%s/%s".formatted(injection.getNamespace(), injection.getPath()); + add( + name, + new ForgeHexLoreLootMod( + new LootItemCondition[] { + LootTableIdCondition.builder(injection).build(), + }, + HexLootHandler.DEFAULT_LORE_CHANCE)); + } - add("amethyst_cluster", new ForgeHexAmethystLootMod(new LootItemCondition[]{ - LootTableIdCondition.builder(Blocks.AMETHYST_CLUSTER.getLootTable()).build() - }, HexLootHandler.DEFAULT_SHARD_MODIFICATION)); - - } + add( + "amethyst_cluster", + new ForgeHexAmethystLootMod( + new LootItemCondition[] { + LootTableIdCondition.builder(Blocks.AMETHYST_CLUSTER.getLootTable()).build() + }, + HexLootHandler.DEFAULT_SHARD_MODIFICATION)); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/TagsProviderEFHSetter.java b/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/TagsProviderEFHSetter.java index ddda7d2966..633031bb3b 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/TagsProviderEFHSetter.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/TagsProviderEFHSetter.java @@ -3,5 +3,5 @@ import net.minecraftforge.common.data.ExistingFileHelper; public interface TagsProviderEFHSetter { - void setEFH(ExistingFileHelper efh); + void setEFH(ExistingFileHelper efh); } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/xplat/HexBlockStatesAndModels.java b/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/xplat/HexBlockStatesAndModels.java index f4e30e8a42..dc05a27b7a 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/xplat/HexBlockStatesAndModels.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/xplat/HexBlockStatesAndModels.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.forge.datagen.xplat; +import static net.minecraftforge.client.model.generators.ModelProvider.BLOCK_FOLDER; + import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.block.circle.BlockCircleComponent; import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicBookshelf; @@ -9,7 +11,6 @@ import at.petrak.hexcasting.common.lib.HexBlocks; import at.petrak.paucal.api.forge.datagen.PaucalBlockStateAndModelProvider; import net.minecraft.core.Direction; -import net.minecraft.data.DataGenerator; import net.minecraft.data.PackOutput; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Block; @@ -19,402 +20,591 @@ import net.minecraftforge.client.model.generators.ModelBuilder; import net.minecraftforge.common.data.ExistingFileHelper; -import static net.minecraftforge.client.model.generators.ModelProvider.BLOCK_FOLDER; - public class HexBlockStatesAndModels extends PaucalBlockStateAndModelProvider { - public HexBlockStatesAndModels(PackOutput output, ExistingFileHelper exFileHelper) { - super(output, HexAPI.MOD_ID, exFileHelper); - } - - @Override - protected void registerStatesAndModels() { - var slateModel = models().getExistingFile(modLoc("slate")); - getVariantBuilder(HexBlocks.SLATE).forAllStatesExcept(bs -> { - int rotationX = 0; - int rotationY = 0; - switch (bs.getValue(BlockSlate.ATTACH_FACE)) { - case CEILING -> rotationX = 180; - case WALL -> { - rotationX = 90; - rotationY = bs.getValue(BlockSlate.FACING).getOpposite().get2DDataValue() * 90; - } - } - return ConfiguredModel.builder() - .modelFile(slateModel) - .rotationX(rotationX) - .rotationY(rotationY) - .uvLock(true) - .build(); - }, BlockSlate.WATERLOGGED); - - impetus(HexBlocks.IMPETUS_EMPTY, "impetus/empty", "empty", false); - impetus(HexBlocks.IMPETUS_RIGHTCLICK, "impetus/rightclick", "rightclick", true); - impetus(HexBlocks.IMPETUS_LOOK, "impetus/look", "look", true); - impetus(HexBlocks.IMPETUS_REDSTONE, "impetus/redstone", "redstone", true); - doAllTheDirectrices(); - - var akashicRecordModel = models().withExistingParent("akashic_record", "block/block") - .renderType("translucent") - .texture("inner", modLoc("block/akashic_ligature")) - .texture("outer", modLoc("block/akashic_record")) - .texture("particle", modLoc("block/akashic_ligature")) - .element() - .cube("#outer") - .end() - .element() - .from(15.75f, 15.75f, 15.75f) - .to(0.25f, 0.25f, 0.25f) - .allFaces((dir, builder) -> builder.texture("#inner").rotation(ModelBuilder.FaceRotation.UPSIDE_DOWN)) - .end(); - - simpleBlock(HexBlocks.AKASHIC_RECORD, akashicRecordModel); - simpleBlockItem(HexBlocks.AKASHIC_RECORD, akashicRecordModel); - blockAndItem(HexBlocks.AKASHIC_LIGATURE, - models().cubeAll("akashic_ligature", modLoc("block/akashic_ligature"))); - - models().getBuilder("akashic_bookshelf") - .renderType("cutout") - .texture("front", modLoc("block/akashic_bookshelf")) - .texture("side", modLoc("block/akashic_bookshelf_horiz")) - .texture("top_bottom", modLoc("block/akashic_bookshelf_vert")) - .texture("particle", modLoc("block/akashic_bookshelf_vert")) - .element() - .allFaces((dir, builder) -> builder.texture(switch (dir) { - case DOWN, UP -> "#top_bottom"; - case EAST, SOUTH, WEST -> "#side"; - default -> "#front"; - }).cullface(dir)) - .end() - .element() - .face(Direction.NORTH).texture("#overlay").cullface(Direction.NORTH).tintindex(0); - - getVariantBuilder(HexBlocks.AKASHIC_BOOKSHELF).forAllStates(bs -> { - Direction dir = bs.getValue(BlockAkashicBookshelf.FACING); - - var builder = ConfiguredModel.builder(); - - if (bs.getValue(BlockAkashicBookshelf.HAS_BOOKS)) { - for (int i = 1; i <= 4; i++) { - var model = models().withExistingParent("akashic_bookshelf_" + i, - modLoc("block/akashic_bookshelf")) - .texture("overlay", modLoc("block/akashic_bookshelf_overlay_" + i)); - - builder.modelFile(model) - .rotationY(dir.getOpposite().get2DDataValue() * 90) - .uvLock(true); - if (i < 4) { - builder = builder.nextModel(); - } - } - } else { - var model = models().orientable("akashic_bookshelf_empty", - modLoc("block/akashic_bookshelf_horiz"), - modLoc("block/akashic_bookshelf"), - modLoc("block/akashic_bookshelf_vert")); - - if (dir == Direction.NORTH) { - simpleBlockItem(HexBlocks.AKASHIC_BOOKSHELF, model); - } - - builder.modelFile(model) - .rotationY(dir.getOpposite().get2DDataValue() * 90) - .uvLock(true); - } - - return builder.build(); - }); - - - blockAndItem(HexBlocks.SLATE_BLOCK, models().cubeAll("slate_block", modLoc("block/slate"))); - blockAndItem(HexBlocks.SLATE_TILES, models().cubeAll("block/deco/slate_tiles", modLoc("block/deco/slate_tiles"))); - blockAndItem(HexBlocks.SLATE_BRICKS, models().cubeAll("block/deco/slate_bricks", modLoc("block/deco/slate_bricks"))); - blockAndItem(HexBlocks.SLATE_BRICKS_SMALL, models().cubeAll("block/deco/slate_bricks_small", modLoc("block/deco/slate_bricks_small"))); - axisBlock(HexBlocks.SLATE_PILLAR, modLoc("block/deco/slate_pillar")); - blockAndItem(HexBlocks.AMETHYST_DUST_BLOCK, - models().singleTexture("amethyst_dust_block", modLoc(BLOCK_FOLDER + "/cube_half_mirrored"), "all", - modLoc("block/amethyst_dust_block"))); - blockAndItem(HexBlocks.AMETHYST_TILES, models().cubeAll("block/deco/amethyst_tiles", modLoc("block/deco/amethyst_tiles"))); - blockAndItem(HexBlocks.AMETHYST_BRICKS, models().cubeAll("block/deco/amethyst_bricks", modLoc("block/deco/amethyst_bricks"))); - blockAndItem(HexBlocks.AMETHYST_BRICKS_SMALL, models().cubeAll("block/deco/amethyst_bricks_small", modLoc("block/deco/amethyst_bricks_small"))); - directionalBlock(HexBlocks.AMETHYST_PILLAR, - models().cubeBottomTop("block/deco/amethyst_pillar", - modLoc("block/deco/amethyst_pillar_side"), - modLoc("block/deco/amethyst_pillar_bottom"), - modLoc("block/deco/amethyst_pillar_top"))); - blockAndItem(HexBlocks.SLATE_AMETHYST_TILES, models().cubeAll("block/deco/slate_amethyst_tiles", modLoc("block/deco/slate_amethyst_tiles"))); - - simpleBlock(HexBlocks.SLATE_AMETHYST_BRICKS, - new ConfiguredModel(models().cubeAll("block/deco/slate_amethyst_bricks_0", modLoc("block/deco/slate_amethyst_bricks_0"))), - new ConfiguredModel(models().cubeAll("block/deco/slate_amethyst_bricks_1", modLoc("block/deco/slate_amethyst_bricks_1"))), - new ConfiguredModel(models().cubeAll("block/deco/slate_amethyst_bricks_2", modLoc("block/deco/slate_amethyst_bricks_2"))) - ); - simpleBlockItem(HexBlocks.SLATE_AMETHYST_BRICKS, models().cubeAll("block/deco/slate_amethyst_bricks_0", modLoc("block/deco/slate_amethyst_bricks_0"))); - - simpleBlock(HexBlocks.SLATE_AMETHYST_BRICKS_SMALL, - new ConfiguredModel(models().cubeAll("block/deco/slate_amethyst_bricks_small_0", modLoc("block/deco/slate_amethyst_bricks_small_0"))), - new ConfiguredModel(models().cubeAll("block/deco/slate_amethyst_bricks_small_1", modLoc("block/deco/slate_amethyst_bricks_small_1"))), - new ConfiguredModel(models().cubeAll("block/deco/slate_amethyst_bricks_small_2", modLoc("block/deco/slate_amethyst_bricks_small_2"))) - ); - simpleBlockItem(HexBlocks.SLATE_AMETHYST_BRICKS_SMALL, models().cubeAll("block/deco/slate_amethyst_bricks_small_0", modLoc("block/deco/slate_amethyst_bricks_small_0"))); - - axisBlock(HexBlocks.SLATE_AMETHYST_PILLAR, modLoc("block/deco/slate_amethyst_pillar")); - cubeBlockAndItem(HexBlocks.SCROLL_PAPER, "scroll_paper"); - cubeBlockAndItem(HexBlocks.ANCIENT_SCROLL_PAPER, "ancient_scroll_paper"); - - blockAndItem(HexBlocks.SCROLL_PAPER_LANTERN, models().cubeBottomTop("scroll_paper_lantern", - modLoc("block/scroll_paper_lantern_side"), - modLoc("block/scroll_paper_lantern_bottom"), - modLoc("block/scroll_paper_lantern_top"))); - - blockAndItem(HexBlocks.ANCIENT_SCROLL_PAPER_LANTERN, - models().cubeBottomTop("ancient_scroll_paper_lantern", - modLoc("block/ancient_scroll_paper_lantern_side"), - modLoc("block/ancient_scroll_paper_lantern_bottom"), - modLoc("block/ancient_scroll_paper_lantern_top"))); - - axisBlock(HexBlocks.EDIFIED_LOG, modLoc("block/edified_log"), modLoc("block/edified_log_top")); - axisBlock(HexBlocks.EDIFIED_LOG_AMETHYST, modLoc("block/deco/edified_log_amethyst"), modLoc("block/edified_log_top")); - axisBlock(HexBlocks.EDIFIED_LOG_AVENTURINE, modLoc("block/deco/edified_log_aventurine"), modLoc("block/edified_log_top")); - axisBlock(HexBlocks.EDIFIED_LOG_CITRINE, modLoc("block/deco/edified_log_citrine"), modLoc("block/edified_log_top")); - axisBlock(HexBlocks.EDIFIED_LOG_PURPLE, modLoc("block/deco/edified_log_purple"), modLoc("block/edified_log_top")); - axisBlock(HexBlocks.STRIPPED_EDIFIED_LOG, modLoc("block/stripped_edified_log"), - modLoc("block/stripped_edified_log_top")); - axisBlock(HexBlocks.EDIFIED_WOOD, modLoc("block/edified_log"), modLoc("block/edified_log")); - axisBlock(HexBlocks.STRIPPED_EDIFIED_WOOD, modLoc("block/stripped_edified_log"), - modLoc("block/stripped_edified_log")); - - blockAndItem(HexBlocks.EDIFIED_PANEL, models().cubeAll("edified_panel", modLoc("block/edified_panel"))); - blockAndItem(HexBlocks.EDIFIED_TILE, models().cubeAll("edified_tile", modLoc("block/edified_tile"))); - - ResourceLocation leavesParent = new ResourceLocation("block/leaves"); - blockAndItem(HexBlocks.AMETHYST_EDIFIED_LEAVES, - models().withExistingParent("amethyst_edified_leaves", leavesParent) - .texture("all", modLoc("block/amethyst_edified_leaves")) - .renderType("cutout_mipped")); - blockAndItem(HexBlocks.AVENTURINE_EDIFIED_LEAVES, - models().withExistingParent("aventurine_edified_leaves", leavesParent) - .texture("all", modLoc("block/aventurine_edified_leaves")) - .renderType("cutout_mipped")); - blockAndItem(HexBlocks.CITRINE_EDIFIED_LEAVES, - models().withExistingParent("citrine_edified_leaves", leavesParent) - .texture("all", modLoc("block/citrine_edified_leaves")) - .renderType("cutout_mipped")); - - doorBlockWithRenderType(HexBlocks.EDIFIED_DOOR, modLoc("block/edified_door_lower"), modLoc("block" + - "/edified_door_upper"), "cutout"); - // door model via the given texture - trapdoorBlockWithRenderType(HexBlocks.EDIFIED_TRAPDOOR, modLoc("block/edified_trapdoor"), true, "cutout"); - - ResourceLocation planks1 = modLoc("block/edified_planks"); - BlockModelBuilder planksModel = models().cubeAll("edified_planks", planks1); - simpleBlock(HexBlocks.EDIFIED_PLANKS, ConfiguredModel.builder() - .modelFile(planksModel) - .weight(3) - .nextModel() - .modelFile(models().cubeAll("edified_planks_2", modLoc("block/edified_planks_2"))) - .weight(3) - .nextModel() - .modelFile(models().cubeAll("edified_planks_3", modLoc("block/edified_planks_3"))) - .build()); - simpleBlockItem(HexBlocks.EDIFIED_PLANKS, planksModel); - - stairsBlock(HexBlocks.EDIFIED_STAIRS, planks1); - fenceBlock(HexBlocks.EDIFIED_FENCE, planks1); - fenceGateBlock(HexBlocks.EDIFIED_FENCE_GATE, planks1); - slabBlock(HexBlocks.EDIFIED_SLAB, planks1, planks1); - buttonBlock(HexBlocks.EDIFIED_BUTTON, planks1); - pressurePlateBlock(HexBlocks.EDIFIED_PRESSURE_PLATE, planks1); - - var sconceModel = models().getExistingFile(modLoc("amethyst_sconce")); - simpleBlock(HexBlocks.SCONCE, sconceModel); - simpleBlockItem(HexBlocks.SCONCE, sconceModel); - - var conjuredModel = models().getBuilder("conjured").texture("particle", mcLoc("block/amethyst_block")) - .renderType("cutout"); - simpleBlock(HexBlocks.CONJURED_BLOCK, conjuredModel); - simpleBlock(HexBlocks.CONJURED_LIGHT, conjuredModel); - - // for the break particles - simpleBlock(HexBlocks.QUENCHED_ALLAY, models().cubeAll("quenched_allay", modLoc("block/quenched_allay_0"))); - simpleBlock(HexBlocks.QUENCHED_ALLAY_TILES, models().cubeAll("quenched_allay_tiles", modLoc("block/deco/quenched_allay_tiles_0"))); - simpleBlock(HexBlocks.QUENCHED_ALLAY_BRICKS, models().cubeAll("quenched_allay_bricks", modLoc("block/deco/quenched_allay_bricks_0"))); - simpleBlock(HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL, models().cubeAll("quenched_allay_bricks_small", modLoc("block/deco/quenched_allay_bricks_small_0"))); - } - - // Assumes that the bottom are always the same - private void arrowCircleBlock(Block block, String name, ResourceLocation particle, - String frontStub, - String topStob, - String leftStub, - String rightStub, - String backStub, - boolean itemModelIsLit - ) { - getVariantBuilder(block).forAllStates(bs -> { - boolean isLit = bs.getValue(BlockCircleComponent.ENERGIZED); - var litness = isLit ? "lit" : "dim"; - var dir = bs.getValue(BlockStateProperties.FACING); - - // I wish we didn't have to put the top "upside down" but there you go - var front = "block/circle/" + frontStub + "_" + litness; - var top = "block/circle/" + topStob + "_" + litness; - var left = "block/circle/" + leftStub + "_" + litness; - var right = "block/circle/" + rightStub + "_" + litness; - var back = "block/circle/" + backStub + "_" + litness; - // and never light the bottom - var bottom = "block/circle/bottom"; - - var modelName = "block/circle/" + name + "/" + litness + "_" + dir.getName(); - var model = models().cube(modelName, modLoc(bottom), modLoc(top), modLoc(front), modLoc(back), - modLoc(left), modLoc(right)) - .texture("particle", particle); - - // Most blocks point north in the inv, but we have these point east so that their faces aren't obscured - // by the count number - if (isLit == itemModelIsLit && dir == Direction.EAST) { - itemModels().getBuilder("item/" + name).parent(model); - } - - return ConfiguredModel.builder() - .modelFile(model) - // this code has been stolen from myself several times - .rotationX(dir.getAxis() == Direction.Axis.Y - ? dir.getAxisDirection().getStep() * -90 - : 0) - .rotationY(dir.getAxis() != Direction.Axis.Y - ? ((dir.get2DDataValue() + 2) % 4) * 90 - : 0) - .build(); - }); - } - - private void impetus(Block block, String name, String stub, boolean itemModelIsLit) { - arrowCircleBlock(block, name, modLoc("block/slate"), - "impetus/" + stub + "/front", - "impetus/" + stub + "/top", - "impetus/" + stub + "/left", - "impetus/" + stub + "/right", - "impetus/back", - itemModelIsLit - ); - } - - private void doAllTheDirectrices() { - arrowCircleBlock(HexBlocks.EMPTY_DIRECTRIX, "directrix/empty", modLoc("block/slate"), - "directrix/empty/front", "directrix/empty/top", "directrix/empty/left", - "directrix/empty/right", "directrix/empty/back", false); - - // Note that "unpowered" means the jowls of the back face are ON. - getVariantBuilder(HexBlocks.DIRECTRIX_REDSTONE).forAllStates(bs -> { - var isLit = bs.getValue(BlockCircleComponent.ENERGIZED); - var litness = isLit ? "lit" : "dim"; - var isPowered = bs.getValue(BlockRedstoneDirectrix.REDSTONE_POWERED); - var poweredness = isPowered ? "powered" : "unpowered"; - var dir = bs.getValue(BlockStateProperties.FACING); - - var top = "block/circle/directrix/redstone/top_" + poweredness; - var left = "block/circle/directrix/redstone/left_" + poweredness; - var right = "block/circle/directrix/redstone/right_" + poweredness; - - // The front face can never be both lit and unpowered (b/c otherwise it would exit the other way) - String frontEnding, backEnding; - if (isLit) { - if (isPowered) { - frontEnding = "lit_powered"; - backEnding = "dim_powered"; - } else { - frontEnding = "dim_unpowered"; - backEnding = "lit_unpowered"; - } - } else { - frontEnding = "dim_" + poweredness; - backEnding = "dim_" + poweredness; - } - var front = "block/circle/directrix/redstone/front_" + frontEnding; - var back = "block/circle/directrix/redstone/back_" + backEnding; - // and always the same - var bottom = "block/circle/bottom"; - - - var modelName = "block/circle/directrix/redstone/" + litness + "_" + poweredness + "_" + dir.getName(); - var model = models().cube(modelName, modLoc(bottom), modLoc(top), modLoc(front), modLoc(back), - modLoc(left), modLoc(right)) - .texture("particle", modLoc("block/slate")); - - if (isLit && !isPowered && dir == Direction.EAST) { - // getBuilder does not add the block/etc to the front if the path contains any slashes - // this is a problem because the block IDs have slashes in them - itemModels().getBuilder("item/directrix/redstone").parent(model); - } - - return ConfiguredModel.builder() - .modelFile(model) - // this code has been stolen from myself several times - .rotationX(dir.getAxis() == Direction.Axis.Y - ? dir.getAxisDirection().getStep() * -90 - : 0) - .rotationY(dir.getAxis() != Direction.Axis.Y - ? ((dir.get2DDataValue() + 2) % 4) * 90 - : 0) - .build(); - }); - - getVariantBuilder(HexBlocks.DIRECTRIX_BOOLEAN).forAllStates(bs -> { - var isLit = bs.getValue(BlockCircleComponent.ENERGIZED); - var litness = isLit ? "lit" : "dim"; - var boolState = bs.getValue(BlockBooleanDirectrix.STATE); - var boolStateString = boolState.toString().toLowerCase(); - var dir = bs.getValue(BlockStateProperties.FACING); - - var top = "block/circle/directrix/boolean/top_" + boolStateString; - var left = "block/circle/directrix/boolean/left_" + boolStateString; - var right = "block/circle/directrix/boolean/right_" + boolStateString; - - // The front face can never be both lit and unpowered (b/c otherwise it would exit the other way) - String frontEnding = null, backEnding = null; - switch (boolState) { - case NEITHER -> { - frontEnding = "not_false"; - backEnding = "not_true"; - } - case TRUE -> { - frontEnding = "not_false"; - backEnding = litness + "_true"; - } - case FALSE -> { - frontEnding = litness + "_false"; - backEnding = "not_true"; - } - } - - var front = "block/circle/directrix/boolean/front_" + frontEnding; - var back = "block/circle/directrix/boolean/back_" + backEnding; - // and always the same - var bottom = "block/circle/bottom"; - - - var modelName = "block/circle/directrix/boolean/" + litness + "_" + boolStateString + "_" + dir.getName(); - var model = models().cube(modelName, modLoc(bottom), modLoc(top), modLoc(front), modLoc(back), - modLoc(left), modLoc(right)) - .texture("particle", modLoc("block/slate")); - - if (isLit && boolState == BlockBooleanDirectrix.State.FALSE && dir == Direction.EAST) { - // getBuilder does not add the block/etc to the front if the path contains any slashes - // this is a problem because the block IDs have slashes in them - itemModels().getBuilder("item/directrix/boolean").parent(model); - } - - return ConfiguredModel.builder() - .modelFile(model) - // this code has been stolen from myself several times - .rotationX(dir.getAxis() == Direction.Axis.Y - ? dir.getAxisDirection().getStep() * -90 - : 0) - .rotationY(dir.getAxis() != Direction.Axis.Y - ? ((dir.get2DDataValue() + 2) % 4) * 90 - : 0) - .build(); - }); - - } + public HexBlockStatesAndModels(PackOutput output, ExistingFileHelper exFileHelper) { + super(output, HexAPI.MOD_ID, exFileHelper); + } + + @Override + protected void registerStatesAndModels() { + var slateModel = models().getExistingFile(modLoc("slate")); + getVariantBuilder(HexBlocks.SLATE) + .forAllStatesExcept( + bs -> { + int rotationX = 0; + int rotationY = 0; + switch (bs.getValue(BlockSlate.ATTACH_FACE)) { + case CEILING -> rotationX = 180; + case WALL -> { + rotationX = 90; + rotationY = bs.getValue(BlockSlate.FACING).getOpposite().get2DDataValue() * 90; + } + } + return ConfiguredModel.builder() + .modelFile(slateModel) + .rotationX(rotationX) + .rotationY(rotationY) + .uvLock(true) + .build(); + }, + BlockSlate.WATERLOGGED); + + impetus(HexBlocks.IMPETUS_EMPTY, "impetus/empty", "empty", false); + impetus(HexBlocks.IMPETUS_RIGHTCLICK, "impetus/rightclick", "rightclick", true); + impetus(HexBlocks.IMPETUS_LOOK, "impetus/look", "look", true); + impetus(HexBlocks.IMPETUS_REDSTONE, "impetus/redstone", "redstone", true); + doAllTheDirectrices(); + + var akashicRecordModel = + models() + .withExistingParent("akashic_record", "block/block") + .renderType("translucent") + .texture("inner", modLoc("block/akashic_ligature")) + .texture("outer", modLoc("block/akashic_record")) + .texture("particle", modLoc("block/akashic_ligature")) + .element() + .cube("#outer") + .end() + .element() + .from(15.75f, 15.75f, 15.75f) + .to(0.25f, 0.25f, 0.25f) + .allFaces( + (dir, builder) -> + builder.texture("#inner").rotation(ModelBuilder.FaceRotation.UPSIDE_DOWN)) + .end(); + + simpleBlock(HexBlocks.AKASHIC_RECORD, akashicRecordModel); + simpleBlockItem(HexBlocks.AKASHIC_RECORD, akashicRecordModel); + blockAndItem( + HexBlocks.AKASHIC_LIGATURE, + models().cubeAll("akashic_ligature", modLoc("block/akashic_ligature"))); + + models() + .getBuilder("akashic_bookshelf") + .renderType("cutout") + .texture("front", modLoc("block/akashic_bookshelf")) + .texture("side", modLoc("block/akashic_bookshelf_horiz")) + .texture("top_bottom", modLoc("block/akashic_bookshelf_vert")) + .texture("particle", modLoc("block/akashic_bookshelf_vert")) + .element() + .allFaces( + (dir, builder) -> + builder + .texture( + switch (dir) { + case DOWN, UP -> "#top_bottom"; + case EAST, SOUTH, WEST -> "#side"; + default -> "#front"; + }) + .cullface(dir)) + .end() + .element() + .face(Direction.NORTH) + .texture("#overlay") + .cullface(Direction.NORTH) + .tintindex(0); + + getVariantBuilder(HexBlocks.AKASHIC_BOOKSHELF) + .forAllStates( + bs -> { + Direction dir = bs.getValue(BlockAkashicBookshelf.FACING); + + var builder = ConfiguredModel.builder(); + + if (bs.getValue(BlockAkashicBookshelf.HAS_BOOKS)) { + for (int i = 1; i <= 4; i++) { + var model = + models() + .withExistingParent( + "akashic_bookshelf_" + i, modLoc("block/akashic_bookshelf")) + .texture("overlay", modLoc("block/akashic_bookshelf_overlay_" + i)); + + builder + .modelFile(model) + .rotationY(dir.getOpposite().get2DDataValue() * 90) + .uvLock(true); + if (i < 4) { + builder = builder.nextModel(); + } + } + } else { + var model = + models() + .orientable( + "akashic_bookshelf_empty", + modLoc("block/akashic_bookshelf_horiz"), + modLoc("block/akashic_bookshelf"), + modLoc("block/akashic_bookshelf_vert")); + + if (dir == Direction.NORTH) { + simpleBlockItem(HexBlocks.AKASHIC_BOOKSHELF, model); + } + + builder + .modelFile(model) + .rotationY(dir.getOpposite().get2DDataValue() * 90) + .uvLock(true); + } + + return builder.build(); + }); + + blockAndItem(HexBlocks.SLATE_BLOCK, models().cubeAll("slate_block", modLoc("block/slate"))); + blockAndItem( + HexBlocks.SLATE_TILES, + models().cubeAll("block/deco/slate_tiles", modLoc("block/deco/slate_tiles"))); + blockAndItem( + HexBlocks.SLATE_BRICKS, + models().cubeAll("block/deco/slate_bricks", modLoc("block/deco/slate_bricks"))); + blockAndItem( + HexBlocks.SLATE_BRICKS_SMALL, + models().cubeAll("block/deco/slate_bricks_small", modLoc("block/deco/slate_bricks_small"))); + axisBlock(HexBlocks.SLATE_PILLAR, modLoc("block/deco/slate_pillar")); + blockAndItem( + HexBlocks.AMETHYST_DUST_BLOCK, + models() + .singleTexture( + "amethyst_dust_block", + modLoc(BLOCK_FOLDER + "/cube_half_mirrored"), + "all", + modLoc("block/amethyst_dust_block"))); + blockAndItem( + HexBlocks.AMETHYST_TILES, + models().cubeAll("block/deco/amethyst_tiles", modLoc("block/deco/amethyst_tiles"))); + blockAndItem( + HexBlocks.AMETHYST_BRICKS, + models().cubeAll("block/deco/amethyst_bricks", modLoc("block/deco/amethyst_bricks"))); + blockAndItem( + HexBlocks.AMETHYST_BRICKS_SMALL, + models() + .cubeAll( + "block/deco/amethyst_bricks_small", modLoc("block/deco/amethyst_bricks_small"))); + directionalBlock( + HexBlocks.AMETHYST_PILLAR, + models() + .cubeBottomTop( + "block/deco/amethyst_pillar", + modLoc("block/deco/amethyst_pillar_side"), + modLoc("block/deco/amethyst_pillar_bottom"), + modLoc("block/deco/amethyst_pillar_top"))); + blockAndItem( + HexBlocks.SLATE_AMETHYST_TILES, + models() + .cubeAll("block/deco/slate_amethyst_tiles", modLoc("block/deco/slate_amethyst_tiles"))); + + simpleBlock( + HexBlocks.SLATE_AMETHYST_BRICKS, + new ConfiguredModel( + models() + .cubeAll( + "block/deco/slate_amethyst_bricks_0", + modLoc("block/deco/slate_amethyst_bricks_0"))), + new ConfiguredModel( + models() + .cubeAll( + "block/deco/slate_amethyst_bricks_1", + modLoc("block/deco/slate_amethyst_bricks_1"))), + new ConfiguredModel( + models() + .cubeAll( + "block/deco/slate_amethyst_bricks_2", + modLoc("block/deco/slate_amethyst_bricks_2")))); + simpleBlockItem( + HexBlocks.SLATE_AMETHYST_BRICKS, + models() + .cubeAll( + "block/deco/slate_amethyst_bricks_0", + modLoc("block/deco/slate_amethyst_bricks_0"))); + + simpleBlock( + HexBlocks.SLATE_AMETHYST_BRICKS_SMALL, + new ConfiguredModel( + models() + .cubeAll( + "block/deco/slate_amethyst_bricks_small_0", + modLoc("block/deco/slate_amethyst_bricks_small_0"))), + new ConfiguredModel( + models() + .cubeAll( + "block/deco/slate_amethyst_bricks_small_1", + modLoc("block/deco/slate_amethyst_bricks_small_1"))), + new ConfiguredModel( + models() + .cubeAll( + "block/deco/slate_amethyst_bricks_small_2", + modLoc("block/deco/slate_amethyst_bricks_small_2")))); + simpleBlockItem( + HexBlocks.SLATE_AMETHYST_BRICKS_SMALL, + models() + .cubeAll( + "block/deco/slate_amethyst_bricks_small_0", + modLoc("block/deco/slate_amethyst_bricks_small_0"))); + + axisBlock(HexBlocks.SLATE_AMETHYST_PILLAR, modLoc("block/deco/slate_amethyst_pillar")); + cubeBlockAndItem(HexBlocks.SCROLL_PAPER, "scroll_paper"); + cubeBlockAndItem(HexBlocks.ANCIENT_SCROLL_PAPER, "ancient_scroll_paper"); + + blockAndItem( + HexBlocks.SCROLL_PAPER_LANTERN, + models() + .cubeBottomTop( + "scroll_paper_lantern", + modLoc("block/scroll_paper_lantern_side"), + modLoc("block/scroll_paper_lantern_bottom"), + modLoc("block/scroll_paper_lantern_top"))); + + blockAndItem( + HexBlocks.ANCIENT_SCROLL_PAPER_LANTERN, + models() + .cubeBottomTop( + "ancient_scroll_paper_lantern", + modLoc("block/ancient_scroll_paper_lantern_side"), + modLoc("block/ancient_scroll_paper_lantern_bottom"), + modLoc("block/ancient_scroll_paper_lantern_top"))); + + axisBlock(HexBlocks.EDIFIED_LOG, modLoc("block/edified_log"), modLoc("block/edified_log_top")); + axisBlock( + HexBlocks.EDIFIED_LOG_AMETHYST, + modLoc("block/deco/edified_log_amethyst"), + modLoc("block/edified_log_top")); + axisBlock( + HexBlocks.EDIFIED_LOG_AVENTURINE, + modLoc("block/deco/edified_log_aventurine"), + modLoc("block/edified_log_top")); + axisBlock( + HexBlocks.EDIFIED_LOG_CITRINE, + modLoc("block/deco/edified_log_citrine"), + modLoc("block/edified_log_top")); + axisBlock( + HexBlocks.EDIFIED_LOG_PURPLE, + modLoc("block/deco/edified_log_purple"), + modLoc("block/edified_log_top")); + axisBlock( + HexBlocks.STRIPPED_EDIFIED_LOG, + modLoc("block/stripped_edified_log"), + modLoc("block/stripped_edified_log_top")); + axisBlock(HexBlocks.EDIFIED_WOOD, modLoc("block/edified_log"), modLoc("block/edified_log")); + axisBlock( + HexBlocks.STRIPPED_EDIFIED_WOOD, + modLoc("block/stripped_edified_log"), + modLoc("block/stripped_edified_log")); + + blockAndItem( + HexBlocks.EDIFIED_PANEL, models().cubeAll("edified_panel", modLoc("block/edified_panel"))); + blockAndItem( + HexBlocks.EDIFIED_TILE, models().cubeAll("edified_tile", modLoc("block/edified_tile"))); + + ResourceLocation leavesParent = new ResourceLocation("block/leaves"); + blockAndItem( + HexBlocks.AMETHYST_EDIFIED_LEAVES, + models() + .withExistingParent("amethyst_edified_leaves", leavesParent) + .texture("all", modLoc("block/amethyst_edified_leaves")) + .renderType("cutout_mipped")); + blockAndItem( + HexBlocks.AVENTURINE_EDIFIED_LEAVES, + models() + .withExistingParent("aventurine_edified_leaves", leavesParent) + .texture("all", modLoc("block/aventurine_edified_leaves")) + .renderType("cutout_mipped")); + blockAndItem( + HexBlocks.CITRINE_EDIFIED_LEAVES, + models() + .withExistingParent("citrine_edified_leaves", leavesParent) + .texture("all", modLoc("block/citrine_edified_leaves")) + .renderType("cutout_mipped")); + + doorBlockWithRenderType( + HexBlocks.EDIFIED_DOOR, + modLoc("block/edified_door_lower"), + modLoc("block" + "/edified_door_upper"), + "cutout"); + // door model via the given texture + trapdoorBlockWithRenderType( + HexBlocks.EDIFIED_TRAPDOOR, modLoc("block/edified_trapdoor"), true, "cutout"); + + ResourceLocation planks1 = modLoc("block/edified_planks"); + BlockModelBuilder planksModel = models().cubeAll("edified_planks", planks1); + simpleBlock( + HexBlocks.EDIFIED_PLANKS, + ConfiguredModel.builder() + .modelFile(planksModel) + .weight(3) + .nextModel() + .modelFile(models().cubeAll("edified_planks_2", modLoc("block/edified_planks_2"))) + .weight(3) + .nextModel() + .modelFile(models().cubeAll("edified_planks_3", modLoc("block/edified_planks_3"))) + .build()); + simpleBlockItem(HexBlocks.EDIFIED_PLANKS, planksModel); + + stairsBlock(HexBlocks.EDIFIED_STAIRS, planks1); + fenceBlock(HexBlocks.EDIFIED_FENCE, planks1); + fenceGateBlock(HexBlocks.EDIFIED_FENCE_GATE, planks1); + slabBlock(HexBlocks.EDIFIED_SLAB, planks1, planks1); + buttonBlock(HexBlocks.EDIFIED_BUTTON, planks1); + pressurePlateBlock(HexBlocks.EDIFIED_PRESSURE_PLATE, planks1); + + var sconceModel = models().getExistingFile(modLoc("amethyst_sconce")); + simpleBlock(HexBlocks.SCONCE, sconceModel); + simpleBlockItem(HexBlocks.SCONCE, sconceModel); + + var conjuredModel = + models() + .getBuilder("conjured") + .texture("particle", mcLoc("block/amethyst_block")) + .renderType("cutout"); + simpleBlock(HexBlocks.CONJURED_BLOCK, conjuredModel); + simpleBlock(HexBlocks.CONJURED_LIGHT, conjuredModel); + + // for the break particles + simpleBlock( + HexBlocks.QUENCHED_ALLAY, + models().cubeAll("quenched_allay", modLoc("block/quenched_allay_0"))); + simpleBlock( + HexBlocks.QUENCHED_ALLAY_TILES, + models().cubeAll("quenched_allay_tiles", modLoc("block/deco/quenched_allay_tiles_0"))); + simpleBlock( + HexBlocks.QUENCHED_ALLAY_BRICKS, + models().cubeAll("quenched_allay_bricks", modLoc("block/deco/quenched_allay_bricks_0"))); + simpleBlock( + HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL, + models() + .cubeAll( + "quenched_allay_bricks_small", modLoc("block/deco/quenched_allay_bricks_small_0"))); + } + + // Assumes that the bottom are always the same + private void arrowCircleBlock( + Block block, + String name, + ResourceLocation particle, + String frontStub, + String topStob, + String leftStub, + String rightStub, + String backStub, + boolean itemModelIsLit) { + getVariantBuilder(block) + .forAllStates( + bs -> { + boolean isLit = bs.getValue(BlockCircleComponent.ENERGIZED); + var litness = isLit ? "lit" : "dim"; + var dir = bs.getValue(BlockStateProperties.FACING); + + // I wish we didn't have to put the top "upside down" but there you go + var front = "block/circle/" + frontStub + "_" + litness; + var top = "block/circle/" + topStob + "_" + litness; + var left = "block/circle/" + leftStub + "_" + litness; + var right = "block/circle/" + rightStub + "_" + litness; + var back = "block/circle/" + backStub + "_" + litness; + // and never light the bottom + var bottom = "block/circle/bottom"; + + var modelName = "block/circle/" + name + "/" + litness + "_" + dir.getName(); + var model = + models() + .cube( + modelName, + modLoc(bottom), + modLoc(top), + modLoc(front), + modLoc(back), + modLoc(left), + modLoc(right)) + .texture("particle", particle); + + // Most blocks point north in the inv, but we have these point east so that their + // faces aren't obscured + // by the count number + if (isLit == itemModelIsLit && dir == Direction.EAST) { + itemModels().getBuilder("item/" + name).parent(model); + } + + return ConfiguredModel.builder() + .modelFile(model) + // this code has been stolen from myself several times + .rotationX( + dir.getAxis() == Direction.Axis.Y + ? dir.getAxisDirection().getStep() * -90 + : 0) + .rotationY( + dir.getAxis() != Direction.Axis.Y ? ((dir.get2DDataValue() + 2) % 4) * 90 : 0) + .build(); + }); + } + + private void impetus(Block block, String name, String stub, boolean itemModelIsLit) { + arrowCircleBlock( + block, + name, + modLoc("block/slate"), + "impetus/" + stub + "/front", + "impetus/" + stub + "/top", + "impetus/" + stub + "/left", + "impetus/" + stub + "/right", + "impetus/back", + itemModelIsLit); + } + + private void doAllTheDirectrices() { + arrowCircleBlock( + HexBlocks.EMPTY_DIRECTRIX, + "directrix/empty", + modLoc("block/slate"), + "directrix/empty/front", + "directrix/empty/top", + "directrix/empty/left", + "directrix/empty/right", + "directrix/empty/back", + false); + + // Note that "unpowered" means the jowls of the back face are ON. + getVariantBuilder(HexBlocks.DIRECTRIX_REDSTONE) + .forAllStates( + bs -> { + var isLit = bs.getValue(BlockCircleComponent.ENERGIZED); + var litness = isLit ? "lit" : "dim"; + var isPowered = bs.getValue(BlockRedstoneDirectrix.REDSTONE_POWERED); + var poweredness = isPowered ? "powered" : "unpowered"; + var dir = bs.getValue(BlockStateProperties.FACING); + + var top = "block/circle/directrix/redstone/top_" + poweredness; + var left = "block/circle/directrix/redstone/left_" + poweredness; + var right = "block/circle/directrix/redstone/right_" + poweredness; + + // The front face can never be both lit and unpowered (b/c otherwise it would exit the + // other way) + String frontEnding, backEnding; + if (isLit) { + if (isPowered) { + frontEnding = "lit_powered"; + backEnding = "dim_powered"; + } else { + frontEnding = "dim_unpowered"; + backEnding = "lit_unpowered"; + } + } else { + frontEnding = "dim_" + poweredness; + backEnding = "dim_" + poweredness; + } + var front = "block/circle/directrix/redstone/front_" + frontEnding; + var back = "block/circle/directrix/redstone/back_" + backEnding; + // and always the same + var bottom = "block/circle/bottom"; + + var modelName = + "block/circle/directrix/redstone/" + + litness + + "_" + + poweredness + + "_" + + dir.getName(); + var model = + models() + .cube( + modelName, + modLoc(bottom), + modLoc(top), + modLoc(front), + modLoc(back), + modLoc(left), + modLoc(right)) + .texture("particle", modLoc("block/slate")); + + if (isLit && !isPowered && dir == Direction.EAST) { + // getBuilder does not add the block/etc to the front if the path contains any + // slashes + // this is a problem because the block IDs have slashes in them + itemModels().getBuilder("item/directrix/redstone").parent(model); + } + + return ConfiguredModel.builder() + .modelFile(model) + // this code has been stolen from myself several times + .rotationX( + dir.getAxis() == Direction.Axis.Y + ? dir.getAxisDirection().getStep() * -90 + : 0) + .rotationY( + dir.getAxis() != Direction.Axis.Y ? ((dir.get2DDataValue() + 2) % 4) * 90 : 0) + .build(); + }); + + getVariantBuilder(HexBlocks.DIRECTRIX_BOOLEAN) + .forAllStates( + bs -> { + var isLit = bs.getValue(BlockCircleComponent.ENERGIZED); + var litness = isLit ? "lit" : "dim"; + var boolState = bs.getValue(BlockBooleanDirectrix.STATE); + var boolStateString = boolState.toString().toLowerCase(); + var dir = bs.getValue(BlockStateProperties.FACING); + + var top = "block/circle/directrix/boolean/top_" + boolStateString; + var left = "block/circle/directrix/boolean/left_" + boolStateString; + var right = "block/circle/directrix/boolean/right_" + boolStateString; + + // The front face can never be both lit and unpowered (b/c otherwise it would exit the + // other way) + String frontEnding = null, backEnding = null; + switch (boolState) { + case NEITHER -> { + frontEnding = "not_false"; + backEnding = "not_true"; + } + case TRUE -> { + frontEnding = "not_false"; + backEnding = litness + "_true"; + } + case FALSE -> { + frontEnding = litness + "_false"; + backEnding = "not_true"; + } + } + + var front = "block/circle/directrix/boolean/front_" + frontEnding; + var back = "block/circle/directrix/boolean/back_" + backEnding; + // and always the same + var bottom = "block/circle/bottom"; + + var modelName = + "block/circle/directrix/boolean/" + + litness + + "_" + + boolStateString + + "_" + + dir.getName(); + var model = + models() + .cube( + modelName, + modLoc(bottom), + modLoc(top), + modLoc(front), + modLoc(back), + modLoc(left), + modLoc(right)) + .texture("particle", modLoc("block/slate")); + + if (isLit + && boolState == BlockBooleanDirectrix.State.FALSE + && dir == Direction.EAST) { + // getBuilder does not add the block/etc to the front if the path contains any + // slashes + // this is a problem because the block IDs have slashes in them + itemModels().getBuilder("item/directrix/boolean").parent(model); + } + + return ConfiguredModel.builder() + .modelFile(model) + // this code has been stolen from myself several times + .rotationX( + dir.getAxis() == Direction.Axis.Y + ? dir.getAxisDirection().getStep() * -90 + : 0) + .rotationY( + dir.getAxis() != Direction.Axis.Y ? ((dir.get2DDataValue() + 2) % 4) * 90 : 0) + .build(); + }); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/xplat/HexItemModels.java b/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/xplat/HexItemModels.java index 7def15a4e4..15fa7350fd 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/xplat/HexItemModels.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/xplat/HexItemModels.java @@ -4,9 +4,9 @@ import at.petrak.hexcasting.client.render.GaslightingTracker; import at.petrak.hexcasting.common.blocks.BlockQuenchedAllay; import at.petrak.hexcasting.common.items.ItemStaff; -import at.petrak.hexcasting.common.items.pigment.ItemPridePigment; import at.petrak.hexcasting.common.items.magic.ItemMediaBattery; import at.petrak.hexcasting.common.items.magic.ItemPackagedHex; +import at.petrak.hexcasting.common.items.pigment.ItemPridePigment; import at.petrak.hexcasting.common.items.storage.ItemFocus; import at.petrak.hexcasting.common.items.storage.ItemScroll; import at.petrak.hexcasting.common.items.storage.ItemSlate; @@ -14,8 +14,8 @@ import at.petrak.hexcasting.common.lib.HexBlocks; import at.petrak.hexcasting.common.lib.HexItems; import at.petrak.paucal.api.forge.datagen.PaucalItemModelProvider; -import net.minecraft.client.renderer.block.model.ItemTransforms; -import net.minecraft.data.DataGenerator; +import java.util.Objects; +import java.util.function.BiFunction; import net.minecraft.data.PackOutput; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.DyeColor; @@ -26,280 +26,356 @@ import net.minecraftforge.common.data.ExistingFileHelper; import net.minecraftforge.registries.ForgeRegistries; -import java.util.Objects; -import java.util.function.BiFunction; - public class HexItemModels extends PaucalItemModelProvider { - public HexItemModels(PackOutput output, ExistingFileHelper existingFileHelper) { - super(output, HexAPI.MOD_ID, existingFileHelper); - } + public HexItemModels(PackOutput output, ExistingFileHelper existingFileHelper) { + super(output, HexAPI.MOD_ID, existingFileHelper); + } - private static final String[] PHIAL_SIZES = {"small", "medium", "large", "larger", "largest"}; + private static final String[] PHIAL_SIZES = {"small", "medium", "large", "larger", "largest"}; - private static String getPath(Item item) { - return Objects.requireNonNull(ForgeRegistries.ITEMS.getKey(item)).getPath(); - } + private static String getPath(Item item) { + return Objects.requireNonNull(ForgeRegistries.ITEMS.getKey(item)).getPath(); + } - private static String getPath(Block block) { - return Objects.requireNonNull(ForgeRegistries.BLOCKS.getKey(block)).getPath(); - } + private static String getPath(Block block) { + return Objects.requireNonNull(ForgeRegistries.BLOCKS.getKey(block)).getPath(); + } - @Override - protected void registerModels() { - simpleItem(HexItems.AMETHYST_DUST); - simpleItem(HexItems.CHARGED_AMETHYST); - simpleItem(HexItems.SUBMARINE_SANDWICH); - simpleItem(HexItems.ABACUS); - brandishedItem(HexItems.JEWELER_HAMMER); - simpleItem(HexItems.CREATIVE_UNLOCKER); - simpleItem(HexItems.LORE_FRAGMENT); + @Override + protected void registerModels() { + simpleItem(HexItems.AMETHYST_DUST); + simpleItem(HexItems.CHARGED_AMETHYST); + simpleItem(HexItems.SUBMARINE_SANDWICH); + simpleItem(HexItems.ABACUS); + brandishedItem(HexItems.JEWELER_HAMMER); + simpleItem(HexItems.CREATIVE_UNLOCKER); + simpleItem(HexItems.LORE_FRAGMENT); - singleTexture(getPath(HexBlocks.CONJURED_BLOCK), - new ResourceLocation("item/generated"), - "layer0", new ResourceLocation("item/amethyst_shard")); - singleTexture(getPath(HexBlocks.CONJURED_LIGHT), - new ResourceLocation("item/generated"), - "layer0", new ResourceLocation("item/amethyst_shard")); + singleTexture( + getPath(HexBlocks.CONJURED_BLOCK), + new ResourceLocation("item/generated"), + "layer0", + new ResourceLocation("item/amethyst_shard")); + singleTexture( + getPath(HexBlocks.CONJURED_LIGHT), + new ResourceLocation("item/generated"), + "layer0", + new ResourceLocation("item/amethyst_shard")); - for (var age : new String[]{"pristine", "ancient"}) { - for (var size : new String[]{"small", "medium", "large"}) { - simpleItem(modLoc("scroll_" + age + "_" + size)); - } - } - buildScroll(HexItems.SCROLL_SMOL, "small"); - buildScroll(HexItems.SCROLL_MEDIUM, "medium"); - buildScroll(HexItems.SCROLL_LARGE, "large"); + for (var age : new String[] {"pristine", "ancient"}) { + for (var size : new String[] {"small", "medium", "large"}) { + simpleItem(modLoc("scroll_" + age + "_" + size)); + } + } + buildScroll(HexItems.SCROLL_SMOL, "small"); + buildScroll(HexItems.SCROLL_MEDIUM, "medium"); + buildScroll(HexItems.SCROLL_LARGE, "large"); - simpleItem(HexItems.SCRYING_LENS); - getBuilder(getPath(HexItems.SCRYING_LENS)) - .transforms() - .transform(ItemDisplayContext.HEAD) - .rotation(0f, 0f, 0f) - .translation(-2.5f, 0f, -8f) - .scale(0.4f); + simpleItem(HexItems.SCRYING_LENS); + getBuilder(getPath(HexItems.SCRYING_LENS)) + .transforms() + .transform(ItemDisplayContext.HEAD) + .rotation(0f, 0f, 0f) + .translation(-2.5f, 0f, -8f) + .scale(0.4f); - singleTexture("old_staff", new ResourceLocation("item/handheld_rod"), - "layer0", modLoc("item/staff/old")); - singleTexture("cherry_staff", new ResourceLocation("item/handheld_rod"), - "layer0", modLoc("item/staff/cherry")); + singleTexture( + "old_staff", new ResourceLocation("item/handheld_rod"), "layer0", modLoc("item/staff/old")); + singleTexture( + "cherry_staff", + new ResourceLocation("item/handheld_rod"), + "layer0", + modLoc("item/staff/cherry")); - buildStaff(HexItems.STAFF_OAK, "oak"); - buildStaff(HexItems.STAFF_BIRCH, "birch"); - buildStaff(HexItems.STAFF_SPRUCE, "spruce"); - buildStaff(HexItems.STAFF_JUNGLE, "jungle"); - buildStaff(HexItems.STAFF_DARK_OAK, "dark_oak"); - buildStaff(HexItems.STAFF_ACACIA, "acacia"); - buildStaff(HexItems.STAFF_CRIMSON, "crimson"); - buildStaff(HexItems.STAFF_WARPED, "warped"); - buildStaff(HexItems.STAFF_MANGROVE, "mangrove"); - buildStaff(HexItems.STAFF_CHERRY, "cherry"); - buildStaff(HexItems.STAFF_BAMBOO, "bamboo"); - buildStaff(HexItems.STAFF_EDIFIED, "edified"); - buildStaff(HexItems.STAFF_MINDSPLICE, "mindsplice"); + buildStaff(HexItems.STAFF_OAK, "oak"); + buildStaff(HexItems.STAFF_BIRCH, "birch"); + buildStaff(HexItems.STAFF_SPRUCE, "spruce"); + buildStaff(HexItems.STAFF_JUNGLE, "jungle"); + buildStaff(HexItems.STAFF_DARK_OAK, "dark_oak"); + buildStaff(HexItems.STAFF_ACACIA, "acacia"); + buildStaff(HexItems.STAFF_CRIMSON, "crimson"); + buildStaff(HexItems.STAFF_WARPED, "warped"); + buildStaff(HexItems.STAFF_MANGROVE, "mangrove"); + buildStaff(HexItems.STAFF_CHERRY, "cherry"); + buildStaff(HexItems.STAFF_BAMBOO, "bamboo"); + buildStaff(HexItems.STAFF_EDIFIED, "edified"); + buildStaff(HexItems.STAFF_MINDSPLICE, "mindsplice"); - // again, doesn't like paths with slashes in them, so we do it manually - buildFourVariantGaslight("item/staff/quenched", "item/staff/quenched", (name, path) -> - singleTexture(path.getPath(), new ResourceLocation("item/handheld_rod"), - "layer0", modLoc(path.getPath()))); - buildFourVariantGaslight(getPath(HexItems.QUENCHED_SHARD), "item/quenched_shard", (name, path) -> - singleTexture(path.getPath(), new ResourceLocation("item/handheld"), - "layer0", modLoc(path.getPath()))); - buildFourVariantGaslight(getPath(HexBlocks.QUENCHED_ALLAY), "block/quenched_allay", (name, path) -> - cubeAll(path.getPath(), path)); - buildFourVariantGaslight(getPath(HexBlocks.QUENCHED_ALLAY_TILES), "block/deco/quenched_allay_tiles", (name, path) -> - cubeAll(path.getPath(), path)); - buildFourVariantGaslight(getPath(HexBlocks.QUENCHED_ALLAY_BRICKS), "block/deco/quenched_allay_bricks", (name, path) -> - cubeAll(path.getPath(), path)); - buildFourVariantGaslight(getPath(HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL), "block/deco/quenched_allay_bricks_small", (name, path) -> - cubeAll(path.getPath(), path)); + // again, doesn't like paths with slashes in them, so we do it manually + buildFourVariantGaslight( + "item/staff/quenched", + "item/staff/quenched", + (name, path) -> + singleTexture( + path.getPath(), + new ResourceLocation("item/handheld_rod"), + "layer0", + modLoc(path.getPath()))); + buildFourVariantGaslight( + getPath(HexItems.QUENCHED_SHARD), + "item/quenched_shard", + (name, path) -> + singleTexture( + path.getPath(), + new ResourceLocation("item/handheld"), + "layer0", + modLoc(path.getPath()))); + buildFourVariantGaslight( + getPath(HexBlocks.QUENCHED_ALLAY), + "block/quenched_allay", + (name, path) -> cubeAll(path.getPath(), path)); + buildFourVariantGaslight( + getPath(HexBlocks.QUENCHED_ALLAY_TILES), + "block/deco/quenched_allay_tiles", + (name, path) -> cubeAll(path.getPath(), path)); + buildFourVariantGaslight( + getPath(HexBlocks.QUENCHED_ALLAY_BRICKS), + "block/deco/quenched_allay_bricks", + (name, path) -> cubeAll(path.getPath(), path)); + buildFourVariantGaslight( + getPath(HexBlocks.QUENCHED_ALLAY_BRICKS_SMALL), + "block/deco/quenched_allay_bricks_small", + (name, path) -> cubeAll(path.getPath(), path)); - simpleItem(modLoc("patchouli_book")); + simpleItem(modLoc("patchouli_book")); - buildThoughtKnot(); - buildSealableIotaHolder(HexItems.FOCUS, "focus", HexItems.FOCUS.numVariants()); - buildSealableIotaHolder(HexItems.SPELLBOOK, "spellbook", HexItems.SPELLBOOK.numVariants()); + buildThoughtKnot(); + buildSealableIotaHolder(HexItems.FOCUS, "focus", HexItems.FOCUS.numVariants()); + buildSealableIotaHolder(HexItems.SPELLBOOK, "spellbook", HexItems.SPELLBOOK.numVariants()); - buildPackagedSpell(HexItems.CYPHER, "cypher", HexItems.CYPHER.numVariants()); - buildPackagedSpell(HexItems.TRINKET, "trinket", HexItems.TRINKET.numVariants()); - buildPackagedSpell(HexItems.ARTIFACT, "artifact", HexItems.ARTIFACT.numVariants()); + buildPackagedSpell(HexItems.CYPHER, "cypher", HexItems.CYPHER.numVariants()); + buildPackagedSpell(HexItems.TRINKET, "trinket", HexItems.TRINKET.numVariants()); + buildPackagedSpell(HexItems.ARTIFACT, "artifact", HexItems.ARTIFACT.numVariants()); - int maxFill = 4; - for (int size = 0; size < PHIAL_SIZES.length; size++) { - for (int fill = 0; fill <= maxFill; fill++) { - String name = "phial_" + PHIAL_SIZES[size] + "_" + fill; - singleTexture( - name, - new ResourceLocation("item/generated"), - "layer0", modLoc("item/phial/" + name)); + int maxFill = 4; + for (int size = 0; size < PHIAL_SIZES.length; size++) { + for (int fill = 0; fill <= maxFill; fill++) { + String name = "phial_" + PHIAL_SIZES[size] + "_" + fill; + singleTexture( + name, new ResourceLocation("item/generated"), "layer0", modLoc("item/phial/" + name)); - float fillProp = (float) fill / maxFill; - getBuilder(getPath(HexItems.BATTERY)).override() - .predicate(ItemMediaBattery.MEDIA_PREDICATE, fillProp) - .predicate(ItemMediaBattery.MAX_MEDIA_PREDICATE, size) - .model(new ModelFile.UncheckedModelFile(modLoc("item/" + name))) - .end(); - } - } + float fillProp = (float) fill / maxFill; + getBuilder(getPath(HexItems.BATTERY)) + .override() + .predicate(ItemMediaBattery.MEDIA_PREDICATE, fillProp) + .predicate(ItemMediaBattery.MAX_MEDIA_PREDICATE, size) + .model(new ModelFile.UncheckedModelFile(modLoc("item/" + name))) + .end(); + } + } - for (var dye : DyeColor.values()) { - singleTexture(getPath(HexItems.DYE_PIGMENTS.get(dye)), - new ResourceLocation("item/generated"), - "layer0", modLoc("item/colorizer/dye_" + dye.getName())); - } - for (var type : ItemPridePigment.Type.values()) { - singleTexture(getPath(HexItems.PRIDE_PIGMENTS.get(type)), - new ResourceLocation("item/generated"), - "layer0", modLoc("item/colorizer/pride_" + type.getName())); - } - singleTexture(getPath(HexItems.UUID_PIGMENT), new ResourceLocation("item/generated"), - "layer0", modLoc("item/colorizer/uuid")); - singleTexture(getPath(HexItems.DEFAULT_PIGMENT), new ResourceLocation("item/generated"), - "layer0", modLoc("item/colorizer/uuid")); + for (var dye : DyeColor.values()) { + singleTexture( + getPath(HexItems.DYE_PIGMENTS.get(dye)), + new ResourceLocation("item/generated"), + "layer0", + modLoc("item/colorizer/dye_" + dye.getName())); + } + for (var type : ItemPridePigment.Type.values()) { + singleTexture( + getPath(HexItems.PRIDE_PIGMENTS.get(type)), + new ResourceLocation("item/generated"), + "layer0", + modLoc("item/colorizer/pride_" + type.getName())); + } + singleTexture( + getPath(HexItems.UUID_PIGMENT), + new ResourceLocation("item/generated"), + "layer0", + modLoc("item/colorizer/uuid")); + singleTexture( + getPath(HexItems.DEFAULT_PIGMENT), + new ResourceLocation("item/generated"), + "layer0", + modLoc("item/colorizer/uuid")); - simpleItem(modLoc("slate_blank")); - simpleItem(modLoc("slate_written")); - getBuilder(getPath(HexItems.SLATE)).override() - .predicate(ItemSlate.WRITTEN_PRED, 0) - .model(new ModelFile.UncheckedModelFile(modLoc("item/slate_blank"))) - .end() - .override() - .predicate(ItemSlate.WRITTEN_PRED, 1) - .model(new ModelFile.UncheckedModelFile(modLoc("item/slate_written"))) - .end(); + simpleItem(modLoc("slate_blank")); + simpleItem(modLoc("slate_written")); + getBuilder(getPath(HexItems.SLATE)) + .override() + .predicate(ItemSlate.WRITTEN_PRED, 0) + .model(new ModelFile.UncheckedModelFile(modLoc("item/slate_blank"))) + .end() + .override() + .predicate(ItemSlate.WRITTEN_PRED, 1) + .model(new ModelFile.UncheckedModelFile(modLoc("item/slate_written"))) + .end(); - getBuilder(getPath(HexBlocks.SLATE_PILLAR)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/slate_pillar"))); - getBuilder(getPath(HexBlocks.AMETHYST_PILLAR)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/deco/amethyst_pillar"))); - getBuilder(getPath(HexBlocks.SLATE_AMETHYST_PILLAR)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/slate_amethyst_pillar"))); + getBuilder(getPath(HexBlocks.SLATE_PILLAR)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/slate_pillar"))); + getBuilder(getPath(HexBlocks.AMETHYST_PILLAR)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/deco/amethyst_pillar"))); + getBuilder(getPath(HexBlocks.SLATE_AMETHYST_PILLAR)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/slate_amethyst_pillar"))); - getBuilder(getPath(HexBlocks.AKASHIC_RECORD)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/akashic_record"))); - simpleItem(modLoc("edified_door")); - getBuilder(getPath(HexBlocks.EDIFIED_TRAPDOOR)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/edified_trapdoor_bottom"))); - getBuilder(getPath(HexBlocks.EDIFIED_LOG)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/edified_log"))); - getBuilder(getPath(HexBlocks.EDIFIED_LOG_AMETHYST)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/edified_log_amethyst"))); - getBuilder(getPath(HexBlocks.EDIFIED_LOG_AVENTURINE)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/edified_log_aventurine"))); - getBuilder(getPath(HexBlocks.EDIFIED_LOG_CITRINE)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/edified_log_citrine"))); - getBuilder(getPath(HexBlocks.EDIFIED_LOG_PURPLE)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/edified_log_purple"))); - getBuilder(getPath(HexBlocks.STRIPPED_EDIFIED_LOG)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/stripped_edified_log"))); - getBuilder(getPath(HexBlocks.EDIFIED_WOOD)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/edified_wood"))); - getBuilder(getPath(HexBlocks.STRIPPED_EDIFIED_WOOD)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/stripped_edified_wood"))); - getBuilder(getPath(HexBlocks.EDIFIED_STAIRS)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/edified_stairs"))); - getBuilder(getPath(HexBlocks.EDIFIED_FENCE)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/edified_fence_inventory"))); - getBuilder(getPath(HexBlocks.EDIFIED_FENCE_GATE)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/edified_fence_gate"))); - getBuilder(getPath(HexBlocks.EDIFIED_SLAB)).parent( - new ModelFile.UncheckedModelFile(modLoc("block/edified_slab"))); - getBuilder(getPath(HexBlocks.EDIFIED_BUTTON)).parent( - new ModelFile.UncheckedModelFile(new ResourceLocation("block/button_inventory"))) - .texture("texture", modLoc("block/edified_planks")); - getBuilder(getPath(HexBlocks.EDIFIED_PRESSURE_PLATE)) - .parent(new ModelFile.UncheckedModelFile(modLoc("block/edified_pressure_plate"))); - } + getBuilder(getPath(HexBlocks.AKASHIC_RECORD)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/akashic_record"))); + simpleItem(modLoc("edified_door")); + getBuilder(getPath(HexBlocks.EDIFIED_TRAPDOOR)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/edified_trapdoor_bottom"))); + getBuilder(getPath(HexBlocks.EDIFIED_LOG)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/edified_log"))); + getBuilder(getPath(HexBlocks.EDIFIED_LOG_AMETHYST)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/edified_log_amethyst"))); + getBuilder(getPath(HexBlocks.EDIFIED_LOG_AVENTURINE)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/edified_log_aventurine"))); + getBuilder(getPath(HexBlocks.EDIFIED_LOG_CITRINE)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/edified_log_citrine"))); + getBuilder(getPath(HexBlocks.EDIFIED_LOG_PURPLE)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/edified_log_purple"))); + getBuilder(getPath(HexBlocks.STRIPPED_EDIFIED_LOG)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/stripped_edified_log"))); + getBuilder(getPath(HexBlocks.EDIFIED_WOOD)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/edified_wood"))); + getBuilder(getPath(HexBlocks.STRIPPED_EDIFIED_WOOD)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/stripped_edified_wood"))); + getBuilder(getPath(HexBlocks.EDIFIED_STAIRS)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/edified_stairs"))); + getBuilder(getPath(HexBlocks.EDIFIED_FENCE)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/edified_fence_inventory"))); + getBuilder(getPath(HexBlocks.EDIFIED_FENCE_GATE)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/edified_fence_gate"))); + getBuilder(getPath(HexBlocks.EDIFIED_SLAB)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/edified_slab"))); + getBuilder(getPath(HexBlocks.EDIFIED_BUTTON)) + .parent(new ModelFile.UncheckedModelFile(new ResourceLocation("block/button_inventory"))) + .texture("texture", modLoc("block/edified_planks")); + getBuilder(getPath(HexBlocks.EDIFIED_PRESSURE_PLATE)) + .parent(new ModelFile.UncheckedModelFile(modLoc("block/edified_pressure_plate"))); + } - private void buildThoughtKnot() { - var unwritten = singleTexture("thought_knot", new ResourceLocation("item/generated"), - "layer0", modLoc("item/thought_knot")); - var written = withExistingParent("thought_knot_written", new ResourceLocation("item/generated")) - .texture("layer0", modLoc("item/thought_knot")) - .texture("layer1", modLoc("item/thought_knot_overlay")); - getBuilder("thought_knot") - .override().predicate(ItemThoughtKnot.WRITTEN_PRED, 0f) - .model(unwritten).end() - .override().predicate(ItemThoughtKnot.WRITTEN_PRED, 1f) - .model(written).end(); - } + private void buildThoughtKnot() { + var unwritten = + singleTexture( + "thought_knot", + new ResourceLocation("item/generated"), + "layer0", + modLoc("item/thought_knot")); + var written = + withExistingParent("thought_knot_written", new ResourceLocation("item/generated")) + .texture("layer0", modLoc("item/thought_knot")) + .texture("layer1", modLoc("item/thought_knot_overlay")); + getBuilder("thought_knot") + .override() + .predicate(ItemThoughtKnot.WRITTEN_PRED, 0f) + .model(unwritten) + .end() + .override() + .predicate(ItemThoughtKnot.WRITTEN_PRED, 1f) + .model(written) + .end(); + } - private void buildSealableIotaHolder(Item item, String stub, int numVariants) { - var name = getPath(item); - var builder = getBuilder(name); - for (int i = 0; i < numVariants; i++) { - var plain = i == 0 ? singleTexture(name, new ResourceLocation("item/generated"), - "layer0", modLoc("item/cad/" + i + "_" + stub + "_empty")) - : withExistingParent(name + "_" + i, new ResourceLocation("item/generated")) - .texture("layer0", modLoc("item/cad/" + i + "_" + stub + "_empty")); - var unsealed = withExistingParent(name + "_" + i + "_filled", new ResourceLocation("item/generated")) - .texture("layer0", modLoc("item/cad/" + i + "_" + stub + "_filled")) - .texture("layer1", modLoc("item/cad/" + i + "_" + stub + "_filled_overlay")); - var sealed = withExistingParent(name + "_" + i + "_sealed", new ResourceLocation("item/generated")) - .texture("layer0", modLoc("item/cad/" + i + "_" + stub + "_sealed")) - .texture("layer1", modLoc("item/cad/" + i + "_" + stub + "_sealed_overlay")); - builder.override().predicate(ItemFocus.VARIANT_PRED, i).predicate(ItemFocus.OVERLAY_PRED, 0f) - .model(plain).end() - .override().predicate(ItemFocus.VARIANT_PRED, i).predicate(ItemFocus.OVERLAY_PRED, 1f) - .model(unsealed).end() - .override().predicate(ItemFocus.VARIANT_PRED, i).predicate(ItemFocus.OVERLAY_PRED, 2f) - .model(sealed).end(); - } - } + private void buildSealableIotaHolder(Item item, String stub, int numVariants) { + var name = getPath(item); + var builder = getBuilder(name); + for (int i = 0; i < numVariants; i++) { + var plain = + i == 0 + ? singleTexture( + name, + new ResourceLocation("item/generated"), + "layer0", + modLoc("item/cad/" + i + "_" + stub + "_empty")) + : withExistingParent(name + "_" + i, new ResourceLocation("item/generated")) + .texture("layer0", modLoc("item/cad/" + i + "_" + stub + "_empty")); + var unsealed = + withExistingParent(name + "_" + i + "_filled", new ResourceLocation("item/generated")) + .texture("layer0", modLoc("item/cad/" + i + "_" + stub + "_filled")) + .texture("layer1", modLoc("item/cad/" + i + "_" + stub + "_filled_overlay")); + var sealed = + withExistingParent(name + "_" + i + "_sealed", new ResourceLocation("item/generated")) + .texture("layer0", modLoc("item/cad/" + i + "_" + stub + "_sealed")) + .texture("layer1", modLoc("item/cad/" + i + "_" + stub + "_sealed_overlay")); + builder + .override() + .predicate(ItemFocus.VARIANT_PRED, i) + .predicate(ItemFocus.OVERLAY_PRED, 0f) + .model(plain) + .end() + .override() + .predicate(ItemFocus.VARIANT_PRED, i) + .predicate(ItemFocus.OVERLAY_PRED, 1f) + .model(unsealed) + .end() + .override() + .predicate(ItemFocus.VARIANT_PRED, i) + .predicate(ItemFocus.OVERLAY_PRED, 2f) + .model(sealed) + .end(); + } + } - private void buildScroll(Item item, String size) { - getBuilder(getPath(item)) - .override() - .predicate(ItemScroll.ANCIENT_PREDICATE, 0f) - .model(new ModelFile.UncheckedModelFile(modLoc("item/scroll_pristine_" + size))).end() - .override() - .predicate(ItemScroll.ANCIENT_PREDICATE, 1f) - .model(new ModelFile.UncheckedModelFile(modLoc("item/scroll_ancient_" + size))).end(); - } + private void buildScroll(Item item, String size) { + getBuilder(getPath(item)) + .override() + .predicate(ItemScroll.ANCIENT_PREDICATE, 0f) + .model(new ModelFile.UncheckedModelFile(modLoc("item/scroll_pristine_" + size))) + .end() + .override() + .predicate(ItemScroll.ANCIENT_PREDICATE, 1f) + .model(new ModelFile.UncheckedModelFile(modLoc("item/scroll_ancient_" + size))) + .end(); + } - private void buildStaff(Item item, String name) { - singleTexture("item/" + getPath(item), new ResourceLocation("item/handheld_rod"), - "layer0", modLoc("item/staff/" + name)); - getBuilder(getPath(item)) - .override() - .predicate(ItemStaff.FUNNY_LEVEL_PREDICATE, 0) - .model(new ModelFile.UncheckedModelFile(modLoc("item/" + name + "_staff"))) - .end().override() - .predicate(ItemStaff.FUNNY_LEVEL_PREDICATE, 1) - .model(new ModelFile.UncheckedModelFile(modLoc("item/old_staff"))) - .predicate(ItemStaff.FUNNY_LEVEL_PREDICATE, 2) - .model(new ModelFile.UncheckedModelFile(modLoc("item/cherry_staff"))) - .end(); - } + private void buildStaff(Item item, String name) { + singleTexture( + "item/" + getPath(item), + new ResourceLocation("item/handheld_rod"), + "layer0", + modLoc("item/staff/" + name)); + getBuilder(getPath(item)) + .override() + .predicate(ItemStaff.FUNNY_LEVEL_PREDICATE, 0) + .model(new ModelFile.UncheckedModelFile(modLoc("item/" + name + "_staff"))) + .end() + .override() + .predicate(ItemStaff.FUNNY_LEVEL_PREDICATE, 1) + .model(new ModelFile.UncheckedModelFile(modLoc("item/old_staff"))) + .predicate(ItemStaff.FUNNY_LEVEL_PREDICATE, 2) + .model(new ModelFile.UncheckedModelFile(modLoc("item/cherry_staff"))) + .end(); + } - private void buildPackagedSpell(Item item, String stub, int numVariants) { - var name = getPath(item); - var builder = getBuilder(name); - for (int i = 0; i < numVariants; i++) { - var plain = i == 0 ? singleTexture(name, new ResourceLocation("item/generated"), - "layer0", modLoc("item/cad/" + i + "_" + stub)) - : withExistingParent(name + "_" + i, new ResourceLocation("item/generated")) - .texture("layer0", modLoc("item/cad/" + i + "_" + stub)); - var filled = withExistingParent(name + "_" + i + "_filled", new ResourceLocation("item/generated")) - .texture("layer0", modLoc("item/cad/" + i + "_" + stub)) - .texture("layer1", modLoc("item/cad/" + i + "_" + stub + "_overlay")); - builder.override().predicate(ItemFocus.VARIANT_PRED, i).predicate(ItemPackagedHex.HAS_PATTERNS_PRED, -0.01f) - .model(plain).end() - .override().predicate(ItemFocus.VARIANT_PRED, i).predicate(ItemPackagedHex.HAS_PATTERNS_PRED, 1f - 0.01f) - .model(filled).end(); - } - } + private void buildPackagedSpell(Item item, String stub, int numVariants) { + var name = getPath(item); + var builder = getBuilder(name); + for (int i = 0; i < numVariants; i++) { + var plain = + i == 0 + ? singleTexture( + name, + new ResourceLocation("item/generated"), + "layer0", + modLoc("item/cad/" + i + "_" + stub)) + : withExistingParent(name + "_" + i, new ResourceLocation("item/generated")) + .texture("layer0", modLoc("item/cad/" + i + "_" + stub)); + var filled = + withExistingParent(name + "_" + i + "_filled", new ResourceLocation("item/generated")) + .texture("layer0", modLoc("item/cad/" + i + "_" + stub)) + .texture("layer1", modLoc("item/cad/" + i + "_" + stub + "_overlay")); + builder + .override() + .predicate(ItemFocus.VARIANT_PRED, i) + .predicate(ItemPackagedHex.HAS_PATTERNS_PRED, -0.01f) + .model(plain) + .end() + .override() + .predicate(ItemFocus.VARIANT_PRED, i) + .predicate(ItemPackagedHex.HAS_PATTERNS_PRED, 1f - 0.01f) + .model(filled) + .end(); + } + } - private void buildFourVariantGaslight(String name, String path, - BiFunction<String, ResourceLocation, ModelFile> makeModel) { - var builder = getBuilder(name); - for (int i = 0; i < BlockQuenchedAllay.VARIANTS; i++) { - var textureLoc = modLoc(path + "_" + i); - var model = makeModel.apply(name, textureLoc); + private void buildFourVariantGaslight( + String name, String path, BiFunction<String, ResourceLocation, ModelFile> makeModel) { + var builder = getBuilder(name); + for (int i = 0; i < BlockQuenchedAllay.VARIANTS; i++) { + var textureLoc = modLoc(path + "_" + i); + var model = makeModel.apply(name, textureLoc); - builder.override() - .predicate(GaslightingTracker.GASLIGHTING_PRED, i) - .model(model) - .end(); - } - } + builder.override().predicate(GaslightingTracker.GASLIGHTING_PRED, i).model(model).end(); + } + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/CuriosApiInterop.java b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/CuriosApiInterop.java index dfb750c35a..6ce260f470 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/CuriosApiInterop.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/CuriosApiInterop.java @@ -6,6 +6,8 @@ import at.petrak.hexcasting.forge.cap.ForgeCapabilityHandler; import at.petrak.hexcasting.interop.HexInterop; import com.google.common.collect.Multimap; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.item.ItemStack; @@ -19,66 +21,69 @@ import top.theillusivec4.curios.api.SlotTypePreset; import top.theillusivec4.curios.api.type.capability.ICurio; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicReference; - public class CuriosApiInterop { - static class Wrapper implements ICurio { - private final ItemStack stack; - private final HexBaubleItem bauble; - - Wrapper(ItemStack stack) { - this.stack = stack; - if (stack.getItem() instanceof HexBaubleItem bauble) { - this.bauble = bauble; - } else { - throw new IllegalArgumentException("Item stack " + stack + " wasn't a bauble item weewoo"); - } - } + static class Wrapper implements ICurio { + private final ItemStack stack; + private final HexBaubleItem bauble; - @Override - public ItemStack getStack() { - return stack; - } + Wrapper(ItemStack stack) { + this.stack = stack; + if (stack.getItem() instanceof HexBaubleItem bauble) { + this.bauble = bauble; + } else { + throw new IllegalArgumentException("Item stack " + stack + " wasn't a bauble item weewoo"); + } + } - @Override - public Multimap<Attribute, AttributeModifier> getAttributeModifiers(SlotContext slotContext, UUID uuid) { - var map = ICurio.super.getAttributeModifiers(slotContext, uuid); - map.putAll(this.bauble.getHexBaubleAttrs(this.stack)); - return map; - } - } + @Override + public ItemStack getStack() { + return stack; + } - public static ICapabilityProvider curioCap(ItemStack stack) { - return ForgeCapabilityHandler.makeProvider(CuriosCapability.ITEM, new Wrapper(stack)); - } + @Override + public Multimap<Attribute, AttributeModifier> getAttributeModifiers( + SlotContext slotContext, UUID uuid) { + var map = ICurio.super.getAttributeModifiers(slotContext, uuid); + map.putAll(this.bauble.getHexBaubleAttrs(this.stack)); + return map; + } + } + public static ICapabilityProvider curioCap(ItemStack stack) { + return ForgeCapabilityHandler.makeProvider(CuriosCapability.ITEM, new Wrapper(stack)); + } - public static void init() { - DiscoveryHandlers.addDebugItemDiscoverer((player, type) -> { - AtomicReference<ItemStack> result = new AtomicReference<>(ItemStack.EMPTY); - player.getCapability(CuriosCapability.INVENTORY).ifPresent(handler -> { - for (var stacksHandler : handler.getCurios().values()) { - var stacks = stacksHandler.getStacks(); - for (int i = 0; i < stacks.getSlots(); i++) { - var stack = stacks.getStackInSlot(i); - if (ItemCreativeUnlocker.isDebug(stack, type)) { - result.set(stack); - return; - } - } - } - }); - return result.get(); - }); - } + public static void init() { + DiscoveryHandlers.addDebugItemDiscoverer( + (player, type) -> { + AtomicReference<ItemStack> result = new AtomicReference<>(ItemStack.EMPTY); + player + .getCapability(CuriosCapability.INVENTORY) + .ifPresent( + handler -> { + for (var stacksHandler : handler.getCurios().values()) { + var stacks = stacksHandler.getStacks(); + for (int i = 0; i < stacks.getSlots(); i++) { + var stack = stacks.getStackInSlot(i); + if (ItemCreativeUnlocker.isDebug(stack, type)) { + result.set(stack); + return; + } + } + } + }); + return result.get(); + }); + } - public static void onInterModEnqueue(final InterModEnqueueEvent event) { - InterModComms.sendTo(HexInterop.Forge.CURIOS_API_ID, SlotTypeMessage.REGISTER_TYPE, - () -> SlotTypePreset.HEAD.getMessageBuilder().build()); - } + public static void onInterModEnqueue(final InterModEnqueueEvent event) { + InterModComms.sendTo( + HexInterop.Forge.CURIOS_API_ID, + SlotTypeMessage.REGISTER_TYPE, + () -> SlotTypePreset.HEAD.getMessageBuilder().build()); + } - public static void onClientSetup(final FMLClientSetupEvent event) { - CuriosRenderers.register(); - } + public static void onClientSetup(final FMLClientSetupEvent event) { + CuriosRenderers.register(); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/CuriosRenderers.java b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/CuriosRenderers.java index 3ec7edd483..85ae20a156 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/CuriosRenderers.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/CuriosRenderers.java @@ -15,16 +15,22 @@ @OnlyIn(Dist.CLIENT) public class CuriosRenderers { - public static void register() { - CuriosRendererRegistry.register(HexItems.SCRYING_LENS, () -> new LensCurioRenderer(Minecraft.getInstance().getEntityModels().bakeLayer(LensCurioRenderer.LAYER))); - } + public static void register() { + CuriosRendererRegistry.register( + HexItems.SCRYING_LENS, + () -> + new LensCurioRenderer( + Minecraft.getInstance().getEntityModels().bakeLayer(LensCurioRenderer.LAYER))); + } - public static void onLayerRegister(final EntityRenderersEvent.RegisterLayerDefinitions event) { - event.registerLayerDefinition(LensCurioRenderer.LAYER, () -> { - CubeListBuilder builder = new CubeListBuilder(); - MeshDefinition mesh = HumanoidModel.createMesh(CubeDeformation.NONE, 0); - mesh.getRoot().addOrReplaceChild("head", builder, PartPose.ZERO); - return LayerDefinition.create(mesh, 1, 1); - }); - } + public static void onLayerRegister(final EntityRenderersEvent.RegisterLayerDefinitions event) { + event.registerLayerDefinition( + LensCurioRenderer.LAYER, + () -> { + CubeListBuilder builder = new CubeListBuilder(); + MeshDefinition mesh = HumanoidModel.createMesh(CubeDeformation.NONE, 0); + mesh.getRoot().addOrReplaceChild("head", builder, PartPose.ZERO); + return LayerDefinition.create(mesh, 1, 1); + }); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/LensCurioRenderer.java b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/LensCurioRenderer.java index 38f5ff065f..d1d5601276 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/LensCurioRenderer.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/curios/LensCurioRenderer.java @@ -19,37 +19,61 @@ import top.theillusivec4.curios.api.client.ICurioRenderer; public class LensCurioRenderer implements ICurioRenderer { - public static final ModelLayerLocation LAYER = new ModelLayerLocation(new ResourceLocation(HexAPI.MOD_ID, "lens"), "lens"); - - private final HumanoidModel<LivingEntity> model; - - public LensCurioRenderer(ModelPart part) { - this.model = new HumanoidModel<>(part); - } - - @Override - public <T extends LivingEntity, M extends EntityModel<T>> void render(ItemStack stack, SlotContext slotContext, PoseStack matrixStack, RenderLayerParent<T, M> renderLayerParent, MultiBufferSource renderTypeBuffer, int light, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { - // https://github.com/Creators-of-Create/Create/blob/ee33823ed0b5084af10ed131a1626ce71db4c07e/src/main/java/com/simibubi/create/compat/curios/GogglesCurioRenderer.java - - // Prepare values for transformation - model.setupAnim(slotContext.entity(), limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); - model.prepareMobModel(slotContext.entity(), limbSwing, limbSwingAmount, partialTicks); - ICurioRenderer.followHeadRotations(slotContext.entity(), model.head); - - // Translate and rotate with our head - matrixStack.pushPose(); - matrixStack.translate(model.head.x / 16.0, model.head.y / 16.0, model.head.z / 16.0); - matrixStack.mulPose(Axis.YP.rotation(model.head.yRot)); - matrixStack.mulPose(Axis.XP.rotation(model.head.xRot)); - - // Translate and scale to our head - matrixStack.translate(0, -0.25, 0); - matrixStack.mulPose(Axis.ZP.rotationDegrees(180.0f)); - matrixStack.scale(0.625f, 0.625f, 0.625f); - - // Render - var instance = Minecraft.getInstance(); - instance.getItemRenderer().renderStatic(stack, ItemDisplayContext.HEAD, light, OverlayTexture.NO_OVERLAY, matrixStack, renderTypeBuffer, instance.level, 0); - matrixStack.popPose(); - } + public static final ModelLayerLocation LAYER = + new ModelLayerLocation(new ResourceLocation(HexAPI.MOD_ID, "lens"), "lens"); + + private final HumanoidModel<LivingEntity> model; + + public LensCurioRenderer(ModelPart part) { + this.model = new HumanoidModel<>(part); + } + + @Override + public <T extends LivingEntity, M extends EntityModel<T>> void render( + ItemStack stack, + SlotContext slotContext, + PoseStack matrixStack, + RenderLayerParent<T, M> renderLayerParent, + MultiBufferSource renderTypeBuffer, + int light, + float limbSwing, + float limbSwingAmount, + float partialTicks, + float ageInTicks, + float netHeadYaw, + float headPitch) { + // https://github.com/Creators-of-Create/Create/blob/ee33823ed0b5084af10ed131a1626ce71db4c07e/src/main/java/com/simibubi/create/compat/curios/GogglesCurioRenderer.java + + // Prepare values for transformation + model.setupAnim( + slotContext.entity(), limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); + model.prepareMobModel(slotContext.entity(), limbSwing, limbSwingAmount, partialTicks); + ICurioRenderer.followHeadRotations(slotContext.entity(), model.head); + + // Translate and rotate with our head + matrixStack.pushPose(); + matrixStack.translate(model.head.x / 16.0, model.head.y / 16.0, model.head.z / 16.0); + matrixStack.mulPose(Axis.YP.rotation(model.head.yRot)); + matrixStack.mulPose(Axis.XP.rotation(model.head.xRot)); + + // Translate and scale to our head + matrixStack.translate(0, -0.25, 0); + matrixStack.mulPose(Axis.ZP.rotationDegrees(180.0f)); + matrixStack.scale(0.625f, 0.625f, 0.625f); + + // Render + var instance = Minecraft.getInstance(); + instance + .getItemRenderer() + .renderStatic( + stack, + ItemDisplayContext.HEAD, + light, + OverlayTexture.NO_OVERLAY, + matrixStack, + renderTypeBuffer, + instance.level, + 0); + matrixStack.popPose(); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/BrainsweepRecipeCategory.java b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/BrainsweepRecipeCategory.java index 6dddb8015a..639322744f 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/BrainsweepRecipeCategory.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/BrainsweepRecipeCategory.java @@ -1,8 +1,13 @@ package at.petrak.hexcasting.forge.interop.jei; +import static at.petrak.hexcasting.api.HexAPI.modLoc; +import static at.petrak.hexcasting.client.render.RenderLib.renderEntity; + import at.petrak.hexcasting.client.ClientTickCounter; import at.petrak.hexcasting.common.recipe.BrainsweepRecipe; import com.mojang.blaze3d.systems.RenderSystem; +import java.util.Collections; +import java.util.List; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.drawable.IDrawable; import mezz.jei.api.gui.drawable.IDrawableStatic; @@ -22,84 +27,85 @@ import net.minecraftforge.api.distmarker.OnlyIn; import org.jetbrains.annotations.NotNull; -import java.util.Collections; -import java.util.List; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; -import static at.petrak.hexcasting.client.render.RenderLib.renderEntity; - public class BrainsweepRecipeCategory implements IRecipeCategory<BrainsweepRecipe> { - public static final ResourceLocation UID = modLoc("brainsweep"); + public static final ResourceLocation UID = modLoc("brainsweep"); - private final IDrawableStatic background; - private final IDrawable icon; - private final Component localizedName; + private final IDrawableStatic background; + private final IDrawable icon; + private final Component localizedName; - public BrainsweepRecipeCategory(IGuiHelper guiHelper) { - ResourceLocation location = modLoc("textures/gui/brainsweep_jei.png"); - background = guiHelper.drawableBuilder(location, 0, 0, 118, 86).setTextureSize(128, 128).build(); - var brainsweep = modLoc("brainsweep"); - localizedName = Component.translatable("hexcasting.action." + brainsweep); - icon = new PatternDrawable(brainsweep, 16, 16); - } + public BrainsweepRecipeCategory(IGuiHelper guiHelper) { + ResourceLocation location = modLoc("textures/gui/brainsweep_jei.png"); + background = + guiHelper.drawableBuilder(location, 0, 0, 118, 86).setTextureSize(128, 128).build(); + var brainsweep = modLoc("brainsweep"); + localizedName = Component.translatable("hexcasting.action." + brainsweep); + icon = new PatternDrawable(brainsweep, 16, 16); + } - @Override - @OnlyIn(Dist.CLIENT) - public @NotNull - Component getTitle() { - return localizedName; - } + @Override + @OnlyIn(Dist.CLIENT) + public @NotNull Component getTitle() { + return localizedName; + } - @Override - public @NotNull - IDrawable getBackground() { - return background; - } + @Override + public @NotNull IDrawable getBackground() { + return background; + } - @Override - public @NotNull - IDrawable getIcon() { - return icon; - } + @Override + public @NotNull IDrawable getIcon() { + return icon; + } - @Override - public @NotNull - List<Component> getTooltipStrings(@NotNull BrainsweepRecipe recipe, - @NotNull IRecipeSlotsView recipeSlotsView, double mouseX, double mouseY) { - if (37 <= mouseX && mouseX <= 37 + 26 && 19 <= mouseY && mouseY <= 19 + 48) { - Minecraft mc = Minecraft.getInstance(); - return recipe.entityIn().getTooltip(mc.options.advancedItemTooltips); - } + @Override + public @NotNull List<Component> getTooltipStrings( + @NotNull BrainsweepRecipe recipe, + @NotNull IRecipeSlotsView recipeSlotsView, + double mouseX, + double mouseY) { + if (37 <= mouseX && mouseX <= 37 + 26 && 19 <= mouseY && mouseY <= 19 + 48) { + Minecraft mc = Minecraft.getInstance(); + return recipe.entityIn().getTooltip(mc.options.advancedItemTooltips); + } - return Collections.emptyList(); - } + return Collections.emptyList(); + } - @Override - public void draw(@NotNull BrainsweepRecipe recipe, @NotNull IRecipeSlotsView recipeSlotsView, @NotNull GuiGraphics graphics, double mouseX, double mouseY) { - ClientLevel level = Minecraft.getInstance().level; - if (level != null) { - var example = recipe.entityIn().exampleEntity(level); - if (example == null) - return; + @Override + public void draw( + @NotNull BrainsweepRecipe recipe, + @NotNull IRecipeSlotsView recipeSlotsView, + @NotNull GuiGraphics graphics, + double mouseX, + double mouseY) { + ClientLevel level = Minecraft.getInstance().level; + if (level != null) { + var example = recipe.entityIn().exampleEntity(level); + if (example == null) return; - RenderSystem.enableBlend(); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - renderEntity(graphics, example, level, 50, 62.5f, ClientTickCounter.getTotal(), 20, 0); - } - } + RenderSystem.enableBlend(); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + renderEntity(graphics, example, level, 50, 62.5f, ClientTickCounter.getTotal(), 20, 0); + } + } - @Override - public void setRecipe(@NotNull IRecipeLayoutBuilder builder, @NotNull BrainsweepRecipe recipe, - @NotNull IFocusGroup focuses) { - builder.addSlot(RecipeIngredientRole.INPUT, 12, 35) - .addItemStacks(recipe.blockIn().getDisplayedStacks()); - builder.addSlot(RecipeIngredientRole.OUTPUT, 87, 35) - .addItemStack(new ItemStack(recipe.result().getBlock())); - } + @Override + public void setRecipe( + @NotNull IRecipeLayoutBuilder builder, + @NotNull BrainsweepRecipe recipe, + @NotNull IFocusGroup focuses) { + builder + .addSlot(RecipeIngredientRole.INPUT, 12, 35) + .addItemStacks(recipe.blockIn().getDisplayedStacks()); + builder + .addSlot(RecipeIngredientRole.OUTPUT, 87, 35) + .addItemStack(new ItemStack(recipe.result().getBlock())); + } - @Override - public @NotNull - RecipeType<BrainsweepRecipe> getRecipeType() { - return HexJEIPlugin.BRAINSWEEPING; - } + @Override + public @NotNull RecipeType<BrainsweepRecipe> getRecipeType() { + return HexJEIPlugin.BRAINSWEEPING; + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/EdifyRecipeCategory.java b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/EdifyRecipeCategory.java index 84ab9bab31..82d29c957b 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/EdifyRecipeCategory.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/EdifyRecipeCategory.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.forge.interop.jei; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.common.casting.actions.spells.OpEdifySapling; import at.petrak.hexcasting.common.lib.HexBlocks; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; @@ -19,60 +21,63 @@ import net.minecraftforge.api.distmarker.OnlyIn; import org.jetbrains.annotations.NotNull; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class EdifyRecipeCategory implements IRecipeCategory<OpEdifySapling> { - public static final ResourceLocation UID = modLoc("edify_tree"); + public static final ResourceLocation UID = modLoc("edify_tree"); - private final IDrawableStatic background; - private final IDrawable icon; - private final Component localizedName; + private final IDrawableStatic background; + private final IDrawable icon; + private final Component localizedName; - public EdifyRecipeCategory(IGuiHelper guiHelper) { - ResourceLocation location = modLoc("textures/gui/edify_jei.png"); - background = guiHelper.drawableBuilder(location, 0, 0, 79, 61).setTextureSize(128, 128).build(); - var edify = modLoc("edify"); - localizedName = Component.translatable("hexcasting.action." + edify); - icon = new PatternDrawable(edify, 16, 16).strokeOrder(false); - } + public EdifyRecipeCategory(IGuiHelper guiHelper) { + ResourceLocation location = modLoc("textures/gui/edify_jei.png"); + background = guiHelper.drawableBuilder(location, 0, 0, 79, 61).setTextureSize(128, 128).build(); + var edify = modLoc("edify"); + localizedName = Component.translatable("hexcasting.action." + edify); + icon = new PatternDrawable(edify, 16, 16).strokeOrder(false); + } - @Override - @OnlyIn(Dist.CLIENT) - public @NotNull Component getTitle() { - return localizedName; - } + @Override + @OnlyIn(Dist.CLIENT) + public @NotNull Component getTitle() { + return localizedName; + } - @Override - public @NotNull IDrawable getBackground() { - return background; - } + @Override + public @NotNull IDrawable getBackground() { + return background; + } - @Override - public @NotNull IDrawable getIcon() { - return icon; - } + @Override + public @NotNull IDrawable getIcon() { + return icon; + } - @Override - public void setRecipe(@NotNull IRecipeLayoutBuilder builder, @NotNull OpEdifySapling recipe, - @NotNull IFocusGroup focuses) { - builder.addSlot(RecipeIngredientRole.INPUT, 12, 22) - .addIngredients(Ingredient.of(ItemTags.SAPLINGS)); + @Override + public void setRecipe( + @NotNull IRecipeLayoutBuilder builder, + @NotNull OpEdifySapling recipe, + @NotNull IFocusGroup focuses) { + builder + .addSlot(RecipeIngredientRole.INPUT, 12, 22) + .addIngredients(Ingredient.of(ItemTags.SAPLINGS)); - builder.addSlot(RecipeIngredientRole.OUTPUT, 51, 10) - .addItemStack(new ItemStack(HexBlocks.AMETHYST_EDIFIED_LEAVES)) - .addItemStack(new ItemStack(HexBlocks.AVENTURINE_EDIFIED_LEAVES)) - .addItemStack(new ItemStack(HexBlocks.CITRINE_EDIFIED_LEAVES)); - builder.addSlot(RecipeIngredientRole.OUTPUT, 51, 35) - .addItemStack(new ItemStack(HexBlocks.EDIFIED_LOG)) - .addItemStack(new ItemStack(HexBlocks.EDIFIED_LOG_AMETHYST)) - .addItemStack(new ItemStack(HexBlocks.EDIFIED_LOG_AVENTURINE)) - .addItemStack(new ItemStack(HexBlocks.EDIFIED_LOG_CITRINE)); -// .addItemStack(new ItemStack(HexBlocks.EDIFIED_LOG_PURPLE)); + builder + .addSlot(RecipeIngredientRole.OUTPUT, 51, 10) + .addItemStack(new ItemStack(HexBlocks.AMETHYST_EDIFIED_LEAVES)) + .addItemStack(new ItemStack(HexBlocks.AVENTURINE_EDIFIED_LEAVES)) + .addItemStack(new ItemStack(HexBlocks.CITRINE_EDIFIED_LEAVES)); + builder + .addSlot(RecipeIngredientRole.OUTPUT, 51, 35) + .addItemStack(new ItemStack(HexBlocks.EDIFIED_LOG)) + .addItemStack(new ItemStack(HexBlocks.EDIFIED_LOG_AMETHYST)) + .addItemStack(new ItemStack(HexBlocks.EDIFIED_LOG_AVENTURINE)) + .addItemStack(new ItemStack(HexBlocks.EDIFIED_LOG_CITRINE)); + // .addItemStack(new ItemStack(HexBlocks.EDIFIED_LOG_PURPLE)); - } + } - @Override - public @NotNull RecipeType<OpEdifySapling> getRecipeType() { - return HexJEIPlugin.EDIFY; - } + @Override + public @NotNull RecipeType<OpEdifySapling> getRecipeType() { + return HexJEIPlugin.EDIFY; + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/HexJEIPlugin.java b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/HexJEIPlugin.java index 32572ba10c..afd29a4053 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/HexJEIPlugin.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/HexJEIPlugin.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.forge.interop.jei; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.common.casting.actions.spells.OpEdifySapling; import at.petrak.hexcasting.common.casting.actions.spells.OpMakeBattery; @@ -8,6 +10,7 @@ import at.petrak.hexcasting.common.recipe.BrainsweepRecipe; import at.petrak.hexcasting.common.recipe.HexRecipeStuffRegistry; import at.petrak.hexcasting.interop.utils.PhialRecipeStackBuilder; +import java.util.List; import mezz.jei.api.IModPlugin; import mezz.jei.api.JeiPlugin; import mezz.jei.api.recipe.RecipeType; @@ -20,70 +23,67 @@ import net.minecraft.world.level.Level; import org.jetbrains.annotations.NotNull; -import java.util.List; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - @JeiPlugin public class HexJEIPlugin implements IModPlugin { - private static final ResourceLocation UID = modLoc(HexAPI.MOD_ID); + private static final ResourceLocation UID = modLoc(HexAPI.MOD_ID); - public static final RecipeType<BrainsweepRecipe> BRAINSWEEPING = - RecipeType.create(HexAPI.MOD_ID, "brainsweeping", BrainsweepRecipe.class); + public static final RecipeType<BrainsweepRecipe> BRAINSWEEPING = + RecipeType.create(HexAPI.MOD_ID, "brainsweeping", BrainsweepRecipe.class); - // Only one entry, might as well use the op class - public static final RecipeType<OpMakeBattery> PHIAL = - RecipeType.create(HexAPI.MOD_ID, "craft_phial", OpMakeBattery.class); - public static final RecipeType<OpEdifySapling> EDIFY = - RecipeType.create(HexAPI.MOD_ID, "edify_tree", OpEdifySapling.class); + // Only one entry, might as well use the op class + public static final RecipeType<OpMakeBattery> PHIAL = + RecipeType.create(HexAPI.MOD_ID, "craft_phial", OpMakeBattery.class); + public static final RecipeType<OpEdifySapling> EDIFY = + RecipeType.create(HexAPI.MOD_ID, "edify_tree", OpEdifySapling.class); - @NotNull - @Override - public ResourceLocation getPluginUid() { - return UID; - } + @NotNull @Override + public ResourceLocation getPluginUid() { + return UID; + } - @Override - public void registerCategories(IRecipeCategoryRegistration registration) { - var guiHelper = registration.getJeiHelpers().getGuiHelper(); - registration.addRecipeCategories( - new BrainsweepRecipeCategory(guiHelper), - new PhialRecipeCategory(guiHelper), - new EdifyRecipeCategory(guiHelper)); - } + @Override + public void registerCategories(IRecipeCategoryRegistration registration) { + var guiHelper = registration.getJeiHelpers().getGuiHelper(); + registration.addRecipeCategories( + new BrainsweepRecipeCategory(guiHelper), + new PhialRecipeCategory(guiHelper), + new EdifyRecipeCategory(guiHelper)); + } - @Override - public void registerRecipes(@NotNull IRecipeRegistration registration) { - Level level = Minecraft.getInstance().level; - if (level != null) { - registration.addRecipes(BRAINSWEEPING, - level.getRecipeManager().getAllRecipesFor(HexRecipeStuffRegistry.BRAINSWEEP_TYPE)); - } + @Override + public void registerRecipes(@NotNull IRecipeRegistration registration) { + Level level = Minecraft.getInstance().level; + if (level != null) { + registration.addRecipes( + BRAINSWEEPING, + level.getRecipeManager().getAllRecipesFor(HexRecipeStuffRegistry.BRAINSWEEP_TYPE)); + } - if (PhialRecipeStackBuilder.shouldAddRecipe()) { - registration.addRecipes(PHIAL, List.of(OpMakeBattery.INSTANCE)); - } + if (PhialRecipeStackBuilder.shouldAddRecipe()) { + registration.addRecipes(PHIAL, List.of(OpMakeBattery.INSTANCE)); + } - registration.addRecipes(EDIFY, List.of(OpEdifySapling.INSTANCE)); - } + registration.addRecipes(EDIFY, List.of(OpEdifySapling.INSTANCE)); + } - @Override - public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) { - for (ItemStaff staff : new ItemStaff[]{ - HexItems.STAFF_OAK, - HexItems.STAFF_SPRUCE, - HexItems.STAFF_BIRCH, - HexItems.STAFF_JUNGLE, - HexItems.STAFF_ACACIA, - HexItems.STAFF_DARK_OAK, - HexItems.STAFF_CRIMSON, - HexItems.STAFF_WARPED, - HexItems.STAFF_MANGROVE, - HexItems.STAFF_CHERRY, - HexItems.STAFF_BAMBOO, - HexItems.STAFF_EDIFIED, - }) { - registration.addRecipeCatalyst(new ItemStack(staff), BRAINSWEEPING, PHIAL, EDIFY); - } - } + @Override + public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) { + for (ItemStaff staff : + new ItemStaff[] { + HexItems.STAFF_OAK, + HexItems.STAFF_SPRUCE, + HexItems.STAFF_BIRCH, + HexItems.STAFF_JUNGLE, + HexItems.STAFF_ACACIA, + HexItems.STAFF_DARK_OAK, + HexItems.STAFF_CRIMSON, + HexItems.STAFF_WARPED, + HexItems.STAFF_MANGROVE, + HexItems.STAFF_CHERRY, + HexItems.STAFF_BAMBOO, + HexItems.STAFF_EDIFIED, + }) { + registration.addRecipeCatalyst(new ItemStack(staff), BRAINSWEEPING, PHIAL, EDIFY); + } + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/PatternDrawable.java b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/PatternDrawable.java index bf96781a00..cdec6052e5 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/PatternDrawable.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/PatternDrawable.java @@ -15,59 +15,73 @@ import net.minecraft.resources.ResourceLocation; public class PatternDrawable implements IDrawable { - private final int width; - private final int height; + private final int width; + private final int height; - private boolean strokeOrder; - private final HexPattern pat; + private boolean strokeOrder; + private final HexPattern pat; - private PatternSettings patSets; + private PatternSettings patSets; - public PatternDrawable(ResourceLocation pattern, int w, int h) { - var regi = IXplatAbstractions.INSTANCE.getActionRegistry(); - var entry = regi.get(pattern); - this.strokeOrder = !HexUtils.isOfTag(regi, pattern, HexTags.Actions.PER_WORLD_PATTERN); - this.pat = entry.prototype(); - this.width = w; - this.height = h; - this.patSets = new PatternSettings("pattern_drawable_" + w + "_" + h, - new PositionSettings(width, height, 0, 0, - PatternSettings.AxisAlignment.CENTER_FIT, PatternSettings.AxisAlignment.CENTER_FIT, Math.max(width, height), 0, 0), - StrokeSettings.fromStroke(0.075 * Math.min(width, height)), - ZappySettings.READABLE); - } + public PatternDrawable(ResourceLocation pattern, int w, int h) { + var regi = IXplatAbstractions.INSTANCE.getActionRegistry(); + var entry = regi.get(pattern); + this.strokeOrder = !HexUtils.isOfTag(regi, pattern, HexTags.Actions.PER_WORLD_PATTERN); + this.pat = entry.prototype(); + this.width = w; + this.height = h; + this.patSets = + new PatternSettings( + "pattern_drawable_" + w + "_" + h, + new PositionSettings( + width, + height, + 0, + 0, + PatternSettings.AxisAlignment.CENTER_FIT, + PatternSettings.AxisAlignment.CENTER_FIT, + Math.max(width, height), + 0, + 0), + StrokeSettings.fromStroke(0.075 * Math.min(width, height)), + ZappySettings.READABLE); + } - @Override - public int getWidth() { - return width; - } + @Override + public int getWidth() { + return width; + } - @Override - public int getHeight() { - return height; - } + @Override + public int getHeight() { + return height; + } - public PatternDrawable strokeOrder(boolean order) { - if(order != strokeOrder){ - patSets = new PatternSettings("pattern_drawable_" + width + "_" + height + (order ? "" : "nostroke"), - patSets.posSets, - patSets.strokeSets, - order ? ZappySettings.READABLE : ZappySettings.STATIC - ); - } - strokeOrder = order; - return this; - } + public PatternDrawable strokeOrder(boolean order) { + if (order != strokeOrder) { + patSets = + new PatternSettings( + "pattern_drawable_" + width + "_" + height + (order ? "" : "nostroke"), + patSets.posSets, + patSets.strokeSets, + order ? ZappySettings.READABLE : ZappySettings.STATIC); + } + strokeOrder = order; + return this; + } - @Override - public void draw(GuiGraphics graphics, int x, int y) { - var ps = graphics.pose(); - ps.pushPose(); - ps.translate(x, y + 1, 0); - PatternRenderer.renderPattern(pat, graphics.pose(), patSets, - new PatternColors(0xc8_0c0a0c, 0xff_333030).withDotColors(0x80_666363, 0), - 0, 10 - ); - ps.popPose(); - } + @Override + public void draw(GuiGraphics graphics, int x, int y) { + var ps = graphics.pose(); + ps.pushPose(); + ps.translate(x, y + 1, 0); + PatternRenderer.renderPattern( + pat, + graphics.pose(), + patSets, + new PatternColors(0xc8_0c0a0c, 0xff_333030).withDotColors(0x80_666363, 0), + 0, + 10); + ps.popPose(); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/PhialRecipeCategory.java b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/PhialRecipeCategory.java index 23a4272a4e..b15a0bafc3 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/PhialRecipeCategory.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/interop/jei/PhialRecipeCategory.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.forge.interop.jei; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.mod.HexTags; import at.petrak.hexcasting.common.casting.actions.spells.OpMakeBattery; import at.petrak.hexcasting.interop.utils.PhialRecipeStackBuilder; @@ -18,57 +20,59 @@ import net.minecraftforge.api.distmarker.OnlyIn; import org.jetbrains.annotations.NotNull; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class PhialRecipeCategory implements IRecipeCategory<OpMakeBattery> { - public static final ResourceLocation UID = modLoc("craft_phial"); + public static final ResourceLocation UID = modLoc("craft_phial"); - private final IDrawableStatic background; - private final IDrawable icon; - private final Component localizedName; + private final IDrawableStatic background; + private final IDrawable icon; + private final Component localizedName; - public PhialRecipeCategory(IGuiHelper guiHelper) { - ResourceLocation location = modLoc("textures/gui/phial_jei.png"); - background = guiHelper.drawableBuilder(location, 0, 0, 113, 40).setTextureSize(128, 128).build(); - var craftPhial = modLoc("craft/battery"); - localizedName = Component.translatable("hexcasting.action." + craftPhial); - icon = new PatternDrawable(craftPhial, 12, 12); - } + public PhialRecipeCategory(IGuiHelper guiHelper) { + ResourceLocation location = modLoc("textures/gui/phial_jei.png"); + background = + guiHelper.drawableBuilder(location, 0, 0, 113, 40).setTextureSize(128, 128).build(); + var craftPhial = modLoc("craft/battery"); + localizedName = Component.translatable("hexcasting.action." + craftPhial); + icon = new PatternDrawable(craftPhial, 12, 12); + } - @Override - @OnlyIn(Dist.CLIENT) - public @NotNull Component getTitle() { - return localizedName; - } + @Override + @OnlyIn(Dist.CLIENT) + public @NotNull Component getTitle() { + return localizedName; + } - @Override - public @NotNull IDrawable getBackground() { - return background; - } + @Override + public @NotNull IDrawable getBackground() { + return background; + } - @Override - public @NotNull IDrawable getIcon() { - return icon; - } + @Override + public @NotNull IDrawable getIcon() { + return icon; + } - @Override - public void setRecipe(@NotNull IRecipeLayoutBuilder builder, @NotNull OpMakeBattery recipe, - @NotNull IFocusGroup focuses) { - var stacks = PhialRecipeStackBuilder.createStacks(); + @Override + public void setRecipe( + @NotNull IRecipeLayoutBuilder builder, + @NotNull OpMakeBattery recipe, + @NotNull IFocusGroup focuses) { + var stacks = PhialRecipeStackBuilder.createStacks(); - var inputSlot = builder.addSlot(RecipeIngredientRole.INPUT, 12, 12) - .addItemStacks(stacks.getFirst()); - builder.addSlot(RecipeIngredientRole.INPUT, 47, 12) - .addIngredients(Ingredient.of(HexTags.Items.PHIAL_BASE)); + var inputSlot = + builder.addSlot(RecipeIngredientRole.INPUT, 12, 12).addItemStacks(stacks.getFirst()); + builder + .addSlot(RecipeIngredientRole.INPUT, 47, 12) + .addIngredients(Ingredient.of(HexTags.Items.PHIAL_BASE)); - var outputSlot = builder.addSlot(RecipeIngredientRole.OUTPUT, 85, 12) - .addItemStacks(stacks.getSecond()); + var outputSlot = + builder.addSlot(RecipeIngredientRole.OUTPUT, 85, 12).addItemStacks(stacks.getSecond()); - builder.createFocusLink(inputSlot, outputSlot); - } + builder.createFocusLink(inputSlot, outputSlot); + } - @Override - public @NotNull RecipeType<OpMakeBattery> getRecipeType() { - return HexJEIPlugin.PHIAL; - } + @Override + public @NotNull RecipeType<OpMakeBattery> getRecipeType() { + return HexJEIPlugin.PHIAL; + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/lib/ForgeHexArgumentTypeRegistry.java b/Forge/src/main/java/at/petrak/hexcasting/forge/lib/ForgeHexArgumentTypeRegistry.java index 4a3450372a..fb85323d53 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/lib/ForgeHexArgumentTypeRegistry.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/lib/ForgeHexArgumentTypeRegistry.java @@ -12,24 +12,27 @@ // ArgumentTypeInfos.java public class ForgeHexArgumentTypeRegistry { - public static final DeferredRegister<ArgumentTypeInfo<?, ?>> ARGUMENT_TYPES = DeferredRegister.create( - ForgeRegistries.COMMAND_ARGUMENT_TYPES, HexAPI.MOD_ID); + public static final DeferredRegister<ArgumentTypeInfo<?, ?>> ARGUMENT_TYPES = + DeferredRegister.create(ForgeRegistries.COMMAND_ARGUMENT_TYPES, HexAPI.MOD_ID); - // how fucking ergonomic - public static final RegistryObject<ArgumentTypeInfo<PatternResLocArgument, - SingletonArgumentInfo<PatternResLocArgument>.Template>> - PATTERN_RESLOC = register(PatternResLocArgument.class, - "pattern", - SingletonArgumentInfo.contextFree(PatternResLocArgument::id) - ); + // how fucking ergonomic + public static final RegistryObject< + ArgumentTypeInfo< + PatternResLocArgument, SingletonArgumentInfo<PatternResLocArgument>.Template>> + PATTERN_RESLOC = + register( + PatternResLocArgument.class, + "pattern", + SingletonArgumentInfo.contextFree(PatternResLocArgument::id)); - private static <A extends ArgumentType<?>, T extends ArgumentTypeInfo.Template<A>, I extends ArgumentTypeInfo<A, T>> - RegistryObject<ArgumentTypeInfo<A, T>> register( - Class<A> clazz, - String name, - ArgumentTypeInfo<A, T> ati) { - var robj = ARGUMENT_TYPES.register(name, () -> ati); - ArgumentTypeInfos.registerByClass(clazz, ati); - return robj; - } + private static < + A extends ArgumentType<?>, + T extends ArgumentTypeInfo.Template<A>, + I extends ArgumentTypeInfo<A, T>> + RegistryObject<ArgumentTypeInfo<A, T>> register( + Class<A> clazz, String name, ArgumentTypeInfo<A, T> ati) { + var robj = ARGUMENT_TYPES.register(name, () -> ati); + ArgumentTypeInfos.registerByClass(clazz, ati); + return robj; + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/lib/ForgeHexLootMods.java b/Forge/src/main/java/at/petrak/hexcasting/forge/lib/ForgeHexLootMods.java index a967358df2..eeed1ea3b9 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/lib/ForgeHexLootMods.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/lib/ForgeHexLootMods.java @@ -11,13 +11,13 @@ import net.minecraftforge.registries.RegistryObject; public class ForgeHexLootMods { - public static final DeferredRegister<Codec<? extends IGlobalLootModifier>> REGISTRY = DeferredRegister.create( - ForgeRegistries.Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS, HexAPI.MOD_ID); + public static final DeferredRegister<Codec<? extends IGlobalLootModifier>> REGISTRY = + DeferredRegister.create(ForgeRegistries.Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS, HexAPI.MOD_ID); - public static final RegistryObject<Codec<ForgeHexScrollLootMod>> INJECT_SCROLLS = REGISTRY.register( - "inject_scrolls", ForgeHexScrollLootMod.CODEC); - public static final RegistryObject<Codec<ForgeHexLoreLootMod>> INJECT_LORE = REGISTRY.register( - "inject_lore", ForgeHexLoreLootMod.CODEC); - public static final RegistryObject<Codec<ForgeHexAmethystLootMod>> AMETHYST = REGISTRY.register( - "amethyst_cluster", ForgeHexAmethystLootMod.CODEC); + public static final RegistryObject<Codec<ForgeHexScrollLootMod>> INJECT_SCROLLS = + REGISTRY.register("inject_scrolls", ForgeHexScrollLootMod.CODEC); + public static final RegistryObject<Codec<ForgeHexLoreLootMod>> INJECT_LORE = + REGISTRY.register("inject_lore", ForgeHexLoreLootMod.CODEC); + public static final RegistryObject<Codec<ForgeHexAmethystLootMod>> AMETHYST = + REGISTRY.register("amethyst_cluster", ForgeHexAmethystLootMod.CODEC); } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/loot/ForgeHexAmethystLootMod.java b/Forge/src/main/java/at/petrak/hexcasting/forge/loot/ForgeHexAmethystLootMod.java index 671e9cec5b..58d76c78db 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/loot/ForgeHexAmethystLootMod.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/loot/ForgeHexAmethystLootMod.java @@ -7,44 +7,46 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import java.util.function.Supplier; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; import net.minecraftforge.common.loot.LootModifier; import org.jetbrains.annotations.NotNull; -import java.util.function.Supplier; - public class ForgeHexAmethystLootMod extends LootModifier { - public static final Supplier<Codec<ForgeHexAmethystLootMod>> CODEC = - Suppliers.memoize(() -> RecordCodecBuilder.create( - inst -> codecStart(inst).and( - Codec.DOUBLE.fieldOf("shardDelta").forGetter(it -> it.shardDelta) - ).apply(inst, ForgeHexAmethystLootMod::new) - )); - - public final double shardDelta; - - public ForgeHexAmethystLootMod(LootItemCondition[] conditionsIn, double shardDelta) { - super(conditionsIn); - this.shardDelta = shardDelta; - } - - @Override - protected @NotNull ObjectArrayList<ItemStack> doApply(ObjectArrayList<ItemStack> generatedLoot, - LootContext context) { - var injectPool = context.getResolver().getLootTable(HexLootHandler.TABLE_INJECT_AMETHYST_CLUSTER); - injectPool.getRandomItemsRaw(context, generatedLoot::add); - - for (var stack : generatedLoot) { - AmethystReducerFunc.doStatic(stack, context, this.shardDelta); - } - - return generatedLoot; - } - - @Override - public Codec<ForgeHexAmethystLootMod> codec() { - return ForgeHexLootMods.AMETHYST.get(); - } + public static final Supplier<Codec<ForgeHexAmethystLootMod>> CODEC = + Suppliers.memoize( + () -> + RecordCodecBuilder.create( + inst -> + codecStart(inst) + .and(Codec.DOUBLE.fieldOf("shardDelta").forGetter(it -> it.shardDelta)) + .apply(inst, ForgeHexAmethystLootMod::new))); + + public final double shardDelta; + + public ForgeHexAmethystLootMod(LootItemCondition[] conditionsIn, double shardDelta) { + super(conditionsIn); + this.shardDelta = shardDelta; + } + + @Override + protected @NotNull ObjectArrayList<ItemStack> doApply( + ObjectArrayList<ItemStack> generatedLoot, LootContext context) { + var injectPool = + context.getResolver().getLootTable(HexLootHandler.TABLE_INJECT_AMETHYST_CLUSTER); + injectPool.getRandomItemsRaw(context, generatedLoot::add); + + for (var stack : generatedLoot) { + AmethystReducerFunc.doStatic(stack, context, this.shardDelta); + } + + return generatedLoot; + } + + @Override + public Codec<ForgeHexAmethystLootMod> codec() { + return ForgeHexLootMods.AMETHYST.get(); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/loot/ForgeHexLoreLootMod.java b/Forge/src/main/java/at/petrak/hexcasting/forge/loot/ForgeHexLoreLootMod.java index e5de13a237..b5fb6ff946 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/loot/ForgeHexLoreLootMod.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/loot/ForgeHexLoreLootMod.java @@ -6,40 +6,41 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import java.util.function.Supplier; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; import net.minecraftforge.common.loot.LootModifier; import org.jetbrains.annotations.NotNull; -import java.util.function.Supplier; - public class ForgeHexLoreLootMod extends LootModifier { - public static final Supplier<Codec<ForgeHexLoreLootMod>> CODEC = - Suppliers.memoize(() -> RecordCodecBuilder.create( - inst -> codecStart(inst).and( - Codec.DOUBLE.fieldOf("chance").forGetter(it -> it.chance) - ).apply(inst, ForgeHexLoreLootMod::new) - )); + public static final Supplier<Codec<ForgeHexLoreLootMod>> CODEC = + Suppliers.memoize( + () -> + RecordCodecBuilder.create( + inst -> + codecStart(inst) + .and(Codec.DOUBLE.fieldOf("chance").forGetter(it -> it.chance)) + .apply(inst, ForgeHexLoreLootMod::new))); - public final double chance; + public final double chance; - public ForgeHexLoreLootMod(LootItemCondition[] conditionsIn, double chance) { - super(conditionsIn); - this.chance = chance; - } + public ForgeHexLoreLootMod(LootItemCondition[] conditionsIn, double chance) { + super(conditionsIn); + this.chance = chance; + } - @Override - protected @NotNull ObjectArrayList<ItemStack> doApply(ObjectArrayList<ItemStack> generatedLoot, - LootContext context) { - if (context.getRandom().nextDouble() < this.chance) { - generatedLoot.add(new ItemStack(HexItems.LORE_FRAGMENT)); - } - return generatedLoot; - } + @Override + protected @NotNull ObjectArrayList<ItemStack> doApply( + ObjectArrayList<ItemStack> generatedLoot, LootContext context) { + if (context.getRandom().nextDouble() < this.chance) { + generatedLoot.add(new ItemStack(HexItems.LORE_FRAGMENT)); + } + return generatedLoot; + } - @Override - public Codec<ForgeHexLoreLootMod> codec() { - return ForgeHexLootMods.INJECT_LORE.get(); - } + @Override + public Codec<ForgeHexLoreLootMod> codec() { + return ForgeHexLootMods.INJECT_LORE.get(); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/loot/ForgeHexScrollLootMod.java b/Forge/src/main/java/at/petrak/hexcasting/forge/loot/ForgeHexScrollLootMod.java index ffae0a85ce..0e2a8e556a 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/loot/ForgeHexScrollLootMod.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/loot/ForgeHexScrollLootMod.java @@ -8,6 +8,7 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import java.util.function.Supplier; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; @@ -15,37 +16,37 @@ import net.minecraftforge.common.loot.LootModifier; import org.jetbrains.annotations.NotNull; -import java.util.function.Supplier; - public class ForgeHexScrollLootMod extends LootModifier { - public static final Supplier<Codec<ForgeHexScrollLootMod>> CODEC = - Suppliers.memoize(() -> RecordCodecBuilder.create( - inst -> codecStart(inst).and( - Codec.INT.fieldOf("countRange").forGetter(it -> it.countRange) - ).apply(inst, ForgeHexScrollLootMod::new) - )); + public static final Supplier<Codec<ForgeHexScrollLootMod>> CODEC = + Suppliers.memoize( + () -> + RecordCodecBuilder.create( + inst -> + codecStart(inst) + .and(Codec.INT.fieldOf("countRange").forGetter(it -> it.countRange)) + .apply(inst, ForgeHexScrollLootMod::new))); - public final int countRange; + public final int countRange; - public ForgeHexScrollLootMod(LootItemCondition[] conditionsIn, int countRange) { - super(conditionsIn); - this.countRange = countRange; - } + public ForgeHexScrollLootMod(LootItemCondition[] conditionsIn, int countRange) { + super(conditionsIn); + this.countRange = countRange; + } - @Override - protected @NotNull ObjectArrayList<ItemStack> doApply(ObjectArrayList<ItemStack> generatedLoot, - LootContext context) { - int count = HexLootHandler.getScrollCount(this.countRange, context.getRandom()); - for (int i = 0; i < count; i++) { - var newStack = new ItemStack(HexItems.SCROLL_LARGE); - AddPerWorldPatternToScrollFunc.doStatic(newStack, context); - generatedLoot.add(newStack); - } - return generatedLoot; - } + @Override + protected @NotNull ObjectArrayList<ItemStack> doApply( + ObjectArrayList<ItemStack> generatedLoot, LootContext context) { + int count = HexLootHandler.getScrollCount(this.countRange, context.getRandom()); + for (int i = 0; i < count; i++) { + var newStack = new ItemStack(HexItems.SCROLL_LARGE); + AddPerWorldPatternToScrollFunc.doStatic(newStack, context); + generatedLoot.add(newStack); + } + return generatedLoot; + } - @Override - public Codec<? extends IGlobalLootModifier> codec() { - return ForgeHexLootMods.INJECT_SCROLLS.get(); - } + @Override + public Codec<? extends IGlobalLootModifier> codec() { + return ForgeHexLootMods.INJECT_SCROLLS.get(); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeAccessorBuiltInRegistries.java b/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeAccessorBuiltInRegistries.java index b086d8714d..845dd9977f 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeAccessorBuiltInRegistries.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeAccessorBuiltInRegistries.java @@ -9,17 +9,18 @@ @Mixin(BuiltInRegistries.class) public interface ForgeAccessorBuiltInRegistries { - @Invoker("registerDefaulted") - static <T> DefaultedRegistry<T> hex$registerDefaulted(ResourceKey<? extends Registry<T>> registryName, - String defaultId, - BuiltInRegistries.RegistryBootstrap<T> bootstrap) { - throw new IllegalStateException(); - } + @Invoker("registerDefaulted") + static <T> DefaultedRegistry<T> hex$registerDefaulted( + ResourceKey<? extends Registry<T>> registryName, + String defaultId, + BuiltInRegistries.RegistryBootstrap<T> bootstrap) { + throw new IllegalStateException(); + } - @Invoker("registerSimple") - static <T> Registry<T> hex$registerSimple(ResourceKey<? extends Registry<T>> registryName, - BuiltInRegistries.RegistryBootstrap<T> bootstrap) { - throw new IllegalStateException(); - } + @Invoker("registerSimple") + static <T> Registry<T> hex$registerSimple( + ResourceKey<? extends Registry<T>> registryName, + BuiltInRegistries.RegistryBootstrap<T> bootstrap) { + throw new IllegalStateException(); + } } - diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinBlockColors.java b/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinBlockColors.java index 04983c5019..481c10f3d6 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinBlockColors.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinBlockColors.java @@ -9,8 +9,8 @@ @Mixin(BlockColors.class) public class ForgeMixinBlockColors { - @Inject(method = "createDefault", at = @At("RETURN")) - private static void hex$onCreateDefault(CallbackInfoReturnable<BlockColors> info) { - ForgeHexClientInitializer.GLOBAL_BLOCK_COLORS = info.getReturnValue(); - } + @Inject(method = "createDefault", at = @At("RETURN")) + private static void hex$onCreateDefault(CallbackInfoReturnable<BlockColors> info) { + ForgeHexClientInitializer.GLOBAL_BLOCK_COLORS = info.getReturnValue(); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinCursedRecipeSerializerBase.java b/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinCursedRecipeSerializerBase.java index b66f878f1b..f3514886ec 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinCursedRecipeSerializerBase.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinCursedRecipeSerializerBase.java @@ -1,21 +1,18 @@ package at.petrak.hexcasting.forge.mixin; import at.petrak.hexcasting.common.recipe.RecipeSerializerBase; +import javax.annotation.Nullable; import net.minecraft.resources.ResourceLocation; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import javax.annotation.Nullable; - // https://github.com/VazkiiMods/Botania/blob/1.18.x/Forge/src/main/java/vazkii/botania/forge/mixin/ForgeMixinRecipeSerializerBase.java @Mixin(value = RecipeSerializerBase.class, remap = false) public class ForgeMixinCursedRecipeSerializerBase { - @Shadow - @Nullable - private ResourceLocation registryName; + @Shadow @Nullable private ResourceLocation registryName; - public Object setRegistryName(ResourceLocation name) { - registryName = name; - return this; - } + public Object setRegistryName(ResourceLocation name) { + registryName = name; + return this; + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinItemColors.java b/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinItemColors.java index 2ef14ac4de..e9abeb1c94 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinItemColors.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinItemColors.java @@ -10,8 +10,9 @@ @Mixin(ItemColors.class) public class ForgeMixinItemColors { - @Inject(method = "createDefault", at = @At("RETURN")) - private static void hex$onCreateDefault(BlockColors blockColors, CallbackInfoReturnable<ItemColors> info) { - ForgeHexClientInitializer.GLOBAL_ITEM_COLORS = info.getReturnValue(); - } + @Inject(method = "createDefault", at = @At("RETURN")) + private static void hex$onCreateDefault( + BlockColors blockColors, CallbackInfoReturnable<ItemColors> info) { + ForgeHexClientInitializer.GLOBAL_ITEM_COLORS = info.getReturnValue(); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinTagsProvider.java b/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinTagsProvider.java index e815506337..544e2cf3c6 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinTagsProvider.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinTagsProvider.java @@ -12,36 +12,43 @@ @Mixin(TagsProvider.class) public abstract class ForgeMixinTagsProvider implements TagsProviderEFHSetter { - @Final - @Shadow(remap = false) - protected ExistingFileHelper existingFileHelper; + @Final + @Shadow(remap = false) + protected ExistingFileHelper existingFileHelper; - private ExistingFileHelper actualFileHelper = null; + private ExistingFileHelper actualFileHelper = null; - @Override - public void setEFH(ExistingFileHelper efh) { - actualFileHelper = efh; - } + @Override + public void setEFH(ExistingFileHelper efh) { + actualFileHelper = efh; + } - @Redirect(method = "missing(Lnet/minecraft/tags/TagEntry;)Z", at = @At( - value = "FIELD", - target = "Lnet/minecraft/data/tags/TagsProvider;existingFileHelper:Lnet/minecraftforge/common/data/ExistingFileHelper;", - opcode = Opcodes.GETFIELD), - remap = false) - private ExistingFileHelper hex$missingRedirect(TagsProvider instance) { - if (actualFileHelper == null) - return existingFileHelper; - return actualFileHelper; - } + @Redirect( + method = "missing(Lnet/minecraft/tags/TagEntry;)Z", + at = + @At( + value = "FIELD", + target = + "Lnet/minecraft/data/tags/TagsProvider;existingFileHelper:Lnet/minecraftforge/common/data/ExistingFileHelper;", + opcode = Opcodes.GETFIELD), + remap = false) + private ExistingFileHelper hex$missingRedirect(TagsProvider instance) { + if (actualFileHelper == null) return existingFileHelper; + return actualFileHelper; + } - @Redirect(method = "lambda$getOrCreateRawBuilder$9(Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/tags/TagBuilder;", at = @At( - value = "FIELD", - target = "Lnet/minecraft/data/tags/TagsProvider;existingFileHelper:Lnet/minecraftforge/common/data/ExistingFileHelper;", - opcode = Opcodes.GETFIELD), - remap = false) - private ExistingFileHelper hex$getOrCreateRawBuilderRedirect(TagsProvider instance) { - if (actualFileHelper == null) - return existingFileHelper; - return actualFileHelper; - } + @Redirect( + method = + "lambda$getOrCreateRawBuilder$9(Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/tags/TagBuilder;", + at = + @At( + value = "FIELD", + target = + "Lnet/minecraft/data/tags/TagsProvider;existingFileHelper:Lnet/minecraftforge/common/data/ExistingFileHelper;", + opcode = Opcodes.GETFIELD), + remap = false) + private ExistingFileHelper hex$getOrCreateRawBuilderRedirect(TagsProvider instance) { + if (actualFileHelper == null) return existingFileHelper; + return actualFileHelper; + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/network/ForgePacketHandler.java b/Forge/src/main/java/at/petrak/hexcasting/forge/network/ForgePacketHandler.java index 78485aa6f9..857fcdf7d5 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/network/ForgePacketHandler.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/network/ForgePacketHandler.java @@ -1,6 +1,11 @@ package at.petrak.hexcasting.forge.network; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.common.msgs.*; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Supplier; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.network.NetworkEvent; @@ -8,75 +13,130 @@ import net.minecraftforge.network.simple.SimpleChannel; import org.apache.logging.log4j.util.TriConsumer; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Supplier; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class ForgePacketHandler { - private static final String PROTOCOL_VERSION = "1"; - private static final SimpleChannel NETWORK = NetworkRegistry.newSimpleChannel( - modLoc("main"), - () -> PROTOCOL_VERSION, - PROTOCOL_VERSION::equals, - PROTOCOL_VERSION::equals - ); + private static final String PROTOCOL_VERSION = "1"; + private static final SimpleChannel NETWORK = + NetworkRegistry.newSimpleChannel( + modLoc("main"), + () -> PROTOCOL_VERSION, + PROTOCOL_VERSION::equals, + PROTOCOL_VERSION::equals); - public static SimpleChannel getNetwork() { - return NETWORK; - } + public static SimpleChannel getNetwork() { + return NETWORK; + } - public static void init() { - int messageIdx = 0; + public static void init() { + int messageIdx = 0; - // Client -> server - NETWORK.registerMessage(messageIdx++, MsgNewSpellPatternC2S.class, MsgNewSpellPatternC2S::serialize, - MsgNewSpellPatternC2S::deserialize, makeServerBoundHandler(MsgNewSpellPatternC2S::handle)); - NETWORK.registerMessage(messageIdx++, MsgShiftScrollC2S.class, MsgShiftScrollC2S::serialize, - MsgShiftScrollC2S::deserialize, makeServerBoundHandler(MsgShiftScrollC2S::handle)); + // Client -> server + NETWORK.registerMessage( + messageIdx++, + MsgNewSpellPatternC2S.class, + MsgNewSpellPatternC2S::serialize, + MsgNewSpellPatternC2S::deserialize, + makeServerBoundHandler(MsgNewSpellPatternC2S::handle)); + NETWORK.registerMessage( + messageIdx++, + MsgShiftScrollC2S.class, + MsgShiftScrollC2S::serialize, + MsgShiftScrollC2S::deserialize, + makeServerBoundHandler(MsgShiftScrollC2S::handle)); - // Server -> client - NETWORK.registerMessage(messageIdx++, MsgNewSpellPatternS2C.class, MsgNewSpellPatternS2C::serialize, - MsgNewSpellPatternS2C::deserialize, makeClientBoundHandler(MsgNewSpellPatternS2C::handle)); - NETWORK.registerMessage(messageIdx++, MsgBlinkS2C.class, MsgBlinkS2C::serialize, - MsgBlinkS2C::deserialize, makeClientBoundHandler(MsgBlinkS2C::handle)); - NETWORK.registerMessage(messageIdx++, MsgSentinelStatusUpdateAck.class, MsgSentinelStatusUpdateAck::serialize, - MsgSentinelStatusUpdateAck::deserialize, makeClientBoundHandler(MsgSentinelStatusUpdateAck::handle)); - NETWORK.registerMessage(messageIdx++, MsgPigmentUpdateAck.class, MsgPigmentUpdateAck::serialize, - MsgPigmentUpdateAck::deserialize, makeClientBoundHandler(MsgPigmentUpdateAck::handle)); - NETWORK.registerMessage(messageIdx++, MsgAltioraUpdateAck.class, MsgAltioraUpdateAck::serialize, - MsgAltioraUpdateAck::deserialize, makeClientBoundHandler(MsgAltioraUpdateAck::handle)); - NETWORK.registerMessage(messageIdx++, MsgCastParticleS2C.class, MsgCastParticleS2C::serialize, - MsgCastParticleS2C::deserialize, makeClientBoundHandler(MsgCastParticleS2C::handle)); - NETWORK.registerMessage(messageIdx++, MsgOpenSpellGuiS2C.class, MsgOpenSpellGuiS2C::serialize, - MsgOpenSpellGuiS2C::deserialize, makeClientBoundHandler(MsgOpenSpellGuiS2C::handle)); - NETWORK.registerMessage(messageIdx++, MsgBeepS2C.class, MsgBeepS2C::serialize, - MsgBeepS2C::deserialize, makeClientBoundHandler(MsgBeepS2C::handle)); - NETWORK.registerMessage(messageIdx++, MsgBrainsweepAck.class, MsgBrainsweepAck::serialize, - MsgBrainsweepAck::deserialize, makeClientBoundHandler(MsgBrainsweepAck::handle)); - NETWORK.registerMessage(messageIdx++, MsgNewWallScrollS2C.class, MsgNewWallScrollS2C::serialize, - MsgNewWallScrollS2C::deserialize, makeClientBoundHandler(MsgNewWallScrollS2C::handle)); - NETWORK.registerMessage(messageIdx++, MsgRecalcWallScrollDisplayS2C.class, MsgRecalcWallScrollDisplayS2C::serialize, - MsgRecalcWallScrollDisplayS2C::deserialize, makeClientBoundHandler(MsgRecalcWallScrollDisplayS2C::handle)); - NETWORK.registerMessage(messageIdx++, MsgNewSpiralPatternsS2C.class, MsgNewSpiralPatternsS2C::serialize, - MsgNewSpiralPatternsS2C::deserialize, makeClientBoundHandler(MsgNewSpiralPatternsS2C::handle)); - NETWORK.registerMessage(messageIdx++, MsgClearSpiralPatternsS2C.class, MsgClearSpiralPatternsS2C::serialize, - MsgClearSpiralPatternsS2C::deserialize, makeClientBoundHandler(MsgClearSpiralPatternsS2C::handle)); - } + // Server -> client + NETWORK.registerMessage( + messageIdx++, + MsgNewSpellPatternS2C.class, + MsgNewSpellPatternS2C::serialize, + MsgNewSpellPatternS2C::deserialize, + makeClientBoundHandler(MsgNewSpellPatternS2C::handle)); + NETWORK.registerMessage( + messageIdx++, + MsgBlinkS2C.class, + MsgBlinkS2C::serialize, + MsgBlinkS2C::deserialize, + makeClientBoundHandler(MsgBlinkS2C::handle)); + NETWORK.registerMessage( + messageIdx++, + MsgSentinelStatusUpdateAck.class, + MsgSentinelStatusUpdateAck::serialize, + MsgSentinelStatusUpdateAck::deserialize, + makeClientBoundHandler(MsgSentinelStatusUpdateAck::handle)); + NETWORK.registerMessage( + messageIdx++, + MsgPigmentUpdateAck.class, + MsgPigmentUpdateAck::serialize, + MsgPigmentUpdateAck::deserialize, + makeClientBoundHandler(MsgPigmentUpdateAck::handle)); + NETWORK.registerMessage( + messageIdx++, + MsgAltioraUpdateAck.class, + MsgAltioraUpdateAck::serialize, + MsgAltioraUpdateAck::deserialize, + makeClientBoundHandler(MsgAltioraUpdateAck::handle)); + NETWORK.registerMessage( + messageIdx++, + MsgCastParticleS2C.class, + MsgCastParticleS2C::serialize, + MsgCastParticleS2C::deserialize, + makeClientBoundHandler(MsgCastParticleS2C::handle)); + NETWORK.registerMessage( + messageIdx++, + MsgOpenSpellGuiS2C.class, + MsgOpenSpellGuiS2C::serialize, + MsgOpenSpellGuiS2C::deserialize, + makeClientBoundHandler(MsgOpenSpellGuiS2C::handle)); + NETWORK.registerMessage( + messageIdx++, + MsgBeepS2C.class, + MsgBeepS2C::serialize, + MsgBeepS2C::deserialize, + makeClientBoundHandler(MsgBeepS2C::handle)); + NETWORK.registerMessage( + messageIdx++, + MsgBrainsweepAck.class, + MsgBrainsweepAck::serialize, + MsgBrainsweepAck::deserialize, + makeClientBoundHandler(MsgBrainsweepAck::handle)); + NETWORK.registerMessage( + messageIdx++, + MsgNewWallScrollS2C.class, + MsgNewWallScrollS2C::serialize, + MsgNewWallScrollS2C::deserialize, + makeClientBoundHandler(MsgNewWallScrollS2C::handle)); + NETWORK.registerMessage( + messageIdx++, + MsgRecalcWallScrollDisplayS2C.class, + MsgRecalcWallScrollDisplayS2C::serialize, + MsgRecalcWallScrollDisplayS2C::deserialize, + makeClientBoundHandler(MsgRecalcWallScrollDisplayS2C::handle)); + NETWORK.registerMessage( + messageIdx++, + MsgNewSpiralPatternsS2C.class, + MsgNewSpiralPatternsS2C::serialize, + MsgNewSpiralPatternsS2C::deserialize, + makeClientBoundHandler(MsgNewSpiralPatternsS2C::handle)); + NETWORK.registerMessage( + messageIdx++, + MsgClearSpiralPatternsS2C.class, + MsgClearSpiralPatternsS2C::serialize, + MsgClearSpiralPatternsS2C::deserialize, + makeClientBoundHandler(MsgClearSpiralPatternsS2C::handle)); + } - private static <T> BiConsumer<T, Supplier<NetworkEvent.Context>> makeServerBoundHandler( - TriConsumer<T, MinecraftServer, ServerPlayer> handler) { - return (m, ctx) -> { - handler.accept(m, ctx.get().getSender().getServer(), ctx.get().getSender()); - ctx.get().setPacketHandled(true); - }; - } + private static <T> BiConsumer<T, Supplier<NetworkEvent.Context>> makeServerBoundHandler( + TriConsumer<T, MinecraftServer, ServerPlayer> handler) { + return (m, ctx) -> { + handler.accept(m, ctx.get().getSender().getServer(), ctx.get().getSender()); + ctx.get().setPacketHandled(true); + }; + } - private static <T> BiConsumer<T, Supplier<NetworkEvent.Context>> makeClientBoundHandler(Consumer<T> consumer) { - return (m, ctx) -> { - consumer.accept(m); - ctx.get().setPacketHandled(true); - }; - } + private static <T> BiConsumer<T, Supplier<NetworkEvent.Context>> makeClientBoundHandler( + Consumer<T> consumer) { + return (m, ctx) -> { + consumer.accept(m); + ctx.get().setPacketHandled(true); + }; + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgAltioraUpdateAck.java b/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgAltioraUpdateAck.java index 0e932b55ea..5f0a51ae79 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgAltioraUpdateAck.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgAltioraUpdateAck.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.forge.network; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.player.AltioraAbility; import at.petrak.hexcasting.common.msgs.IMessage; import at.petrak.hexcasting.xplat.IXplatAbstractions; @@ -9,44 +11,44 @@ import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public record MsgAltioraUpdateAck(@Nullable AltioraAbility altiora) implements IMessage { - public static final ResourceLocation ID = modLoc("altiora"); - - @Override - public ResourceLocation getFabricId() { - return ID; - } - - public static MsgAltioraUpdateAck deserialize(ByteBuf buffer) { - var buf = new FriendlyByteBuf(buffer); - - var extant = buf.readBoolean(); - if (!extant) { - return new MsgAltioraUpdateAck(null); - } - var grace = buf.readVarInt(); - return new MsgAltioraUpdateAck(new AltioraAbility(grace)); - } - - @Override - public void serialize(FriendlyByteBuf buf) { - buf.writeBoolean(this.altiora != null); - if (this.altiora != null) { - buf.writeVarInt(this.altiora.gracePeriod()); - } - } - - public static void handle(MsgAltioraUpdateAck self) { - Minecraft.getInstance().execute(new Runnable() { - @Override - public void run() { - var player = Minecraft.getInstance().player; - if (player != null) { - IXplatAbstractions.INSTANCE.setAltiora(player, self.altiora); - } - } - }); - } + public static final ResourceLocation ID = modLoc("altiora"); + + @Override + public ResourceLocation getFabricId() { + return ID; + } + + public static MsgAltioraUpdateAck deserialize(ByteBuf buffer) { + var buf = new FriendlyByteBuf(buffer); + + var extant = buf.readBoolean(); + if (!extant) { + return new MsgAltioraUpdateAck(null); + } + var grace = buf.readVarInt(); + return new MsgAltioraUpdateAck(new AltioraAbility(grace)); + } + + @Override + public void serialize(FriendlyByteBuf buf) { + buf.writeBoolean(this.altiora != null); + if (this.altiora != null) { + buf.writeVarInt(this.altiora.gracePeriod()); + } + } + + public static void handle(MsgAltioraUpdateAck self) { + Minecraft.getInstance() + .execute( + new Runnable() { + @Override + public void run() { + var player = Minecraft.getInstance().player; + if (player != null) { + IXplatAbstractions.INSTANCE.setAltiora(player, self.altiora); + } + } + }); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgBrainsweepAck.java b/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgBrainsweepAck.java index c9d24606fc..7e548c0d19 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgBrainsweepAck.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgBrainsweepAck.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.forge.network; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.common.msgs.IMessage; import at.petrak.hexcasting.xplat.IXplatAbstractions; import io.netty.buffer.ByteBuf; @@ -9,47 +11,45 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Mob; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - -/** - * Sent server->client to synchronize the status of a brainswept mob. - */ +/** Sent server->client to synchronize the status of a brainswept mob. */ public record MsgBrainsweepAck(int target) implements IMessage { - public static final ResourceLocation ID = modLoc("sweep"); - - @Override - public ResourceLocation getFabricId() { - return ID; - } - - public static MsgBrainsweepAck deserialize(ByteBuf buffer) { - var buf = new FriendlyByteBuf(buffer); - - var target = buf.readInt(); - return new MsgBrainsweepAck(target); - } - - @Override - public void serialize(FriendlyByteBuf buf) { - buf.writeInt(target); - } - - public static MsgBrainsweepAck of(Entity target) { - return new MsgBrainsweepAck(target.getId()); - } - - public static void handle(MsgBrainsweepAck msg) { - Minecraft.getInstance().execute(new Runnable() { - @Override - public void run() { - var level = Minecraft.getInstance().level; - if (level != null) { - Entity entity = level.getEntity(msg.target()); - if (entity instanceof Mob living) { - IXplatAbstractions.INSTANCE.setBrainsweepAddlData(living); - } - } - } - }); - } + public static final ResourceLocation ID = modLoc("sweep"); + + @Override + public ResourceLocation getFabricId() { + return ID; + } + + public static MsgBrainsweepAck deserialize(ByteBuf buffer) { + var buf = new FriendlyByteBuf(buffer); + + var target = buf.readInt(); + return new MsgBrainsweepAck(target); + } + + @Override + public void serialize(FriendlyByteBuf buf) { + buf.writeInt(target); + } + + public static MsgBrainsweepAck of(Entity target) { + return new MsgBrainsweepAck(target.getId()); + } + + public static void handle(MsgBrainsweepAck msg) { + Minecraft.getInstance() + .execute( + new Runnable() { + @Override + public void run() { + var level = Minecraft.getInstance().level; + if (level != null) { + Entity entity = level.getEntity(msg.target()); + if (entity instanceof Mob living) { + IXplatAbstractions.INSTANCE.setBrainsweepAddlData(living); + } + } + } + }); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgPigmentUpdateAck.java b/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgPigmentUpdateAck.java index c38266b1ae..2251ddb5d7 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgPigmentUpdateAck.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgPigmentUpdateAck.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.forge.network; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.pigment.FrozenPigment; import at.petrak.hexcasting.common.msgs.IMessage; import at.petrak.hexcasting.xplat.IXplatAbstractions; @@ -8,41 +10,39 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; -import static at.petrak.hexcasting.api.HexAPI.modLoc; - -/** - * Sent server->client to synchronize the status of the sentinel. - */ +/** Sent server->client to synchronize the status of the sentinel. */ public record MsgPigmentUpdateAck(FrozenPigment update) implements IMessage { - public static final ResourceLocation ID = modLoc("color"); - - @Override - public ResourceLocation getFabricId() { - return ID; - } - - public static MsgPigmentUpdateAck deserialize(ByteBuf buffer) { - var buf = new FriendlyByteBuf(buffer); - - var tag = buf.readAnySizeNbt(); - var colorizer = FrozenPigment.fromNBT(tag); - return new MsgPigmentUpdateAck(colorizer); - } - - @Override - public void serialize(FriendlyByteBuf buf) { - buf.writeNbt(this.update.serializeToNBT()); - } - - public static void handle(MsgPigmentUpdateAck self) { - Minecraft.getInstance().execute(new Runnable() { - @Override - public void run() { - var player = Minecraft.getInstance().player; - if (player != null) { - IXplatAbstractions.INSTANCE.setPigment(player, self.update()); - } - } - }); - } + public static final ResourceLocation ID = modLoc("color"); + + @Override + public ResourceLocation getFabricId() { + return ID; + } + + public static MsgPigmentUpdateAck deserialize(ByteBuf buffer) { + var buf = new FriendlyByteBuf(buffer); + + var tag = buf.readAnySizeNbt(); + var colorizer = FrozenPigment.fromNBT(tag); + return new MsgPigmentUpdateAck(colorizer); + } + + @Override + public void serialize(FriendlyByteBuf buf) { + buf.writeNbt(this.update.serializeToNBT()); + } + + public static void handle(MsgPigmentUpdateAck self) { + Minecraft.getInstance() + .execute( + new Runnable() { + @Override + public void run() { + var player = Minecraft.getInstance().player; + if (player != null) { + IXplatAbstractions.INSTANCE.setPigment(player, self.update()); + } + } + }); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgSentinelStatusUpdateAck.java b/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgSentinelStatusUpdateAck.java index dc8f712d8e..bd870105e6 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgSentinelStatusUpdateAck.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/network/MsgSentinelStatusUpdateAck.java @@ -1,9 +1,12 @@ package at.petrak.hexcasting.forge.network; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.player.Sentinel; import at.petrak.hexcasting.common.msgs.IMessage; import at.petrak.hexcasting.xplat.IXplatAbstractions; import io.netty.buffer.ByteBuf; +import javax.annotation.Nullable; import net.minecraft.client.Minecraft; import net.minecraft.core.registries.Registries; import net.minecraft.network.FriendlyByteBuf; @@ -11,61 +14,57 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.phys.Vec3; -import javax.annotation.Nullable; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - -/** - * Sent server->client to synchronize the status of the sentinel. - */ +/** Sent server->client to synchronize the status of the sentinel. */ public record MsgSentinelStatusUpdateAck(@Nullable Sentinel update) implements IMessage { - public static final ResourceLocation ID = modLoc("sntnl"); + public static final ResourceLocation ID = modLoc("sntnl"); - @Override - public ResourceLocation getFabricId() { - return ID; - } + @Override + public ResourceLocation getFabricId() { + return ID; + } - public static MsgSentinelStatusUpdateAck deserialize(ByteBuf buffer) { - var buf = new FriendlyByteBuf(buffer); + public static MsgSentinelStatusUpdateAck deserialize(ByteBuf buffer) { + var buf = new FriendlyByteBuf(buffer); - var exists = buf.readBoolean(); - if (!exists) { - return new MsgSentinelStatusUpdateAck(null); - } + var exists = buf.readBoolean(); + if (!exists) { + return new MsgSentinelStatusUpdateAck(null); + } - var greater = buf.readBoolean(); - var origin = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()); - var dimension = ResourceKey.create(Registries.DIMENSION, buf.readResourceLocation()); + var greater = buf.readBoolean(); + var origin = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()); + var dimension = ResourceKey.create(Registries.DIMENSION, buf.readResourceLocation()); - var sentinel = new Sentinel(greater, origin, dimension); - return new MsgSentinelStatusUpdateAck(sentinel); - } + var sentinel = new Sentinel(greater, origin, dimension); + return new MsgSentinelStatusUpdateAck(sentinel); + } - public void serialize(FriendlyByteBuf buf) { - if (update == null) { - buf.writeBoolean(false); - return; - } + public void serialize(FriendlyByteBuf buf) { + if (update == null) { + buf.writeBoolean(false); + return; + } - buf.writeBoolean(true); - buf.writeBoolean(update.extendsRange()); - buf.writeDouble(update.position().x); - buf.writeDouble(update.position().y); - buf.writeDouble(update.position().z); - buf.writeResourceLocation(update.dimension().location()); - } + buf.writeBoolean(true); + buf.writeBoolean(update.extendsRange()); + buf.writeDouble(update.position().x); + buf.writeDouble(update.position().y); + buf.writeDouble(update.position().z); + buf.writeResourceLocation(update.dimension().location()); + } - public static void handle(MsgSentinelStatusUpdateAck self) { - //noinspection Convert2Lambda - Minecraft.getInstance().execute(new Runnable() { - @Override - public void run() { - var player = Minecraft.getInstance().player; - if (player != null) { - IXplatAbstractions.INSTANCE.setSentinel(player, self.update()); - } - } - }); - } + public static void handle(MsgSentinelStatusUpdateAck self) { + //noinspection Convert2Lambda + Minecraft.getInstance() + .execute( + new Runnable() { + @Override + public void run() { + var player = Minecraft.getInstance().player; + if (player != null) { + IXplatAbstractions.INSTANCE.setSentinel(player, self.update()); + } + } + }); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/recipe/ForgeModConditionalIngredient.java b/Forge/src/main/java/at/petrak/hexcasting/forge/recipe/ForgeModConditionalIngredient.java index 0969291d47..4cbe4e184f 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/recipe/ForgeModConditionalIngredient.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/recipe/ForgeModConditionalIngredient.java @@ -1,9 +1,14 @@ package at.petrak.hexcasting.forge.recipe; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; +import java.util.Arrays; +import java.util.Objects; +import javax.annotation.Nullable; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; @@ -12,103 +17,102 @@ import net.minecraftforge.common.crafting.IIngredientSerializer; import org.jetbrains.annotations.NotNull; -import javax.annotation.Nullable; -import java.util.Arrays; -import java.util.Objects; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class ForgeModConditionalIngredient extends AbstractIngredient { - public static final ResourceLocation ID = modLoc("mod_conditional"); - - private final Ingredient main; - private final String modid; - private final Ingredient ifModLoaded; - - private final Ingredient toUse; - - protected ForgeModConditionalIngredient(Ingredient main, String modid, Ingredient ifModLoaded) { - super(IXplatAbstractions.INSTANCE.isModPresent(modid) ? Arrays.stream(ifModLoaded.values) : Arrays.stream(main.values)); - this.main = main; - this.modid = modid; - this.ifModLoaded = ifModLoaded; - - this.toUse = IXplatAbstractions.INSTANCE.isModPresent(modid) ? ifModLoaded : main; - } - - /** - * Creates a new ingredient matching the given stack - */ - public static ForgeModConditionalIngredient of(Ingredient main, String modid, Ingredient ifModLoaded) { - return new ForgeModConditionalIngredient(main, modid, ifModLoaded); - } - - @Override - public boolean test(@Nullable ItemStack input) { - return toUse.test(input); - } - - @Override - public boolean isSimple() { - return toUse.isSimple(); - } - - @Override - public @NotNull JsonElement toJson() { - JsonObject json = new JsonObject(); - json.addProperty("type", Objects.toString(ID)); - json.add("default", main.toJson()); - json.addProperty("modid", modid); - json.add("if_loaded", ifModLoaded.toJson()); - return json; - } - - @Override - public @NotNull IIngredientSerializer<? extends Ingredient> getSerializer() { - return Serializer.INSTANCE; - } - - public static @NotNull Ingredient fromNetwork(FriendlyByteBuf friendlyByteBuf) { - return Ingredient.fromNetwork(friendlyByteBuf); // Just send the actual ingredient - } - - public static Ingredient fromJson(JsonObject object) { - if (object.has("type") && object.getAsJsonPrimitive("type").getAsString().equals(ID.toString())) { - if (object.has("modid") && IXplatAbstractions.INSTANCE.isModPresent(object.getAsJsonPrimitive("modid").getAsString())) { - try { - Ingredient ingredient = Ingredient.fromJson(object.get("if_loaded")); - if (!ingredient.isEmpty()) { - return ingredient; - } - } catch (JsonParseException e) { - // NO-OP - } - } - - return Ingredient.fromJson(object.get("default")); - } - - return Ingredient.of(); - } - - public static class Serializer implements IIngredientSerializer<Ingredient> { - public static final Serializer INSTANCE = new Serializer(); - - @Override - public @NotNull Ingredient parse(@NotNull FriendlyByteBuf buffer) { - return fromNetwork(buffer); - } - - @Override - public @NotNull Ingredient parse(@NotNull JsonObject json) { - return fromJson(json); - } - - @Override - public void write(@NotNull FriendlyByteBuf buffer, @NotNull Ingredient ingredient) { - if (ingredient instanceof ForgeModConditionalIngredient conditionalIngredient) - conditionalIngredient.toUse.toNetwork(buffer); - // It shouldn't be possible to not be a ForgeModConditionalIngredient here - } - } + public static final ResourceLocation ID = modLoc("mod_conditional"); + + private final Ingredient main; + private final String modid; + private final Ingredient ifModLoaded; + + private final Ingredient toUse; + + protected ForgeModConditionalIngredient(Ingredient main, String modid, Ingredient ifModLoaded) { + super( + IXplatAbstractions.INSTANCE.isModPresent(modid) + ? Arrays.stream(ifModLoaded.values) + : Arrays.stream(main.values)); + this.main = main; + this.modid = modid; + this.ifModLoaded = ifModLoaded; + + this.toUse = IXplatAbstractions.INSTANCE.isModPresent(modid) ? ifModLoaded : main; + } + + /** Creates a new ingredient matching the given stack */ + public static ForgeModConditionalIngredient of( + Ingredient main, String modid, Ingredient ifModLoaded) { + return new ForgeModConditionalIngredient(main, modid, ifModLoaded); + } + + @Override + public boolean test(@Nullable ItemStack input) { + return toUse.test(input); + } + + @Override + public boolean isSimple() { + return toUse.isSimple(); + } + + @Override + public @NotNull JsonElement toJson() { + JsonObject json = new JsonObject(); + json.addProperty("type", Objects.toString(ID)); + json.add("default", main.toJson()); + json.addProperty("modid", modid); + json.add("if_loaded", ifModLoaded.toJson()); + return json; + } + + @Override + public @NotNull IIngredientSerializer<? extends Ingredient> getSerializer() { + return Serializer.INSTANCE; + } + + public static @NotNull Ingredient fromNetwork(FriendlyByteBuf friendlyByteBuf) { + return Ingredient.fromNetwork(friendlyByteBuf); // Just send the actual ingredient + } + + public static Ingredient fromJson(JsonObject object) { + if (object.has("type") + && object.getAsJsonPrimitive("type").getAsString().equals(ID.toString())) { + if (object.has("modid") + && IXplatAbstractions.INSTANCE.isModPresent( + object.getAsJsonPrimitive("modid").getAsString())) { + try { + Ingredient ingredient = Ingredient.fromJson(object.get("if_loaded")); + if (!ingredient.isEmpty()) { + return ingredient; + } + } catch (JsonParseException e) { + // NO-OP + } + } + + return Ingredient.fromJson(object.get("default")); + } + + return Ingredient.of(); + } + + public static class Serializer implements IIngredientSerializer<Ingredient> { + public static final Serializer INSTANCE = new Serializer(); + + @Override + public @NotNull Ingredient parse(@NotNull FriendlyByteBuf buffer) { + return fromNetwork(buffer); + } + + @Override + public @NotNull Ingredient parse(@NotNull JsonObject json) { + return fromJson(json); + } + + @Override + public void write(@NotNull FriendlyByteBuf buffer, @NotNull Ingredient ingredient) { + if (ingredient instanceof ForgeModConditionalIngredient conditionalIngredient) + conditionalIngredient.toUse.toNetwork(buffer); + // It shouldn't be possible to not be a ForgeModConditionalIngredient here + } + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/recipe/ForgeUnsealedIngredient.java b/Forge/src/main/java/at/petrak/hexcasting/forge/recipe/ForgeUnsealedIngredient.java index 434104aa9b..c5d5169c54 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/recipe/ForgeUnsealedIngredient.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/recipe/ForgeUnsealedIngredient.java @@ -1,5 +1,7 @@ package at.petrak.hexcasting.forge.recipe; +import static at.petrak.hexcasting.api.HexAPI.modLoc; + import at.petrak.hexcasting.api.addldata.ADIotaHolder; import at.petrak.hexcasting.api.casting.iota.NullIota; import at.petrak.hexcasting.api.item.IotaHolderItem; @@ -7,6 +9,9 @@ import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import java.util.Objects; +import java.util.stream.Stream; +import javax.annotation.Nullable; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; @@ -18,86 +23,80 @@ import net.minecraftforge.registries.ForgeRegistries; import org.jetbrains.annotations.NotNull; -import javax.annotation.Nullable; -import java.util.Objects; -import java.util.stream.Stream; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; - public class ForgeUnsealedIngredient extends AbstractIngredient { - public static final ResourceLocation ID = modLoc("unsealed"); - - private final ItemStack stack; - - private static ItemStack createStack(ItemStack base) { - ItemStack newStack = base.copy(); - NBTHelper.putString(newStack, IotaHolderItem.TAG_OVERRIDE_VISUALLY, "any"); - return newStack; - } - - protected ForgeUnsealedIngredient(ItemStack stack) { - super(Stream.of(new Ingredient.ItemValue(createStack(stack)))); - this.stack = stack; - } - - /** - * Creates a new ingredient matching the given stack - */ - public static ForgeUnsealedIngredient of(ItemStack stack) { - return new ForgeUnsealedIngredient(stack); - } - - @Override - public boolean test(@Nullable ItemStack input) { - if (input == null) { - return false; - } - if (this.stack.getItem() == input.getItem() && this.stack.getDamageValue() == input.getDamageValue()) { - ADIotaHolder holder = IXplatAbstractions.INSTANCE.findDataHolder(this.stack); - if (holder != null) { - return holder.readIotaTag() != null && holder.writeIota(new NullIota(), true); - } - } - - return false; - } - - @Override - public boolean isSimple() { - return false; - } - - @Override - public @NotNull IIngredientSerializer<? extends Ingredient> getSerializer() { - return ForgeUnsealedIngredient.Serializer.INSTANCE; - } - - @Override - public @NotNull JsonElement toJson() { - JsonObject json = new JsonObject(); - // TODO: should this be Partial or Strict - json.addProperty("type", Objects.toString(CraftingHelper.getID(PartialNBTIngredient.Serializer.INSTANCE))); - json.addProperty("item", Objects.toString(ForgeRegistries.ITEMS.getKey(stack.getItem()))); - return json; - } - - - public static class Serializer implements IIngredientSerializer<ForgeUnsealedIngredient> { - public static final ForgeUnsealedIngredient.Serializer INSTANCE = new ForgeUnsealedIngredient.Serializer(); - - @Override - public @NotNull ForgeUnsealedIngredient parse(FriendlyByteBuf buffer) { - return new ForgeUnsealedIngredient(buffer.readItem()); - } - - @Override - public @NotNull ForgeUnsealedIngredient parse(@NotNull JsonObject json) { - return new ForgeUnsealedIngredient(CraftingHelper.getItemStack(json, true)); - } - - @Override - public void write(FriendlyByteBuf buffer, ForgeUnsealedIngredient ingredient) { - buffer.writeItem(ingredient.stack); - } - } + public static final ResourceLocation ID = modLoc("unsealed"); + + private final ItemStack stack; + + private static ItemStack createStack(ItemStack base) { + ItemStack newStack = base.copy(); + NBTHelper.putString(newStack, IotaHolderItem.TAG_OVERRIDE_VISUALLY, "any"); + return newStack; + } + + protected ForgeUnsealedIngredient(ItemStack stack) { + super(Stream.of(new Ingredient.ItemValue(createStack(stack)))); + this.stack = stack; + } + + /** Creates a new ingredient matching the given stack */ + public static ForgeUnsealedIngredient of(ItemStack stack) { + return new ForgeUnsealedIngredient(stack); + } + + @Override + public boolean test(@Nullable ItemStack input) { + if (input == null) { + return false; + } + if (this.stack.getItem() == input.getItem() + && this.stack.getDamageValue() == input.getDamageValue()) { + ADIotaHolder holder = IXplatAbstractions.INSTANCE.findDataHolder(this.stack); + if (holder != null) { + return holder.readIotaTag() != null && holder.writeIota(new NullIota(), true); + } + } + + return false; + } + + @Override + public boolean isSimple() { + return false; + } + + @Override + public @NotNull IIngredientSerializer<? extends Ingredient> getSerializer() { + return ForgeUnsealedIngredient.Serializer.INSTANCE; + } + + @Override + public @NotNull JsonElement toJson() { + JsonObject json = new JsonObject(); + // TODO: should this be Partial or Strict + json.addProperty( + "type", Objects.toString(CraftingHelper.getID(PartialNBTIngredient.Serializer.INSTANCE))); + json.addProperty("item", Objects.toString(ForgeRegistries.ITEMS.getKey(stack.getItem()))); + return json; + } + + public static class Serializer implements IIngredientSerializer<ForgeUnsealedIngredient> { + public static final ForgeUnsealedIngredient.Serializer INSTANCE = + new ForgeUnsealedIngredient.Serializer(); + + @Override + public @NotNull ForgeUnsealedIngredient parse(FriendlyByteBuf buffer) { + return new ForgeUnsealedIngredient(buffer.readItem()); + } + + @Override + public @NotNull ForgeUnsealedIngredient parse(@NotNull JsonObject json) { + return new ForgeUnsealedIngredient(CraftingHelper.getItemStack(json, true)); + } + + @Override + public void write(FriendlyByteBuf buffer, ForgeUnsealedIngredient ingredient) { + buffer.writeItem(ingredient.stack); + } + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeClientXplatImpl.java b/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeClientXplatImpl.java index d33c2654b0..c6cea3d430 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeClientXplatImpl.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeClientXplatImpl.java @@ -20,53 +20,52 @@ import net.minecraft.world.phys.AABB; public class ForgeClientXplatImpl implements IClientXplatAbstractions { - @Override - public void sendPacketToServer(IMessage packet) { - ForgePacketHandler.getNetwork().sendToServer(packet); - } + @Override + public void sendPacketToServer(IMessage packet) { + ForgePacketHandler.getNetwork().sendToServer(packet); + } - @Override - public void setRenderLayer(Block block, RenderType type) { - // For forge, handled in block models -// ItemBlockRenderTypes.setRenderLayer(block, type); - } + @Override + public void setRenderLayer(Block block, RenderType type) { + // For forge, handled in block models + // ItemBlockRenderTypes.setRenderLayer(block, type); + } - @Override - public void initPlatformSpecific() { - // NO-OP - } + @Override + public void initPlatformSpecific() { + // NO-OP + } - @Override - public <T extends Entity> void registerEntityRenderer(EntityType<? extends T> type, - EntityRendererProvider<T> renderer) { - EntityRenderers.register(type, renderer); - } + @Override + public <T extends Entity> void registerEntityRenderer( + EntityType<? extends T> type, EntityRendererProvider<T> renderer) { + EntityRenderers.register(type, renderer); + } - @Override - public void registerItemProperty(Item item, ResourceLocation id, ItemPropertyFunction func) { - ItemProperties.register(item, id, func); - } + @Override + public void registerItemProperty(Item item, ResourceLocation id, ItemPropertyFunction func) { + ItemProperties.register(item, id, func); + } - @Override - public ClientCastingStack getClientCastingStack(Player player) { - var maybeCap = player.getCapability(HexCapabilities.CLIENT_CASTING_STACK).resolve(); - if (maybeCap.isEmpty()) - return new ClientCastingStack(); // lie - return maybeCap.get().get(); - } + @Override + public ClientCastingStack getClientCastingStack(Player player) { + var maybeCap = player.getCapability(HexCapabilities.CLIENT_CASTING_STACK).resolve(); + if (maybeCap.isEmpty()) return new ClientCastingStack(); // lie + return maybeCap.get().get(); + } - @Override - public void setFilterSave(AbstractTexture texture, boolean filter, boolean mipmap) { - texture.setBlurMipmap(filter, mipmap); - } + @Override + public void setFilterSave(AbstractTexture texture, boolean filter, boolean mipmap) { + texture.setBlurMipmap(filter, mipmap); + } - @Override - public void restoreLastFilter(AbstractTexture texture) { - texture.restoreLastBlurMipmap(); - } + @Override + public void restoreLastFilter(AbstractTexture texture) { + texture.restoreLastBlurMipmap(); + } - @Override - public boolean fabricAdditionalQuenchFrustumCheck(AABB aabb) { - return true; // forge fixes this with a patch so we just say "yep" - } + @Override + public boolean fabricAdditionalQuenchFrustumCheck(AABB aabb) { + return true; // forge fixes this with a patch so we just say "yep" + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeXplatImpl.java b/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeXplatImpl.java index 9d9188599d..df1971398a 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeXplatImpl.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/xplat/ForgeXplatImpl.java @@ -1,5 +1,8 @@ package at.petrak.hexcasting.forge.xplat; +import static at.petrak.hexcasting.api.HexAPI.modLoc; +import static net.minecraftforge.fluids.capability.IFluidHandler.FluidAction.EXECUTE; + import at.petrak.hexcasting.api.addldata.ADHexHolder; import at.petrak.hexcasting.api.addldata.ADIotaHolder; import at.petrak.hexcasting.api.addldata.ADMediaHolder; @@ -39,6 +42,12 @@ import at.petrak.hexcasting.xplat.IXplatTags; import at.petrak.hexcasting.xplat.Platform; import com.google.common.base.Suppliers; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.function.BiFunction; +import java.util.function.Supplier; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Registry; @@ -90,501 +99,510 @@ import top.theillusivec4.caelus.api.CaelusApi; import virtuoel.pehkui.api.ScaleTypes; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.UUID; -import java.util.function.BiFunction; -import java.util.function.Supplier; - -import static at.petrak.hexcasting.api.HexAPI.modLoc; -import static net.minecraftforge.fluids.capability.IFluidHandler.FluidAction.EXECUTE; - public class ForgeXplatImpl implements IXplatAbstractions { - @Override - public Platform platform() { - return Platform.FORGE; - } - - @Override - public boolean isPhysicalClient() { - return FMLLoader.getDist() == Dist.CLIENT; - } - - @Override - public boolean isModPresent(String id) { - return ModList.get().isLoaded(id); - } - - @Override - public void initPlatformSpecific() { - if (this.isModPresent(HexInterop.Forge.CURIOS_API_ID)) { - CuriosApiInterop.init(); - } - } - -// @Override -// public double getReachDistance(Player player) { -// return player.getAttributeValue(ForgeMod.REACH_DISTANCE.get()); -// } - - @Override - public void setBrainsweepAddlData(Mob mob) { - mob.getPersistentData().putBoolean(TAG_BRAINSWEPT, true); - - if (mob.level() instanceof ServerLevel) { - ForgePacketHandler.getNetwork() - .send(PacketDistributor.TRACKING_ENTITY.with(() -> mob), MsgBrainsweepAck.of(mob)); - } - } - - @Override - public void setFlight(ServerPlayer player, FlightAbility flight) { - CompoundTag tag = player.getPersistentData(); - tag.putBoolean(TAG_FLIGHT_ALLOWED, flight != null); - if (flight != null) { - tag.putInt(TAG_FLIGHT_TIME, flight.timeLeft()); - tag.put(TAG_FLIGHT_ORIGIN, HexUtils.serializeToNBT(flight.origin())); - tag.putString(TAG_FLIGHT_DIMENSION, flight.dimension().location().toString()); - tag.putDouble(TAG_FLIGHT_RADIUS, flight.radius()); - } else { - tag.remove(TAG_FLIGHT_TIME); - tag.remove(TAG_FLIGHT_ORIGIN); - tag.remove(TAG_FLIGHT_DIMENSION); - tag.remove(TAG_FLIGHT_RADIUS); - } - } - - @Override - public void setAltiora(Player player, @Nullable AltioraAbility altiora) { - CompoundTag tag = player.getPersistentData(); - tag.putBoolean(TAG_ALTIORA_ALLOWED, altiora != null); - if (altiora != null) { - tag.putInt(TAG_ALTIORA_GRACE, altiora.gracePeriod()); - } else { - tag.remove(TAG_ALTIORA_ALLOWED); - } - - // The elytra ability is done with an event on fabric - var elytraing = CaelusApi.getInstance().getFlightAttribute(); - var inst = player.getAttributes().getInstance(elytraing); - if (altiora != null) { - if (inst.getModifier(ALTIORA_ATTRIBUTE_ID) == null) { - inst.addTransientModifier(new AttributeModifier(ALTIORA_ATTRIBUTE_ID, "Altiora", 1.0, - AttributeModifier.Operation.ADDITION)); - } - } else { - inst.removeModifier(ALTIORA_ATTRIBUTE_ID); - } - - if (player instanceof ServerPlayer serverPlayer) { - CapSyncers.syncAltiora(serverPlayer); - } - } - - @Override - public @Nullable FrozenPigment setPigment(Player player, @Nullable FrozenPigment pigment) { - var old = getPigment(player); - - CompoundTag tag = player.getPersistentData(); - if (pigment != null) - tag.put(TAG_PIGMENT, pigment.serializeToNBT()); - else - tag.remove(TAG_PIGMENT); - - if (player instanceof ServerPlayer serverPlayer) { - CapSyncers.syncPigment(serverPlayer); - } - - return old; - } - - @Override - public void setSentinel(Player player, @Nullable Sentinel sentinel) { - CompoundTag tag = player.getPersistentData(); - tag.putBoolean(TAG_SENTINEL_EXISTS, sentinel != null); - if (sentinel != null) { - tag.putBoolean(TAG_SENTINEL_GREATER, sentinel.extendsRange()); - tag.put(TAG_SENTINEL_POSITION, HexUtils.serializeToNBT(sentinel.position())); - tag.putString(TAG_SENTINEL_DIMENSION, sentinel.dimension().location().toString()); - } else { - tag.remove(TAG_SENTINEL_GREATER); - tag.remove(TAG_SENTINEL_POSITION); - tag.remove(TAG_SENTINEL_DIMENSION); - } - - if (player instanceof ServerPlayer serverPlayer) { - CapSyncers.syncSentinel(serverPlayer); - } - } - - @Override - public void setStaffcastImage(ServerPlayer player, @Nullable CastingImage image) { - player.getPersistentData().put(TAG_HARNESS, image == null ? new CompoundTag() : image.serializeToNbt()); - } - - @Override - public void setPatterns(ServerPlayer player, List<ResolvedPattern> patterns) { - var listTag = new ListTag(); - for (ResolvedPattern pattern : patterns) { - listTag.add(pattern.serializeToNBT()); - } - player.getPersistentData().put(TAG_PATTERNS, listTag); - } - - @Override - public boolean isBrainswept(Mob e) { - return e.getPersistentData().getBoolean(TAG_BRAINSWEPT); - } - - @Override - public FlightAbility getFlight(ServerPlayer player) { - CompoundTag tag = player.getPersistentData(); - boolean allowed = tag.getBoolean(TAG_FLIGHT_ALLOWED); - if (allowed) { - var timeLeft = tag.getInt(TAG_FLIGHT_TIME); - var origin = HexUtils.vecFromNBT(tag.getCompound(TAG_FLIGHT_ORIGIN)); - var radius = tag.getDouble(TAG_FLIGHT_RADIUS); - var dimension = ResourceKey.create(Registries.DIMENSION, - new ResourceLocation(tag.getString(TAG_FLIGHT_DIMENSION))); - return new FlightAbility(timeLeft, dimension, origin, radius); - } - return null; - } - - @Override - public AltioraAbility getAltiora(Player player) { - CompoundTag tag = player.getPersistentData(); - boolean allowed = tag.getBoolean(TAG_ALTIORA_ALLOWED); - if (allowed) { - var grace = tag.getInt(TAG_ALTIORA_GRACE); - return new AltioraAbility(grace); - } - return null; - } - - @Override - public FrozenPigment getPigment(Player player) { - return FrozenPigment.fromNBT(player.getPersistentData().getCompound(TAG_PIGMENT)); - } - - @Override - public Sentinel getSentinel(Player player) { - CompoundTag tag = player.getPersistentData(); - var exists = tag.getBoolean(TAG_SENTINEL_EXISTS); - if (!exists) { - return null; - } - var extendsRange = tag.getBoolean(TAG_SENTINEL_GREATER); - var position = HexUtils.vecFromNBT(tag.getCompound(TAG_SENTINEL_POSITION)); - var dimension = ResourceKey.create(Registries.DIMENSION, - new ResourceLocation(tag.getString(TAG_SENTINEL_DIMENSION))); - - return new Sentinel(extendsRange, position, dimension); - } - - @Override - public CastingVM getStaffcastVM(ServerPlayer player, InteractionHand hand) { - // This is always from a staff because we don't need to load the harness when casting from item - var ctx = new StaffCastEnv(player, hand); - return new CastingVM(CastingImage.loadFromNbt(player.getPersistentData().getCompound(TAG_HARNESS), - player.serverLevel()), ctx); - } - - @Override - public List<ResolvedPattern> getPatternsSavedInUi(ServerPlayer player) { - ListTag patternsTag = player.getPersistentData().getList(TAG_PATTERNS, Tag.TAG_COMPOUND); - - List<ResolvedPattern> patterns = new ArrayList<>(patternsTag.size()); - - for (int i = 0; i < patternsTag.size(); i++) { - patterns.add(ResolvedPattern.fromNBT(patternsTag.getCompound(i))); - } - return patterns; - } - - @Override - public void clearCastingData(ServerPlayer player) { - player.getPersistentData().remove(TAG_HARNESS); - player.getPersistentData().remove(TAG_PATTERNS); - } - - @Override - public @Nullable - ADMediaHolder findMediaHolder(ItemStack stack) { - var maybeCap = stack.getCapability(HexCapabilities.MEDIA).resolve(); - return maybeCap.orElse(null); - } - - @Override - public @Nullable ADMediaHolder findMediaHolder(ServerPlayer player) { - var maybeCap = player.getCapability(HexCapabilities.MEDIA).resolve(); - return maybeCap.orElse(null); - } - - @Override - public @Nullable - ADIotaHolder findDataHolder(ItemStack stack) { - var maybeCap = stack.getCapability(HexCapabilities.IOTA).resolve(); - return maybeCap.orElse(null); - } - - @Override - public @Nullable ADIotaHolder findDataHolder(Entity entity) { - var maybeCap = entity.getCapability(HexCapabilities.IOTA).resolve(); - return maybeCap.orElse(null); - } - - @Override - public @Nullable - ADHexHolder findHexHolder(ItemStack stack) { - var maybeCap = stack.getCapability(HexCapabilities.STORED_HEX).resolve(); - return maybeCap.orElse(null); - } - - @Override - public @Nullable ADVariantItem findVariantHolder(ItemStack stack) { - var maybeCap = stack.getCapability(HexCapabilities.VARIANT_ITEM).resolve(); - return maybeCap.orElse(null); - } - - @Override - public boolean isPigment(ItemStack stack) { - return stack.getCapability(HexCapabilities.COLOR).isPresent(); - } - - @Override - public ColorProvider getColorProvider(FrozenPigment pigment) { - var maybePigment = pigment.item().getCapability(HexCapabilities.COLOR).resolve(); - if (maybePigment.isPresent()) { - return maybePigment.get().provideColor(pigment.owner()); - } - return ColorProvider.MISSING; - } - - @Override - public void sendPacketToPlayer(ServerPlayer target, IMessage packet) { - ForgePacketHandler.getNetwork().send(PacketDistributor.PLAYER.with(() -> target), packet); - } - - @Override - public void sendPacketNear(Vec3 pos, double radius, ServerLevel dimension, IMessage packet) { - ForgePacketHandler.getNetwork().send(PacketDistributor.NEAR.with(() -> new PacketDistributor.TargetPoint( - pos.x, pos.y, pos.z, radius * radius, dimension.dimension() - )), packet); - } - - @Override - public void sendPacketTracking(Entity entity, IMessage packet) { - ForgePacketHandler.getNetwork().send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), packet); - } - - @Override - public Packet<ClientGamePacketListener> toVanillaClientboundPacket(IMessage message) { - //noinspection unchecked - return (Packet<ClientGamePacketListener>) ForgePacketHandler.getNetwork().toVanillaPacket(message, NetworkDirection.PLAY_TO_CLIENT); - } - - @Override - public <T extends BlockEntity> BlockEntityType<T> createBlockEntityType(BiFunction<BlockPos, BlockState, T> func, - Block... blocks) { - return BlockEntityType.Builder.of(func::apply, blocks).build(null); - } - - @Override - public boolean tryPlaceFluid(Level level, InteractionHand hand, BlockPos pos, Fluid fluid) { - Optional<IFluidHandler> handler = FluidUtil.getFluidHandler(level, pos, Direction.UP).resolve(); - return handler.isPresent() && - handler.get().fill(new FluidStack(fluid, FluidType.BUCKET_VOLUME), EXECUTE) > 0; - } - - @Override - public boolean drainAllFluid(Level level, BlockPos pos) { - Optional<IFluidHandler> handler = FluidUtil.getFluidHandler(level, pos, Direction.UP).resolve(); - if (handler.isPresent()) { - boolean any = false; - IFluidHandler pool = handler.get(); - for (int i = 0; i < pool.getTanks(); i++) { - if (!pool.drain(pool.getFluidInTank(i), EXECUTE).isEmpty()) { - any = true; - } - } - return any; - } - return false; - } - - @Override - public Ingredient getUnsealedIngredient(ItemStack stack) { - return ForgeUnsealedIngredient.of(stack); - } - - @Override - public boolean isCorrectTierForDrops(Tier tier, BlockState bs) { - return !bs.requiresCorrectToolForDrops() || TierSortingRegistry.isCorrectTierForDrops(tier, bs); - } - - @Override - public Item.Properties addEquipSlotFabric(EquipmentSlot slot) { - return new Item.Properties(); - } - - private static final IXplatTags TAGS = new IXplatTags() { - @Override - public TagKey<Item> amethystDust() { - return HexTags.Items.create(new ResourceLocation("forge", "dusts/amethyst")); - } - - @Override - public TagKey<Item> gems() { - return HexTags.Items.create(new ResourceLocation("forge", "gems")); - } - }; - - @Override - public IXplatTags tags() { - return TAGS; - } - - @Override - public LootItemCondition.Builder isShearsCondition() { - return CanToolPerformAction.canToolPerformAction(ToolActions.SHEARS_DIG); - } - - @Override - public String getModName(String namespace) { - if (namespace.equals("c")) { - return "Common"; - } - Optional<? extends ModContainer> container = ModList.get().getModContainerById(namespace); - if (container.isPresent()) { - return container.get().getModInfo().getDisplayName(); - } - return namespace; - } - - private static final Supplier<Registry<ActionRegistryEntry>> ACTION_REGISTRY = Suppliers.memoize(() -> - ForgeAccessorBuiltInRegistries.hex$registerSimple( - HexRegistries.ACTION, null) - ); - private static final Supplier<Registry<SpecialHandler.Factory<?>>> SPECIAL_HANDLER_REGISTRY = - Suppliers.memoize(() -> - ForgeAccessorBuiltInRegistries.hex$registerSimple( - HexRegistries.SPECIAL_HANDLER, null) - ); - private static final Supplier<Registry<IotaType<?>>> IOTA_TYPE_REGISTRY = Suppliers.memoize(() -> - ForgeAccessorBuiltInRegistries.hex$registerDefaulted( - HexRegistries.IOTA_TYPE, - modLoc("null").toString(), registry -> HexIotaTypes.NULL) - ); - private static final Supplier<Registry<Arithmetic>> ARITHMETIC_REGISTRY = Suppliers.memoize(() -> - ForgeAccessorBuiltInRegistries.hex$registerSimple( - HexRegistries.ARITHMETIC, null) - ); - private static final Supplier<Registry<ContinuationFrame.Type<?>>> CONTINUATION_TYPE_REGISTRY = Suppliers.memoize(() -> - ForgeAccessorBuiltInRegistries.hex$registerDefaulted( - HexRegistries.CONTINUATION_TYPE, - modLoc("end").toString(), registry -> HexContinuationTypes.END) - ); - private static final Supplier<Registry<EvalSound>> EVAL_SOUND_REGISTRY = Suppliers.memoize(() -> - ForgeAccessorBuiltInRegistries.hex$registerDefaulted( - HexRegistries.EVAL_SOUND, - modLoc("nothing").toString(), registry -> HexEvalSounds.NOTHING) - ); - - @Override - public Registry<ActionRegistryEntry> getActionRegistry() { - return ACTION_REGISTRY.get(); - } - - @Override - public Registry<SpecialHandler.Factory<?>> getSpecialHandlerRegistry() { - return SPECIAL_HANDLER_REGISTRY.get(); - } - - @Override - public Registry<IotaType<?>> getIotaTypeRegistry() { - return IOTA_TYPE_REGISTRY.get(); - } - - @Override - public Registry<Arithmetic> getArithmeticRegistry() { - return ARITHMETIC_REGISTRY.get(); - } - - @Override - public Registry<ContinuationFrame.Type<?>> getContinuationTypeRegistry() { - return CONTINUATION_TYPE_REGISTRY.get(); - } - - @Override - public Registry<EvalSound> getEvalSoundRegistry() { - return EVAL_SOUND_REGISTRY.get(); - } - - @Override - public boolean isBreakingAllowed(ServerLevel world, BlockPos pos, BlockState state, @Nullable Player player) { - if (player == null) - player = FakePlayerFactory.get(world, HEXCASTING); - return !MinecraftForge.EVENT_BUS.post(new BlockEvent.BreakEvent(world, pos, state, player)); - } - - @Override - public boolean isPlacingAllowed(ServerLevel world, BlockPos pos, ItemStack blockStack, @Nullable Player player) { - if (player == null) - player = FakePlayerFactory.get(world, HEXCASTING); - ItemStack cached = player.getMainHandItem(); - player.setItemInHand(InteractionHand.MAIN_HAND, blockStack.copy()); - var evt = ForgeHooks.onRightClickBlock(player, InteractionHand.MAIN_HAND, pos, - new BlockHitResult(Vec3.atCenterOf(pos), Direction.DOWN, pos, true)); - player.setItemInHand(InteractionHand.MAIN_HAND, cached); - return !evt.isCanceled(); - } - - // it's literally the EXACT SAME on fabric aaa - private static PehkuiInterop.ApiAbstraction PEHKUI_API = null; - - @Override - public PehkuiInterop.ApiAbstraction getPehkuiApi() { - if (!this.isModPresent(HexInterop.PEHKUI_ID)) { - throw new IllegalArgumentException("cannot get the pehkui api without pehkui"); - } - - if (PEHKUI_API == null) { - PEHKUI_API = new PehkuiInterop.ApiAbstraction() { - @Override - public float getScale(Entity e) { - return ScaleTypes.BASE.getScaleData(e).getScale(); - } - - @Override - public void setScale(Entity e, float scale) { - ScaleTypes.BASE.getScaleData(e).setScale(scale); - } - }; - } - return PEHKUI_API; - } - - public static final String TAG_BRAINSWEPT = "hexcasting:brainswept"; - public static final String TAG_SENTINEL_EXISTS = "hexcasting:sentinel_exists"; - public static final String TAG_SENTINEL_GREATER = "hexcasting:sentinel_extends_range"; - public static final String TAG_SENTINEL_POSITION = "hexcasting:sentinel_position"; - public static final String TAG_SENTINEL_DIMENSION = "hexcasting:sentinel_dimension"; - - public static final String TAG_PIGMENT = "hexcasting:pigment"; - - public static final String TAG_FLIGHT_ALLOWED = "hexcasting:flight_allowed"; - public static final String TAG_FLIGHT_TIME = "hexcasting:flight_time"; - public static final String TAG_FLIGHT_ORIGIN = "hexcasting:flight_origin"; - public static final String TAG_FLIGHT_DIMENSION = "hexcasting:flight_dimension"; - public static final String TAG_FLIGHT_RADIUS = "hexcasting:flight_radius"; - - public static final String TAG_ALTIORA_ALLOWED = "hexcasting:altiora_allowed"; - public static final String TAG_ALTIORA_GRACE = "hexcasting:altiora_grace_period"; - - public static final UUID ALTIORA_ATTRIBUTE_ID = UUID.fromString("91897c79-3ebb-468c-a265-40418ed01c41"); - - public static final String TAG_HARNESS = "hexcasting:spell_harness"; - public static final String TAG_PATTERNS = "hexcasting:spell_patterns"; + @Override + public Platform platform() { + return Platform.FORGE; + } + + @Override + public boolean isPhysicalClient() { + return FMLLoader.getDist() == Dist.CLIENT; + } + + @Override + public boolean isModPresent(String id) { + return ModList.get().isLoaded(id); + } + + @Override + public void initPlatformSpecific() { + if (this.isModPresent(HexInterop.Forge.CURIOS_API_ID)) { + CuriosApiInterop.init(); + } + } + + // @Override + // public double getReachDistance(Player player) { + // return player.getAttributeValue(ForgeMod.REACH_DISTANCE.get()); + // } + + @Override + public void setBrainsweepAddlData(Mob mob) { + mob.getPersistentData().putBoolean(TAG_BRAINSWEPT, true); + + if (mob.level() instanceof ServerLevel) { + ForgePacketHandler.getNetwork() + .send(PacketDistributor.TRACKING_ENTITY.with(() -> mob), MsgBrainsweepAck.of(mob)); + } + } + + @Override + public void setFlight(ServerPlayer player, FlightAbility flight) { + CompoundTag tag = player.getPersistentData(); + tag.putBoolean(TAG_FLIGHT_ALLOWED, flight != null); + if (flight != null) { + tag.putInt(TAG_FLIGHT_TIME, flight.timeLeft()); + tag.put(TAG_FLIGHT_ORIGIN, HexUtils.serializeToNBT(flight.origin())); + tag.putString(TAG_FLIGHT_DIMENSION, flight.dimension().location().toString()); + tag.putDouble(TAG_FLIGHT_RADIUS, flight.radius()); + } else { + tag.remove(TAG_FLIGHT_TIME); + tag.remove(TAG_FLIGHT_ORIGIN); + tag.remove(TAG_FLIGHT_DIMENSION); + tag.remove(TAG_FLIGHT_RADIUS); + } + } + + @Override + public void setAltiora(Player player, @Nullable AltioraAbility altiora) { + CompoundTag tag = player.getPersistentData(); + tag.putBoolean(TAG_ALTIORA_ALLOWED, altiora != null); + if (altiora != null) { + tag.putInt(TAG_ALTIORA_GRACE, altiora.gracePeriod()); + } else { + tag.remove(TAG_ALTIORA_ALLOWED); + } + + // The elytra ability is done with an event on fabric + var elytraing = CaelusApi.getInstance().getFlightAttribute(); + var inst = player.getAttributes().getInstance(elytraing); + if (altiora != null) { + if (inst.getModifier(ALTIORA_ATTRIBUTE_ID) == null) { + inst.addTransientModifier( + new AttributeModifier( + ALTIORA_ATTRIBUTE_ID, "Altiora", 1.0, AttributeModifier.Operation.ADDITION)); + } + } else { + inst.removeModifier(ALTIORA_ATTRIBUTE_ID); + } + + if (player instanceof ServerPlayer serverPlayer) { + CapSyncers.syncAltiora(serverPlayer); + } + } + + @Override + public @Nullable FrozenPigment setPigment(Player player, @Nullable FrozenPigment pigment) { + var old = getPigment(player); + + CompoundTag tag = player.getPersistentData(); + if (pigment != null) tag.put(TAG_PIGMENT, pigment.serializeToNBT()); + else tag.remove(TAG_PIGMENT); + + if (player instanceof ServerPlayer serverPlayer) { + CapSyncers.syncPigment(serverPlayer); + } + + return old; + } + + @Override + public void setSentinel(Player player, @Nullable Sentinel sentinel) { + CompoundTag tag = player.getPersistentData(); + tag.putBoolean(TAG_SENTINEL_EXISTS, sentinel != null); + if (sentinel != null) { + tag.putBoolean(TAG_SENTINEL_GREATER, sentinel.extendsRange()); + tag.put(TAG_SENTINEL_POSITION, HexUtils.serializeToNBT(sentinel.position())); + tag.putString(TAG_SENTINEL_DIMENSION, sentinel.dimension().location().toString()); + } else { + tag.remove(TAG_SENTINEL_GREATER); + tag.remove(TAG_SENTINEL_POSITION); + tag.remove(TAG_SENTINEL_DIMENSION); + } + + if (player instanceof ServerPlayer serverPlayer) { + CapSyncers.syncSentinel(serverPlayer); + } + } + + @Override + public void setStaffcastImage(ServerPlayer player, @Nullable CastingImage image) { + player + .getPersistentData() + .put(TAG_HARNESS, image == null ? new CompoundTag() : image.serializeToNbt()); + } + + @Override + public void setPatterns(ServerPlayer player, List<ResolvedPattern> patterns) { + var listTag = new ListTag(); + for (ResolvedPattern pattern : patterns) { + listTag.add(pattern.serializeToNBT()); + } + player.getPersistentData().put(TAG_PATTERNS, listTag); + } + + @Override + public boolean isBrainswept(Mob e) { + return e.getPersistentData().getBoolean(TAG_BRAINSWEPT); + } + + @Override + public FlightAbility getFlight(ServerPlayer player) { + CompoundTag tag = player.getPersistentData(); + boolean allowed = tag.getBoolean(TAG_FLIGHT_ALLOWED); + if (allowed) { + var timeLeft = tag.getInt(TAG_FLIGHT_TIME); + var origin = HexUtils.vecFromNBT(tag.getCompound(TAG_FLIGHT_ORIGIN)); + var radius = tag.getDouble(TAG_FLIGHT_RADIUS); + var dimension = + ResourceKey.create( + Registries.DIMENSION, new ResourceLocation(tag.getString(TAG_FLIGHT_DIMENSION))); + return new FlightAbility(timeLeft, dimension, origin, radius); + } + return null; + } + + @Override + public AltioraAbility getAltiora(Player player) { + CompoundTag tag = player.getPersistentData(); + boolean allowed = tag.getBoolean(TAG_ALTIORA_ALLOWED); + if (allowed) { + var grace = tag.getInt(TAG_ALTIORA_GRACE); + return new AltioraAbility(grace); + } + return null; + } + + @Override + public FrozenPigment getPigment(Player player) { + return FrozenPigment.fromNBT(player.getPersistentData().getCompound(TAG_PIGMENT)); + } + + @Override + public Sentinel getSentinel(Player player) { + CompoundTag tag = player.getPersistentData(); + var exists = tag.getBoolean(TAG_SENTINEL_EXISTS); + if (!exists) { + return null; + } + var extendsRange = tag.getBoolean(TAG_SENTINEL_GREATER); + var position = HexUtils.vecFromNBT(tag.getCompound(TAG_SENTINEL_POSITION)); + var dimension = + ResourceKey.create( + Registries.DIMENSION, new ResourceLocation(tag.getString(TAG_SENTINEL_DIMENSION))); + + return new Sentinel(extendsRange, position, dimension); + } + + @Override + public CastingVM getStaffcastVM(ServerPlayer player, InteractionHand hand) { + // This is always from a staff because we don't need to load the harness when casting from item + var ctx = new StaffCastEnv(player, hand); + return new CastingVM( + CastingImage.loadFromNbt( + player.getPersistentData().getCompound(TAG_HARNESS), player.serverLevel()), + ctx); + } + + @Override + public List<ResolvedPattern> getPatternsSavedInUi(ServerPlayer player) { + ListTag patternsTag = player.getPersistentData().getList(TAG_PATTERNS, Tag.TAG_COMPOUND); + + List<ResolvedPattern> patterns = new ArrayList<>(patternsTag.size()); + + for (int i = 0; i < patternsTag.size(); i++) { + patterns.add(ResolvedPattern.fromNBT(patternsTag.getCompound(i))); + } + return patterns; + } + + @Override + public void clearCastingData(ServerPlayer player) { + player.getPersistentData().remove(TAG_HARNESS); + player.getPersistentData().remove(TAG_PATTERNS); + } + + @Override + public @Nullable ADMediaHolder findMediaHolder(ItemStack stack) { + var maybeCap = stack.getCapability(HexCapabilities.MEDIA).resolve(); + return maybeCap.orElse(null); + } + + @Override + public @Nullable ADMediaHolder findMediaHolder(ServerPlayer player) { + var maybeCap = player.getCapability(HexCapabilities.MEDIA).resolve(); + return maybeCap.orElse(null); + } + + @Override + public @Nullable ADIotaHolder findDataHolder(ItemStack stack) { + var maybeCap = stack.getCapability(HexCapabilities.IOTA).resolve(); + return maybeCap.orElse(null); + } + + @Override + public @Nullable ADIotaHolder findDataHolder(Entity entity) { + var maybeCap = entity.getCapability(HexCapabilities.IOTA).resolve(); + return maybeCap.orElse(null); + } + + @Override + public @Nullable ADHexHolder findHexHolder(ItemStack stack) { + var maybeCap = stack.getCapability(HexCapabilities.STORED_HEX).resolve(); + return maybeCap.orElse(null); + } + + @Override + public @Nullable ADVariantItem findVariantHolder(ItemStack stack) { + var maybeCap = stack.getCapability(HexCapabilities.VARIANT_ITEM).resolve(); + return maybeCap.orElse(null); + } + + @Override + public boolean isPigment(ItemStack stack) { + return stack.getCapability(HexCapabilities.COLOR).isPresent(); + } + + @Override + public ColorProvider getColorProvider(FrozenPigment pigment) { + var maybePigment = pigment.item().getCapability(HexCapabilities.COLOR).resolve(); + if (maybePigment.isPresent()) { + return maybePigment.get().provideColor(pigment.owner()); + } + return ColorProvider.MISSING; + } + + @Override + public void sendPacketToPlayer(ServerPlayer target, IMessage packet) { + ForgePacketHandler.getNetwork().send(PacketDistributor.PLAYER.with(() -> target), packet); + } + + @Override + public void sendPacketNear(Vec3 pos, double radius, ServerLevel dimension, IMessage packet) { + ForgePacketHandler.getNetwork() + .send( + PacketDistributor.NEAR.with( + () -> + new PacketDistributor.TargetPoint( + pos.x, pos.y, pos.z, radius * radius, dimension.dimension())), + packet); + } + + @Override + public void sendPacketTracking(Entity entity, IMessage packet) { + ForgePacketHandler.getNetwork() + .send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), packet); + } + + @Override + public Packet<ClientGamePacketListener> toVanillaClientboundPacket(IMessage message) { + //noinspection unchecked + return (Packet<ClientGamePacketListener>) + ForgePacketHandler.getNetwork().toVanillaPacket(message, NetworkDirection.PLAY_TO_CLIENT); + } + + @Override + public <T extends BlockEntity> BlockEntityType<T> createBlockEntityType( + BiFunction<BlockPos, BlockState, T> func, Block... blocks) { + return BlockEntityType.Builder.of(func::apply, blocks).build(null); + } + + @Override + public boolean tryPlaceFluid(Level level, InteractionHand hand, BlockPos pos, Fluid fluid) { + Optional<IFluidHandler> handler = FluidUtil.getFluidHandler(level, pos, Direction.UP).resolve(); + return handler.isPresent() + && handler.get().fill(new FluidStack(fluid, FluidType.BUCKET_VOLUME), EXECUTE) > 0; + } + + @Override + public boolean drainAllFluid(Level level, BlockPos pos) { + Optional<IFluidHandler> handler = FluidUtil.getFluidHandler(level, pos, Direction.UP).resolve(); + if (handler.isPresent()) { + boolean any = false; + IFluidHandler pool = handler.get(); + for (int i = 0; i < pool.getTanks(); i++) { + if (!pool.drain(pool.getFluidInTank(i), EXECUTE).isEmpty()) { + any = true; + } + } + return any; + } + return false; + } + + @Override + public Ingredient getUnsealedIngredient(ItemStack stack) { + return ForgeUnsealedIngredient.of(stack); + } + + @Override + public boolean isCorrectTierForDrops(Tier tier, BlockState bs) { + return !bs.requiresCorrectToolForDrops() || TierSortingRegistry.isCorrectTierForDrops(tier, bs); + } + + @Override + public Item.Properties addEquipSlotFabric(EquipmentSlot slot) { + return new Item.Properties(); + } + + private static final IXplatTags TAGS = + new IXplatTags() { + @Override + public TagKey<Item> amethystDust() { + return HexTags.Items.create(new ResourceLocation("forge", "dusts/amethyst")); + } + + @Override + public TagKey<Item> gems() { + return HexTags.Items.create(new ResourceLocation("forge", "gems")); + } + }; + + @Override + public IXplatTags tags() { + return TAGS; + } + + @Override + public LootItemCondition.Builder isShearsCondition() { + return CanToolPerformAction.canToolPerformAction(ToolActions.SHEARS_DIG); + } + + @Override + public String getModName(String namespace) { + if (namespace.equals("c")) { + return "Common"; + } + Optional<? extends ModContainer> container = ModList.get().getModContainerById(namespace); + if (container.isPresent()) { + return container.get().getModInfo().getDisplayName(); + } + return namespace; + } + + private static final Supplier<Registry<ActionRegistryEntry>> ACTION_REGISTRY = + Suppliers.memoize( + () -> ForgeAccessorBuiltInRegistries.hex$registerSimple(HexRegistries.ACTION, null)); + private static final Supplier<Registry<SpecialHandler.Factory<?>>> SPECIAL_HANDLER_REGISTRY = + Suppliers.memoize( + () -> + ForgeAccessorBuiltInRegistries.hex$registerSimple( + HexRegistries.SPECIAL_HANDLER, null)); + private static final Supplier<Registry<IotaType<?>>> IOTA_TYPE_REGISTRY = + Suppliers.memoize( + () -> + ForgeAccessorBuiltInRegistries.hex$registerDefaulted( + HexRegistries.IOTA_TYPE, + modLoc("null").toString(), + registry -> HexIotaTypes.NULL)); + private static final Supplier<Registry<Arithmetic>> ARITHMETIC_REGISTRY = + Suppliers.memoize( + () -> ForgeAccessorBuiltInRegistries.hex$registerSimple(HexRegistries.ARITHMETIC, null)); + private static final Supplier<Registry<ContinuationFrame.Type<?>>> CONTINUATION_TYPE_REGISTRY = + Suppliers.memoize( + () -> + ForgeAccessorBuiltInRegistries.hex$registerDefaulted( + HexRegistries.CONTINUATION_TYPE, + modLoc("end").toString(), + registry -> HexContinuationTypes.END)); + private static final Supplier<Registry<EvalSound>> EVAL_SOUND_REGISTRY = + Suppliers.memoize( + () -> + ForgeAccessorBuiltInRegistries.hex$registerDefaulted( + HexRegistries.EVAL_SOUND, + modLoc("nothing").toString(), + registry -> HexEvalSounds.NOTHING)); + + @Override + public Registry<ActionRegistryEntry> getActionRegistry() { + return ACTION_REGISTRY.get(); + } + + @Override + public Registry<SpecialHandler.Factory<?>> getSpecialHandlerRegistry() { + return SPECIAL_HANDLER_REGISTRY.get(); + } + + @Override + public Registry<IotaType<?>> getIotaTypeRegistry() { + return IOTA_TYPE_REGISTRY.get(); + } + + @Override + public Registry<Arithmetic> getArithmeticRegistry() { + return ARITHMETIC_REGISTRY.get(); + } + + @Override + public Registry<ContinuationFrame.Type<?>> getContinuationTypeRegistry() { + return CONTINUATION_TYPE_REGISTRY.get(); + } + + @Override + public Registry<EvalSound> getEvalSoundRegistry() { + return EVAL_SOUND_REGISTRY.get(); + } + + @Override + public boolean isBreakingAllowed( + ServerLevel world, BlockPos pos, BlockState state, @Nullable Player player) { + if (player == null) player = FakePlayerFactory.get(world, HEXCASTING); + return !MinecraftForge.EVENT_BUS.post(new BlockEvent.BreakEvent(world, pos, state, player)); + } + + @Override + public boolean isPlacingAllowed( + ServerLevel world, BlockPos pos, ItemStack blockStack, @Nullable Player player) { + if (player == null) player = FakePlayerFactory.get(world, HEXCASTING); + ItemStack cached = player.getMainHandItem(); + player.setItemInHand(InteractionHand.MAIN_HAND, blockStack.copy()); + var evt = + ForgeHooks.onRightClickBlock( + player, + InteractionHand.MAIN_HAND, + pos, + new BlockHitResult(Vec3.atCenterOf(pos), Direction.DOWN, pos, true)); + player.setItemInHand(InteractionHand.MAIN_HAND, cached); + return !evt.isCanceled(); + } + + // it's literally the EXACT SAME on fabric aaa + private static PehkuiInterop.ApiAbstraction PEHKUI_API = null; + + @Override + public PehkuiInterop.ApiAbstraction getPehkuiApi() { + if (!this.isModPresent(HexInterop.PEHKUI_ID)) { + throw new IllegalArgumentException("cannot get the pehkui api without pehkui"); + } + + if (PEHKUI_API == null) { + PEHKUI_API = + new PehkuiInterop.ApiAbstraction() { + @Override + public float getScale(Entity e) { + return ScaleTypes.BASE.getScaleData(e).getScale(); + } + + @Override + public void setScale(Entity e, float scale) { + ScaleTypes.BASE.getScaleData(e).setScale(scale); + } + }; + } + return PEHKUI_API; + } + + public static final String TAG_BRAINSWEPT = "hexcasting:brainswept"; + public static final String TAG_SENTINEL_EXISTS = "hexcasting:sentinel_exists"; + public static final String TAG_SENTINEL_GREATER = "hexcasting:sentinel_extends_range"; + public static final String TAG_SENTINEL_POSITION = "hexcasting:sentinel_position"; + public static final String TAG_SENTINEL_DIMENSION = "hexcasting:sentinel_dimension"; + + public static final String TAG_PIGMENT = "hexcasting:pigment"; + + public static final String TAG_FLIGHT_ALLOWED = "hexcasting:flight_allowed"; + public static final String TAG_FLIGHT_TIME = "hexcasting:flight_time"; + public static final String TAG_FLIGHT_ORIGIN = "hexcasting:flight_origin"; + public static final String TAG_FLIGHT_DIMENSION = "hexcasting:flight_dimension"; + public static final String TAG_FLIGHT_RADIUS = "hexcasting:flight_radius"; + + public static final String TAG_ALTIORA_ALLOWED = "hexcasting:altiora_allowed"; + public static final String TAG_ALTIORA_GRACE = "hexcasting:altiora_grace_period"; + + public static final UUID ALTIORA_ATTRIBUTE_ID = + UUID.fromString("91897c79-3ebb-468c-a265-40418ed01c41"); + + public static final String TAG_HARNESS = "hexcasting:spell_harness"; + public static final String TAG_PATTERNS = "hexcasting:spell_patterns"; }