Compare commits

...

150 Commits

Author SHA1 Message Date
Sebastian Hartte 5da5315a5b Post-merge fixes. Reformat. Optimize Imports. 2020-09-20 14:47:25 +02:00
Sebastian Hartte f3c44c64c2 Merge remote-tracking branch 'origin/master' into fabric/master
# Conflicts:
#	build.gradle
#	gradle.properties
#	src/api/java/appeng/api/util/DimensionalCoord.java
#	src/main/java/appeng/block/paint/PaintSplotchesBakedModel.java
#	src/main/java/appeng/bootstrap/BlockDefinitionBuilder.java
#	src/main/java/appeng/client/gui/AEBaseScreen.java
#	src/main/java/appeng/client/gui/implementations/CraftAmountScreen.java
#	src/main/java/appeng/client/gui/implementations/CraftConfirmScreen.java
#	src/main/java/appeng/client/gui/implementations/CraftingStatusScreen.java
#	src/main/java/appeng/client/gui/implementations/InterfaceScreen.java
#	src/main/java/appeng/client/gui/implementations/InterfaceTerminalScreen.java
#	src/main/java/appeng/client/gui/implementations/LevelEmitterScreen.java
#	src/main/java/appeng/client/gui/implementations/NumberEntryWidget.java
#	src/main/java/appeng/client/gui/implementations/PriorityScreen.java
#	src/main/java/appeng/client/gui/widgets/IconButton.java
#	src/main/java/appeng/client/gui/widgets/NumberBox.java
#	src/main/java/appeng/client/gui/widgets/SettingToggleButton.java
#	src/main/java/appeng/client/gui/widgets/TabButton.java
#	src/main/java/appeng/client/render/DelegateBakedModel.java
#	src/main/java/appeng/client/render/DummyFluidDispatcherBakedModel.java
#	src/main/java/appeng/client/render/FacadeBakedItemModel.java
#	src/main/java/appeng/client/render/FacadeDispatcherBakedModel.java
#	src/main/java/appeng/client/render/cablebus/P2PTunnelFrequencyBakedModel.java
#	src/main/java/appeng/client/render/crafting/EncodedPatternBakedModel.java
#	src/main/java/appeng/client/render/model/AutoRotatingBakedModel.java
#	src/main/java/appeng/client/render/model/BiometricCardBakedModel.java
#	src/main/java/appeng/client/render/model/ColorApplicatorBakedModel.java
#	src/main/java/appeng/client/render/model/GlassBakedModel.java
#	src/main/java/appeng/client/render/model/MemoryCardBakedModel.java
#	src/main/java/appeng/client/render/model/SkyCompassBakedModel.java
#	src/main/java/appeng/client/render/tesr/ChestTileEntityRenderer.java
#	src/main/java/appeng/container/AEBaseContainer.java
#	src/main/java/appeng/container/ContainerLocator.java
#	src/main/java/appeng/container/guisync/SyncData.java
#	src/main/java/appeng/container/implementations/CellWorkbenchContainer.java
#	src/main/java/appeng/container/implementations/CondenserContainer.java
#	src/main/java/appeng/container/implementations/ContainerHelper.java
#	src/main/java/appeng/container/implementations/CraftConfirmContainer.java
#	src/main/java/appeng/container/implementations/CraftingCPUContainer.java
#	src/main/java/appeng/container/implementations/CraftingCPURecord.java
#	src/main/java/appeng/container/implementations/CraftingStatusContainer.java
#	src/main/java/appeng/container/implementations/IOPortContainer.java
#	src/main/java/appeng/container/implementations/InscriberContainer.java
#	src/main/java/appeng/container/implementations/InterfaceTerminalContainer.java
#	src/main/java/appeng/container/implementations/LevelEmitterContainer.java
#	src/main/java/appeng/container/implementations/MEMonitorableContainer.java
#	src/main/java/appeng/container/implementations/MolecularAssemblerContainer.java
#	src/main/java/appeng/container/implementations/PatternTermContainer.java
#	src/main/java/appeng/container/implementations/PriorityContainer.java
#	src/main/java/appeng/container/implementations/QuartzKnifeContainer.java
#	src/main/java/appeng/container/implementations/SpatialIOPortContainer.java
#	src/main/java/appeng/container/implementations/VibrationChamberContainer.java
#	src/main/java/appeng/container/implementations/WirelessTermContainer.java
#	src/main/java/appeng/core/AEConfig.java
#	src/main/java/appeng/core/AppEngBootstrap.java
#	src/main/java/appeng/core/Registration.java
#	src/main/java/appeng/core/api/definitions/ApiItems.java
#	src/main/java/appeng/core/features/registries/WorldGenRegistry.java
#	src/main/java/appeng/core/sync/network/NetworkHandler.java
#	src/main/java/appeng/core/worlddata/WorldData.java
#	src/main/java/appeng/datagen/providers/loot/BlockDropProvider.java
#	src/main/java/appeng/debug/ChunkLoaderBlockEntity.java
#	src/main/java/appeng/debug/ReplicatorCardItem.java
#	src/main/java/appeng/entity/GrowingCrystalEntity.java
#	src/main/java/appeng/fluids/client/gui/FluidLevelEmitterScreen.java
#	src/main/java/appeng/fluids/client/gui/FluidTerminalScreen.java
#	src/main/java/appeng/fluids/container/FluidConfigurableContainer.java
#	src/main/java/appeng/fluids/container/FluidInterfaceContainer.java
#	src/main/java/appeng/fluids/container/FluidLevelEmitterContainer.java
#	src/main/java/appeng/fluids/container/FluidTerminalContainer.java
#	src/main/java/appeng/fluids/util/AEFluidInventory.java
#	src/main/java/appeng/items/misc/CrystalSeedItem.java
#	src/main/java/appeng/items/misc/CrystalSeedRendering.java
#	src/main/java/appeng/items/storage/SpatialStorageCellItem.java
#	src/main/java/appeng/me/cluster/implementations/QuantumCluster.java
#	src/main/java/appeng/mixins/feature/ConfiguredFeaturesAccessor.java
#	src/main/java/appeng/mixins/spatial/BiomesMixin.java
#	src/main/java/appeng/mixins/spatial/DimensionTypeMixin.java
#	src/main/java/appeng/mixins/spatial/EntityMixin.java
#	src/main/java/appeng/mixins/spatial/SkyRenderMixin.java
#	src/main/java/appeng/mixins/structure/BiomeAccessor.java
#	src/main/java/appeng/mixins/structure/GenerationSettingsAccessor.java
#	src/main/java/appeng/parts/automation/FormationPlanePart.java
#	src/main/java/appeng/parts/automation/PlaneBakedModel.java
#	src/main/java/appeng/server/subcommands/SpatialStorageCommand.java
#	src/main/java/appeng/server/subcommands/TestMeteoritesCommand.java
#	src/main/java/appeng/server/subcommands/TestOreGenCommand.java
#	src/main/java/appeng/spatial/SpatialStorageBiome.java
#	src/main/java/appeng/spatial/SpatialStorageChunkGenerator.java
#	src/main/java/appeng/spatial/SpatialStorageDimensionIds.java
#	src/main/java/appeng/spatial/SpatialStorageHelper.java
#	src/main/java/appeng/util/Platform.java
#	src/main/java/appeng/worldgen/BiomeModifier.java
#	src/main/java/appeng/worldgen/meteorite/MeteoriteStructureStart.java
#	src/main/java/appeng/worldgen/meteorite/fallout/FalloutCopy.java
#	src/main/resources/assets/appliedenergistics2/textures/guis/states.png
2020-09-20 14:11:22 +02:00
Sebastian Hartte b8f48407cd Fix tooltip rendering. 2020-09-20 01:06:53 +02:00
Sebastian Hartte 489b0f635e Merge remote-tracking branch 'origin/8.0.x-1.16.1' 2020-09-20 00:42:52 +02:00
shartte e6fb553a53 Fixes #4741: Rework Crafting CPU cycling and extract commonalities into a separate class. (#4742)
Also Fixes:
- Enter key confirms the "Confirm Crafting" dialog again
- Right Mouse Button correctly cycles backwards through CPUs, while left mouse button forward
- Fixes an internal problem with syncing CPU names
- Naming of unnamed CPUs begins at #1 now
2020-09-20 00:26:34 +02:00
Sebastian Hartte cacd824db3 Remove unused field indicating availability of client classes. 2020-09-19 18:20:11 +02:00
yueh 876bb52087 Update forge mappings to 20200916-1.16.2 (#4749) 2020-09-19 17:32:23 +02:00
Sebastian Hartte 1b4969c8e7 Formatting fixes. 2020-09-19 16:58:37 +02:00
Sebastian Hartte f2427ee347 Fixes #4747: The chunk unload event was triggering before the chunk was actually saved to disk, which means disconnecting grid connections at that point led to grid nodes not saving their data to the chunk. 2020-09-19 16:54:30 +02:00
Sebastian Hartte 4aa9c92a68 Fixes #4747: Server unload event was destroying grids before the associated nodes were saved, leading to player ids not being saved correctly when quitting the server. 2020-09-19 16:49:44 +02:00
shartte 971a9d22e8 Improvements to the usability of the number entry widgets (Priority, Level Emitter, Craft Amount): (#4737)
- Fixed tab order
- Introduced focus state for corner buttons
- Allowed the player to enter any text, but add validation that only persist it if it is a valid number
- Enter will now confirm these dialogs and return to the previous dialog
- The text field is automatically focused and its contents are selected
2020-09-19 16:27:29 +02:00
Sebastian Hartte b5a90357c0 Fix ME Chest attributes being exposed on the wrong side. 2020-09-19 13:59:09 +02:00
Sebastian Hartte 5be0adbc89 Fixed Mixins that were targeting the wrong class/methods. 2020-09-19 02:48:59 +02:00
Sebastian Hartte d8e5f4fed5 Fixed formatating after migrating mappings. 2020-09-19 02:41:53 +02:00
Sebastian Hartte 47dfc19b7c Renamed mixin after mapping update. 2020-09-19 02:40:51 +02:00
Sebastian Hartte 45f5851079 Updated versions, and mappings. 2020-09-19 02:40:35 +02:00
Sebastian Hartte 76efe6026d Add an indicator that shows the number of active crafting jobs. 2020-09-18 21:34:42 +02:00
yueh 4e03cbd356 Simply build all branches 2020-09-18 10:32:06 +02:00
Sebastian Hartte ce058b006c Fixes #4748: badly filtered inventory leads to crashes, also expose the ME storage again. 2020-09-18 03:11:33 +02:00
yueh 9005db6f1c Fix yaml syntax 2020-09-17 21:42:20 +02:00
yueh 58afe755b8 Build PRs for all release branches (#4746) 2020-09-17 21:37:53 +02:00
Sebastian Hartte f368f9dac2 Fixes #4697: Show number of required items in condenser tooltips. 2020-09-17 14:33:43 +02:00
Sebastian Hartte e5b45d51cc Minor style fixes. 2020-09-17 11:43:29 +02:00
shartte 5a1d5356d1 Fixes #4733: Fix a crash bug when an external machine tries draining fluids from a fluid interface without a filter. (#4738) 2020-09-16 23:13:18 +02:00
Sebastian Hartte 5aef82b9ef Optimized Imports 2020-09-16 21:35:47 +02:00
Sebastian Hartte 483f93f977 Post-merge fixes and item generator fix. 2020-09-16 20:12:38 +02:00
Sebastian Hartte 1759f92164 Prevent FG from force-exiting the daemon if runData is used. 2020-09-16 19:51:22 +02:00
Sebastian Hartte e50c13e570 Rolled back the memory change since it'll cause a daemon to launch even during a CI build. 2020-09-16 19:29:47 +02:00
Sebastian Hartte c0575e11b0 Merge remote-tracking branch 'origin/master' into fabric/master
# Conflicts:
#	build.gradle
#	gradle.properties
#	gradle/scripts/artifacts.gradle
#	gradle/scripts/curseforge.gradle
#	gradle/wrapper/gradle-wrapper.jar
#	gradle/wrapper/gradle-wrapper.properties
#	src/main/java/appeng/block/networking/CableBusBlock.java
#	src/main/java/appeng/client/gui/AEBaseScreen.java
#	src/main/java/appeng/client/gui/implementations/InterfaceTerminalScreen.java
#	src/main/java/appeng/client/gui/widgets/Scrollbar.java
#	src/main/java/appeng/core/sync/packets/JEIRecipePacket.java
#	src/main/java/appeng/tile/AEBaseBlockEntity.java
#	src/main/resources/META-INF/mods.toml
2020-09-16 18:57:15 +02:00
Sebastian Hartte 749dd35f88 Updated forge and increased memory for IDE-sync daemon. 2020-09-16 18:18:22 +02:00
Sebastian Hartte ca79a377bd Merge remote-tracking branch 'origin/8.0.x-1.16.1'
# Conflicts:
#	gradle/scripts/dependencies.gradle
2020-09-16 17:49:59 +02:00
Sebastian Hartte 475c8ff5a1 Adapt the same sorting logic used for items stored in the network for items obtained from patterns, which fixes items from patterns not being able to be shift-clicked into new patterns. 2020-09-16 17:44:49 +02:00
yueh 5b3ccf26d0 Merge all gradle files (#4732)
* Merge all gradle files

The specific build files are now much smaller, so a single one is mostly acceptable now.
Also updates Gradle to 5.6.3

* Disable the Mixin annotation processor when importing this project into IntelliJ since it should only be needed to generate refmaps on an actual build.

* Removed Sonarqube and JaCoCo plugins.

Co-authored-by: Sebastian Hartte <sebastian@hartte.de>
2020-09-14 14:14:00 +02:00
Sebastian Hartte e73dbe4891 Updated Forge / MC to 1.16.3
Keep Mappings
Allow higher range for MC + Forge versions
2020-09-14 02:02:59 +02:00
Sebastian Hartte 38244000c9 Fixes #4731: Take the position where the user clicked the handle into account when calculating the new scrollbar position.
Also fixes: The scrollbar did not subtract the handle height when determining the available space for moving the handle, thus introducing drift the further down a user scrolled.
Also fixes: The scrollbar did not resize it's trackbar when the ME inventory screens were resized and the number of rows changed, same for craft confirm.
2020-09-13 23:12:59 +02:00
Sebastian Hartte d87ff9d1e7 Formatting fixes. 2020-09-13 22:18:38 +02:00
Sebastian Hartte 4ba97ec899 Remove unnecessary debug prints, and rename methods. 2020-09-13 22:11:40 +02:00
Sebastian Hartte 0147e1ddfb Fixes #4730 and also introduces repeat-pageup/pagedown when holding the mouse on the area above or below the scrollbar handle. 2020-09-13 22:09:47 +02:00
yueh 621d2ee715 Fixes #4728: Mark all offloading threads as daemons (#4729) 2020-09-13 11:55:18 +02:00
Sebastian Hartte 31ecdfbe0a Use the correct method to update an entities position forcefully. 2020-09-11 18:04:17 +02:00
Sebastian Hartte f0bfbfec48 Should also actually _use_ the fixed invoker... 2020-09-11 17:25:39 +02:00
Sebastian Hartte 06a8843a65 Fix a Mixin bug that causes an Invoker conflict with Patchouli.
See https://github.com/SpongePowered/Mixin/issues/430
2020-09-11 17:20:20 +02:00
shartte d07937fa93 Render Performance Improvements (#4721)
* Return a fixed bounding box for frustrum culling of AE tile entity renderers to prevent Forge from re-retrieving the TE from the world and calculating the collision box (very costly for cables).

* Changed dynamic cable bus lighting to be based on block states to improved rendering speed and fix optifine issues. (Potential fix for #4716).
2020-09-10 22:56:50 +02:00
shartte 65f58913a4 Make players assume ownership of networks when they place security stations onto unsecured ones (#4714)
* Fixes #4712: When a security station is placed onto an unsecured network, the placer assumes ownership of the entire network. Otherwise the contiguous network would not necessarily reconnect in the same way when the chunk is reloaded due to differing player-ids throughout the network.
In addition, changes to the node's owner were not being persisted due to the host never being marked as dirty.

* Fix formatting
2020-09-10 22:34:16 +02:00
Sebastian Hartte 2bca23d75d Rebuilt the recipe transfer after upstream changes. 2020-09-10 22:05:06 +02:00
Sebastian Hartte b47543d166 Merge remote-tracking branch 'origin/master' into fabric/master
# Conflicts:
#	gradle.properties
#	src/main/java/appeng/core/Registration.java
#	src/main/java/appeng/core/sync/packets/JEIRecipePacket.java
#	src/main/java/appeng/entity/TinyTNTPrimedEntity.java
#	src/main/java/appeng/fluids/client/gui/widgets/FluidSlotWidget.java
#	src/main/java/appeng/fluids/container/FluidConfigurableContainer.java
#	src/main/java/appeng/integration/modules/jei/FacadeRegistryPlugin.java
#	src/main/java/appeng/integration/modules/jei/JEIPlugin.java
#	src/main/java/appeng/integration/modules/jei/RecipeTransferHandler.java
#	src/main/java/appeng/mixins/structure/BiomeAccessor.java
#	src/main/java/appeng/parts/automation/AnnihilationPlanePart.java
#	src/main/java/appeng/parts/automation/FormationPlanePart.java
2020-09-10 19:20:58 +02:00
Sebastian Hartte a340925d98 Fix Wireless screen translated text. 2020-09-10 19:06:00 +02:00
yueh b8e53adf40 Fixes #4719: Take the entity size into account when spawning item entities (#4720) 2020-09-10 17:54:02 +02:00
yueh 44544c598f Fixes #4253: Just transfer the recipe id instead of every ingredient. (#4689)
* Fixes #4253: Just transfer the recipe id instead of every ingredient.
* If possible handle any IRecipe for processing mode
* Improvements and support for AE2 facades.
* Switched to using JEI's displayed stacks (which means we can remove the shapeless variant).

Co-authored-by: Sebastian Hartte <sebastian@hartte.de>
2020-09-09 14:08:24 +02:00
Sebastian Hartte 0be7322c2c Formatting Fixes. 2020-09-09 02:27:12 +02:00
Sebastian Hartte a521e827db Merge remote-tracking branch 'origin/master' into fabric/master
# Conflicts:
#	src/main/java/appeng/core/api/definitions/ApiItems.java
2020-09-09 02:25:15 +02:00
Sebastian Hartte bcee2ec427 Slightly increased the height of the item hitbox for crystals to make their pickup by annihilation planes less "clippy". 2020-09-09 02:23:58 +02:00
Sebastian Hartte 17648633fe Merge fixes. 2020-09-09 02:23:14 +02:00
Sebastian Hartte fcbebd4ffc Merge remote-tracking branch 'origin/master' into fabric/master
# Conflicts:
#	gradle.properties
#	src/api/java/appeng/api/implementations/items/IGrowableCrystal.java
#	src/main/java/appeng/core/AEConfig.java
#	src/main/java/appeng/core/api/definitions/ApiBlocks.java
#	src/main/java/appeng/core/features/registries/LocatableRegistry.java
#	src/main/java/appeng/decorative/solid/QuartzGlassBlock.java
#	src/main/java/appeng/decorative/solid/SkyStoneBlock.java
#	src/main/java/appeng/entity/GrowingCrystalEntity.java
#	src/main/java/appeng/fluids/parts/FluidImportBusPart.java
#	src/main/java/appeng/items/misc/CrystalSeedItem.java
#	src/main/java/appeng/items/tools/powered/ColorApplicatorItem.java
#	src/main/java/appeng/me/cluster/implementations/QuantumCluster.java
#	src/main/java/appeng/parts/CableBusContainer.java
#	src/main/java/appeng/tile/AEBaseBlockEntity.java
2020-09-09 01:41:49 +02:00
Sebastian Hartte 9e41d543f5 Merge remote-tracking branch 'origin/8.0.x-1.16.1' 2020-09-09 00:59:58 +02:00
Sebastian Hartte 81cc0b804d Fixes #4699: AE's glass should only hide it's sides adjacent to other AE glass.
Also disables spawn on AE's glass same as Vanilla glass.
2020-09-09 00:58:14 +02:00
Sebastian Hartte e1fc9908b3 Fixes #4693: Fix color applicator not working on cable-buses. 2020-09-09 00:51:45 +02:00
shartte 9ed1535477 Fixes #4661: Do not update a tile entity when it's in an unloaded chunk (i.e. during chunk unloading) (#4708) 2020-09-08 22:28:30 +02:00
Sebastian Hartte 1ef345d4a4 Formatting fixes. 2020-09-08 22:24:27 +02:00
Sebastian Hartte ff7d1b9719 Fixes #4704: QNB is not finding a registered QNB because it believes the chunk to be unloaded.
Also adds debug logging to the locatable registry to better debug this issues in the future.
2020-09-08 22:20:33 +02:00
shartte 88c9370e4f Crystal Growth Refactor (#4702)
* Refactored crystal in-world purification:
- Removed iterative formula
- Set the default growth factor to 1 rather than 0.5 to simplify settings
- Made the growth-tick-progress-per-tick a configuration setting for 0-6 accelerators
- Unfinished seeds now slowly sink when ejected by an annihilation plane or other system (emulates a player throwing it in)
- Instead of checking for "isLiquid", we now check for a new tag (appliedenergistics2:crystal_purification_medium) to check if the crystal is submerged in an allowed fluid for growth, defaults to #minecraft:water.

* Removed configuration options for changing how accelerators work,
replaced with improved fluid tag option with a clamped multiplier [1,10].
2020-09-08 18:10:45 +02:00
Sebastian Hartte f2aae3ef0f Added a global Voxelshape cache for cable bus voxel shapes, since combining voxel shapes turns out to be an extremely expensive process (i.e. 1.7s for 10000x5 shapes). 2020-09-08 17:56:02 +02:00
Sebastian Hartte 12739f1e66 Remove unneeded cable-bus inventory-model, which caused the part models to be loaded twice leading to unnecessary memory-usage. 2020-09-08 17:53:14 +02:00
shartte 81d2170ada Implemented a cache with maximum quad-count it will cache for the cable bus, (#4670)
which also fixes concurrent access to the hashmap.

(cherry picked from commit b756d68be1)
2020-09-08 14:28:08 +02:00
Sebastian Hartte 0f469e9df6 Bumped Forge version. 2020-09-07 23:34:56 +02:00
Sebastian Hartte 0f34f09b32 Remove object-scanning subscriptions and remove unused test-file. 2020-09-06 20:59:37 +02:00
Sebastian Hartte 8e54a8fed9 Fixes a problem where tile entities would become unremovable (well, one more of these at least),
because they would reset their block state upon removal and loss of power.
2020-09-06 20:59:19 +02:00
Sebastian Hartte ca007a3737 Fix compatibility with fabric-api 0.20 2020-09-05 19:30:00 +02:00
Sebastian Hartte 92b6650022 Reformat. 2020-09-05 19:22:21 +02:00
Sebastian Hartte e1cd3bba25 Improved logging and slight refactor. 2020-09-05 19:22:05 +02:00
Sebastian Hartte 689bf6e8d9 Removed unused worldgen registry,
added biome blacklists for meteorites and quartz ore, and
also fixed adding meteorite/quartz to biomes that are
registered after AE2 initializes.
2020-09-05 19:15:45 +02:00
Sebastian Hartte c8a5049d71 Fix path to AE2 logo in mod json. 2020-09-03 23:33:48 +02:00
Sebastian Hartte 10a1a6d855 Fixes #4674: Facade quads should not keep their original cull-faces if they're moved away
from the block face.
2020-09-03 17:54:23 +02:00
Sebastian Hartte d9bb81a00f Fixes #4680: Facade advancement is showing an untextured facade. 2020-09-03 17:36:20 +02:00
yueh 39e038d916 Fixes #4683: Hopefully LazyOptional works as advertised (#4684) 2020-09-02 21:36:40 +02:00
Sebastian Hartte 575a625f75 Also update the layer-map, even though the spatial biome should never show up in any vanilla layering. 2020-09-02 19:44:37 +02:00
Sebastian Hartte 89ea923c43 Merge fixes 2020-09-02 19:41:44 +02:00
Sebastian Hartte 5d818eb03e Merge remote-tracking branch 'origin/master' into fabric/master 2020-09-02 02:55:39 +02:00
Sebastian Hartte 12ca8d109a Merge remote-tracking branch 'origin/8.0.x-1.16.1' 2020-09-02 02:55:12 +02:00
Sebastian Hartte e34126458b Merge remote-tracking branch 'origin/master' into fabric/master
# Conflicts:
#	gradle.properties
#	src/main/java/appeng/client/gui/Size1Slot.java
#	src/main/java/appeng/client/me/SlotFluidME.java
#	src/main/java/appeng/client/me/SlotME.java
#	src/main/java/appeng/client/render/cablebus/CableBusBakedModel.java
#	src/main/java/appeng/client/render/cablebus/CableBusModelLoader.java
#	src/main/java/appeng/core/sync/packets/MEFluidInventoryUpdatePacket.java
#	src/main/java/appeng/core/sync/packets/MEInterfaceUpdatePacket.java
#	src/main/java/appeng/core/sync/packets/MEInventoryUpdatePacket.java
#	src/main/java/appeng/datagen/providers/loot/BlockDropProvider.java
#	src/main/java/appeng/fluids/client/gui/widgets/FluidSlotWidget.java
#	src/main/java/appeng/fluids/container/FluidConfigurableContainer.java
#	src/main/java/appeng/fluids/helper/FluidCellConfig.java
#	src/main/resources/META-INF/mods.toml
2020-09-02 02:45:31 +02:00
Sebastian Hartte 0ac918c363 Fixed exclusion zones for many screens. 2020-09-02 02:37:47 +02:00
Sebastian Hartte b6160e40bc Fixes #4671: Use other Ingredient method which is not client-only. 2020-09-02 01:49:24 +02:00
Sebastian Hartte cf103b06c1 Fixes #4677: Stackoverflow when crafting with the quartz knife. 2020-09-02 00:12:20 +02:00
yueh f0d0595c8f Fixes #4669: Take NBT into account for comparing. (#4675)
This only covers combining different items together.
Fuzzy filtering is still a bit too fuzzy for corner cases.
2020-09-01 21:59:08 +02:00
shartte b756d68be1 Implemented a cache with maximum quad-count it will cache for the cable bus, (#4670)
which also fixes concurrent access to the hashmap.
2020-09-01 18:20:51 +02:00
Sebastian Hartte 60b07e5ca5 Merge branch '8.0.x-1.16.1' 2020-09-01 01:07:47 +02:00
shartte 7c99fca789 Fixes removal of facades not invalidating the cached server-side collision boxes. (#4663)
(cherry picked from commit 957bc4c5cc)
2020-09-01 01:07:30 +02:00
yueh ab393b0ed1 Serialize the complete NBT data to avoid mismatches (#4665)
This might increase the network traffic a bit, but the amount of mods actually using the share tag seems to be very limited.
For now it is worth the risk as it solves the problem. In case we run into actual issues, there might still be other solutions, which will be way more complex and can potentially introduce additional problems.

(cherry picked from commit e90dd2f9c6)
2020-09-01 01:07:28 +02:00
shartte 957bc4c5cc Fixes removal of facades not invalidating the cached server-side collision boxes. (#4663) 2020-08-31 23:10:25 +02:00
yueh 133ed1f09d Remove GZipStreams from packets. (#4664)
This should now be handled by the normal network manager (hopefully).
Also renamed the `CompressedNBTPacket` to `MEInterfaceUpdatePacket` as that is the only use case.
2020-08-31 23:09:28 +02:00
yueh e90dd2f9c6 Serialize the complete NBT data to avoid mismatches (#4665)
This might increase the network traffic a bit, but the amount of mods actually using the share tag seems to be very limited.
For now it is worth the risk as it solves the problem. In case we run into actual issues, there might still be other solutions, which will be way more complex and can potentially introduce additional problems.
2020-08-31 23:09:14 +02:00
Sebastian Hartte 9719c7ffc3 Bump to Forge 33.0.22 2020-08-29 23:13:29 +02:00
Sebastian Hartte 319d92a371 Merge branch '8.0.x-1.16.1' 2020-08-29 22:18:12 +02:00
shartte db9ec2b070 Remove the use of SlotItemHandler since we are only faking an inventory-backed slot, (#4654)
we might as well use what we had used pre-2017, which is simply extending a normal Slot.
This should also fix #4652.
2020-08-29 22:03:35 +02:00
Sebastian Hartte 5d33005aaf Added back dynamic cable bus lighting. 2020-08-29 01:02:32 +02:00
Sebastian Hartte 87cf070b33 Fixes #4657: Remove usage of an implementation class and just copy the needed values into arrays. 2020-08-29 00:45:01 +02:00
Masakitenchi 3a0552c56e Update zh_cn.json (#4653) 2020-08-28 10:49:11 +02:00
Sebastian Hartte b1a55f3a79 Bumped dependencies. 2020-08-27 00:49:41 +02:00
Sebastian Hartte 226e9596ee Fix the fluid export bus not actually extracting fluids from storage when exporting. 2020-08-27 00:21:14 +02:00
Sebastian Hartte 5cab9c8799 Fix rendering of fluid filter slots in UIs. 2020-08-27 00:20:53 +02:00
Sebastian Hartte 1d2ac29742 Document Maven Repositories. 2020-08-26 23:22:17 +02:00
Sebastian Hartte cbe6012b98 Merge remote-tracking branch 'origin/master' into fabric/master 2020-08-26 23:20:50 +02:00
Sebastian Hartte 8a0dd192e5 Added Modmaven repository to README.md 2020-08-26 23:19:42 +02:00
Sebastian Hartte 1842febf86 Merge remote-tracking branch 'origin/master' into fabric/master
# Conflicts:
#	build.gradle
2020-08-26 11:41:13 +02:00
Sebastian Hartte a97b35f3d0 Merge branch '8.0.x-1.16.1' 2020-08-26 11:39:20 +02:00
Sebastian Hartte 00d4c20d9f Strip pom.xml dependencies. 2020-08-26 11:39:03 +02:00
Sebastian Hartte d2b69671f5 Merge remote-tracking branch 'origin/master' into fabric/master
# Conflicts:
#	src/main/java/appeng/tile/grid/AENetworkInvBlockEntity.java
2020-08-24 23:55:41 +02:00
Sebastian Hartte 1394ab0863 Merge branch '8.0.x-1.16.1' 2020-08-24 23:54:57 +02:00
Sebastian Hartte 5efc085693 Fix tiles that have a "powered" block state from not being able to be broken when
they are connected to a powered grid.
2020-08-24 23:54:37 +02:00
Sebastian Hartte 359e3f7e63 Fix crystal despawning. 2020-08-24 23:13:58 +02:00
Sebastian Hartte fa3e41e687 Fix remaining filtered item handler uses. 2020-08-24 22:48:07 +02:00
Sebastian Hartte 4e86c92720 Merge remote-tracking branch 'origin/master' into fabric/master
# Conflicts:
#	src/main/java/appeng/client/gui/implementations/InterfaceTerminalScreen.java
2020-08-24 22:34:26 +02:00
Sebastian Hartte 159f4c7f14 Merge branch '8.0.x-1.16.1' 2020-08-24 22:33:38 +02:00
Sebastian Hartte aff94cec8c Fix search box interactions in the interface terminal. 2020-08-24 22:33:04 +02:00
Sebastian Hartte 07dfa3db2e Fix filtered inventory for IO port. 2020-08-24 21:24:51 +02:00
Sebastian Hartte e0e139900f Fix Spatial IO Port filtered inventory. 2020-08-24 21:19:27 +02:00
Sebastian Hartte 9942f2d32c Fix filtered inventory for Grinder 2020-08-24 21:11:52 +02:00
Sebastian Hartte 858826d1fa Fix use of Fuel Registry (it is null not, 0 for unregistered items).
Fix Vibration Chamber inventory filter.
Fix Molecular Assembler inventory filter.
2020-08-24 20:58:49 +02:00
Sebastian Hartte 90ad345672 Slight wrench cleanup. 2020-08-24 20:34:57 +02:00
Sebastian Hartte 9a81ebfa50 Check the REI search field for being null before using it. 2020-08-24 20:25:03 +02:00
Sebastian Hartte da9fa3d697 Merge remote-tracking branch 'origin/master' into fabric/master 2020-08-24 01:07:08 +02:00
Sebastian Hartte ee7fe9f40d Merge branch '8.0.x-1.16.1' 2020-08-24 01:06:50 +02:00
Sebastian Hartte 2184d03d0b Actually save the rotation when a tile is rotated. 2020-08-24 01:06:26 +02:00
Sebastian Hartte cae1621613 Fix inscriber inventory filtering, and accidental overwriting of the output slot. 2020-08-24 01:01:16 +02:00
Sebastian Hartte e8574d03ea Use a different heuristic for determining how to render items in the middle of the inscriber. 2020-08-24 01:00:33 +02:00
Sebastian Hartte d28f33d198 Split into internal and external inventories.
Fixes Charger not being able to load inventories that violated the filter.
2020-08-24 00:01:18 +02:00
Sebastian Hartte 7df5bf4076 Fix crank not attaching sideways. 2020-08-23 23:49:50 +02:00
Sebastian Hartte 66760865a3 Split resource generation and build because there's a hidden dependency. 2020-08-23 23:12:47 +02:00
Sebastian Hartte e4a08ba99d Log where resources are being generated. 2020-08-23 23:07:12 +02:00
Sebastian Hartte f11e9e2a4c Actually generate data for branch-builds too. 2020-08-23 22:54:52 +02:00
Sebastian Hartte 7a469c1a1d Fix server-side HYWLA problems. 2020-08-23 22:30:08 +02:00
Sebastian Hartte e256a4f664 Post-Merge fixes. 2020-08-23 21:20:51 +02:00
Sebastian Hartte 73cc3f8998 Merge remote-tracking branch 'origin/master' into fabric/master
# Conflicts:
#	gradle.properties
#	src/main/java/appeng/core/api/definitions/ApiItems.java
2020-08-23 21:08:47 +02:00
Sebastian Hartte 9c9a49f9e7 Merge branch '8.0.x-1.16.1' 2020-08-23 20:48:19 +02:00
Sebastian Hartte 44c0931c02 Fixes #4635: Actually remove requesters when removing requesters. 2020-08-23 20:47:05 +02:00
Sebastian Hartte 874f46ed4d Fixes #4633: Storage buses cannot see attached inventories. 2020-08-23 11:23:35 +02:00
Sebastian Hartte b7949e4134 Re-Enabled JEI and TOP in dev. 2020-08-22 19:56:37 +02:00
Sebastian Hartte ea95913ec8 Merge branch '8.0.x-1.16.1' 2020-08-22 19:38:36 +02:00
yueh 423ab81813 Added step to publish to modmaven (#4607)
(cherry picked from commit 7e1bfdb5ac)
2020-08-21 20:40:03 +02:00
Sebastian Hartte d82c713112 Delay registration of various client settings until the client is fully initialized. 2020-08-21 00:00:03 +02:00
Sebastian Hartte 45cbc40177 Fix wrench interaction with part hosts. 2020-08-20 22:58:49 +02:00
shartte 33d7f02323 Fixes #4590: Crystal seeds (other than certus) don't display their growth stages. (#4619) 2020-08-19 16:43:47 +02:00
shartte 4e42b17e81 Fixes #4590: Crystal seeds (other than certus) don't display their growth stages. (#4618) 2020-08-19 16:43:45 +02:00
Sebastian Hartte 0e7e9313ee Fixes wrenches not working on tile entities.
This is a temporary hack for now.
2020-08-19 01:53:51 +02:00
Sebastian Hartte 2bba843313 Remove unused code in Condenser. 2020-08-19 01:34:15 +02:00
Sebastian Hartte a0949297d5 Added AE tools to fabric tool tags to fix breaking speed. 2020-08-19 01:34:08 +02:00
Sebastian Hartte 420fb272b4 Bump LBA version to fix filter bugs. 2020-08-19 01:33:34 +02:00
shartte fc0f8eab56 Fixes #4611: Use of client-side only method for Tiny TNT explosion. (#4612) 2020-08-18 01:33:47 +02:00
shartte 41b7900706 Fixes #4598: Incorrectly rotated face for determining block lightlevel in ME Chest renderer. (#4599) (#4609)
(cherry picked from commit 954ce1442e)
2020-08-17 21:58:51 +02:00
shartte 7656157b0d Fixes #4602: Prevent encoding invalid patterns and handle corrupted patterns a little more gracefully. (#4608) 2020-08-17 21:49:37 +02:00
200 changed files with 3549 additions and 3744 deletions
+3 -1
View File
@@ -21,7 +21,9 @@ jobs:
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
- name: Build with Gradle
- name: Generate Resources
run: ./gradlew generateData
- name: Build
run: ./gradlew build
- uses: actions/upload-artifact@v2
with:
+2 -1
View File
@@ -2,7 +2,8 @@ name: 'Build PRs'
on:
pull_request:
branches: [ master ]
branches:
- '*'
jobs:
build:
+5 -1
View File
@@ -23,10 +23,14 @@ jobs:
run: chmod +x gradlew
- name: Validate no assets
run: test ! -d ./src/generated
- name: Generate resources
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew generateData
- name: Build with Gradle
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew generateData build
run: ./gradlew build
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
+26 -4
View File
@@ -72,19 +72,41 @@ The API for Applied Energistics 2. It is open source to discuss changes, improve
### Maven
We use Github Packages as maven repository now. You can use the following snippet as example on how to add a repository to your gradle build file.
Our authoritative Maven repository is Github Packages, which you can also use in your builds. Use of Github Packages
[requires special setup](https://docs.github.com/en/packages/using-github-packages-with-your-projects-ecosystem/configuring-gradle-for-use-with-github-packages#authenticating-to-github-packages)
to authenticate with your personal access token.
AE2 is also available without authentication from Modmaven.
You can use the following snippet as example on how to add a repository to your gradle build file.
repositories {
maven {
name "AE2"
url "https://maven.pkg.github.com/AppliedEnergistics/Applied-Energistics-2"
name "Modmaven"
url "https://modmaven.k-4u.nl/"
// For Gradle 5.1 and above, limit it to just AE2
content {
includeGroup 'appeng'
}
}
// Required for libblockattributes
maven {
name = "BuildCraft"
url = "https://mod-buildcraft.com/maven"
content {
includeGroup "alexiil.mc.lib"
}
}
}
When compiling against the AE2 API you can use gradle dependencies, just add
dependencies {
compileOnly "appeng:appliedenergistics2:VERSION:api"
modCompileOnly "appeng:appliedenergistics2-fabric:VERSION:api"
// Include only if you want AE2 at runtime
modRuntimeOnly "appeng:appliedenergistics2-fabric:VERSION"
}
or add the `compileOnly` line to your existing dependencies task to your build.gradle.
+178 -48
View File
@@ -47,6 +47,47 @@ repositories {
}
}
dependencies {
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
//Fabric api
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_version}"
modImplementation "alexiil.mc.lib:libblockattributes-core:${libblockattributes_version}"
modImplementation "alexiil.mc.lib:libblockattributes-items:${libblockattributes_version}"
modImplementation "alexiil.mc.lib:libblockattributes-fluids:${libblockattributes_version}"
include "alexiil.mc.lib:libblockattributes-core:${libblockattributes_version}"
include "alexiil.mc.lib:libblockattributes-items:${libblockattributes_version}"
include "alexiil.mc.lib:libblockattributes-fluids:${libblockattributes_version}"
// Energy API
modApi "teamreborn:energy:${tr_energy_version}"
include "teamreborn:energy:${tr_energy_version}"
modCompileOnly("me.shedaniel:RoughlyEnoughItems:${rei_version}") {
exclude group: "net.fabricmc.fabric-api"
}
modCompileOnly("mcp.mobius.waila:Hwyla:1.16.1-1.9.22-75") {
exclude group: "net.fabricmc.fabric-api"
}
modRuntime("me.shedaniel:RoughlyEnoughItems:${rei_version}") {
exclude group: "net.fabricmc.fabric-api"
}
modRuntime("TechReborn:TechReborn-1.16:3.5.1+build.101") {
exclude group: "net.fabricmc.fabric-api"
}
// modRuntimeOnly "mcp.mobius.waila:Hwyla:1.16.1-1.9.22-75"
implementation 'com.google.code.findbugs:jsr305:3.0.2'
// unit test dependencies
testCompile "junit:junit:4.13"
}
group = artifact_group
archivesBaseName = artifact_basename
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8
compileJava {
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8
@@ -59,7 +100,9 @@ tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
// Create version number
///////////////////
// Version Number
ext.pr = System.getenv('PR_NUMBER') ?: ""
if (ext.pr) {
version = version + "+pr." + ext.pr
@@ -81,9 +124,8 @@ if (ext.tag && ext.tag.startsWith("fabric/v")) {
}
}
// Maven group and artifact name
group = artifact_group
archivesBaseName = artifact_basename
ext.isAlpha = project.version.contains("alpha")
ext.isBeta = project.version.contains("beta")
sourceSets {
api
@@ -119,51 +161,12 @@ configurations {
siteexportRuntime.extendsFrom(runtimeClasspath)
}
apply from: 'gradle/scripts/spotless.gradle'
////////////////////
// Forge/Minecraft
minecraft {
accessWidener "src/main/resources/appliedenergistics2.accesswidener"
}
dependencies {
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
//Fabric api
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_version}"
modImplementation "alexiil.mc.lib:libblockattributes-core:${libblockattributes_version}"
modImplementation "alexiil.mc.lib:libblockattributes-items:${libblockattributes_version}"
modImplementation "alexiil.mc.lib:libblockattributes-fluids:${libblockattributes_version}"
include "alexiil.mc.lib:libblockattributes-core:${libblockattributes_version}"
include "alexiil.mc.lib:libblockattributes-items:${libblockattributes_version}"
include "alexiil.mc.lib:libblockattributes-fluids:${libblockattributes_version}"
// Energy API
modApi "teamreborn:energy:${tr_energy_version}"
include "teamreborn:energy:${tr_energy_version}"
modCompileOnly("me.shedaniel:RoughlyEnoughItems:5.0.2-unstable") {
exclude group: "net.fabricmc.fabric-api"
}
modCompileOnly("mcp.mobius.waila:Hwyla:1.16.1-1.9.22-75") {
exclude group: "net.fabricmc.fabric-api"
}
modRuntime("me.shedaniel:RoughlyEnoughItems:5.0.2-unstable") {
exclude group: "net.fabricmc.fabric-api"
}
modRuntime("TechReborn:TechReborn-1.16:3.5.1+build.101") {
exclude group: "net.fabricmc.fabric-api"
}
// modRuntimeOnly "mcp.mobius.waila:Hwyla:1.16.1-1.9.22-75"
implementation 'com.google.code.findbugs:jsr305:3.0.2'
// unit test dependencies
testCompile "junit:junit:4.13"
}
processResources {
inputs.property "version", project.version
@@ -177,10 +180,76 @@ processResources {
}
}
apply from: 'gradle/scripts/artifacts.gradle'
apply from: 'gradle/scripts/curseforge.gradle'
//////////////
// Aritfacts
processResources {
exclude '.cache'
}
// configure the maven publication
jar {
finalizedBy 'remapJar'
from sourceSets.main.output.classesDirs
from sourceSets.api.output.classesDirs
from sourceSets.main.output.resourcesDir
from sourceSets.api.output.resourcesDir
manifest {
attributes([
"Specification-Title": "Applied Energistics 2",
"Specification-Vendor": "TeamAppliedEnergistics",
"Specification-Version": "${project.version}",
"Implementation-Title": "${project.name}",
"Implementation-Version": "${project.version}",
"Implementation-Vendor" :"TeamAppliedEnergistics",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
"MixinConfigs": "appliedenergistics2.mixins.json"
])
}
}
task javadocs(type: Javadoc) {
classpath = sourceSets.main.compileClasspath
source = sourceSets.api.java
include "appeng/api/**"
options.addStringOption('Xdoclint:none', '-quiet')
options.encoding = 'UTF-8'
options.charSet = 'UTF-8'
}
task javadocJar(type: Jar, dependsOn: javadocs) {
classifier = "javadoc"
from javadoc.destinationDir
}
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this task, sources will not be generated.
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = "sources"
from sourceSets.main.allSource
from sourceSets.api.allSource
}
task apiJar(type: Jar) {
classifier = "api"
from sourceSets.api.output
include "appeng/api/**"
// TODO: when FG bug is fixed, remove allJava from the api jar.
// https://github.com/MinecraftForge/ForgeGradle/issues/369
// Gradle should be able to pull them from the -sources jar.
from sourceSets.api.allJava
}
artifacts {
archives javadocJar
archives sourcesJar
archives apiJar
}
//////////////////
// Maven publish
publishing {
if (!version.endsWith("-SNAPSHOT")) {
publications {
@@ -239,3 +308,64 @@ task runSiteExport(type: RunClientTask, dependsOn: downloadAssets, group: "ae2",
classpath sourceSets.main.output
classpath sourceSets.siteexport.output
}
/////////////
// Spotless
spotless {
java {
target 'src/*/java/appeng/**/*.java'
indentWithSpaces()
eclipse().configFile 'codeformat/codeformat.xml'
importOrderFile 'codeformat/ae2.importorder'
}
format 'json', {
target 'src/*/resources/**/*.json'
targetExclude 'src/generated/resources/**'
prettier().config(['parser': 'json'])
}
}
////////////////
// Curse Forge
if (System.getenv("CURSEFORGE") && !version.endsWith("-SNAPSHOT")) {
def cfReleaseType = "release"
if (ext.isAlpha) {
cfReleaseType = "alpha"
} else if (ext.isBeta) {
cfReleaseType = "beta"
}
curseforge {
apiKey = System.getenv("CURSEFORGE")
project {
id = project.curseforge_project
changelogType = "markdown"
changelog = System.getenv("CHANGELOG") ?: "Please visit our [releases](https://github.com/AppliedEnergistics/Applied-Energistics-2/releases) for a changelog"
releaseType = cfReleaseType
addGameVersion project.minecraft_version
addGameVersion "Fabric"
mainArtifact(remapJar.archiveFile) {
displayName = "${project.version} [FABRIC]"
}
}
options {
forgeGradleIntegration = false
}
afterEvaluate {
tasks.getByName("curseforge${project.curseforge_project}").dependsOn remapJar
}
}
}
////////////////
// IntelliJ Project Import
// The Mixin annotation process does not have an obfuscation source when running through the IntelliJ compiler,
// thus we have to prevent it from being activated as part of importing this Gradle project into IntelliJ.
if (System.getProperty("idea.sync.active") == "true") {
afterEvaluate {
tasks.withType(JavaCompile).all {
it.options.annotationProcessorPath = files()
}
}
}
+7 -11
View File
@@ -3,28 +3,24 @@ version=0.0.0-SNAPSHOT
artifact_group=appeng
artifact_basename=appliedenergistics2-fabric
kotlin.code.style=official
org.gradle.jvmargs=-Xmx2G
# Fabric Properties
# Check these on https://modmuss50.me/fabric.html
minecraft_version=1.16.2
yarn_mappings=1.16.2+build.6
loader_version=0.9.1+build.205
minecraft_version=1.16.3
yarn_mappings=1.16.3+build.11
loader_version=0.9.3+build.207
#Fabric api
fabric_version=0.17.2+build.396-1.16
fabric_version=0.21.0+build.407-1.16
loom_version=0.4-SNAPSHOT
# Kotlin
kotlin_version=1.3.61
fabric_kotlin_version=1.3.61+build.1
loom_version=0.5-SNAPSHOT
# Dependencies
libblockattributes_version=0.8.0-pre.18
libblockattributes_version=0.8.0
tr_energy_version=0.1.0
rei_version=5.2.10
#########################################################
# Deployment #
-78
View File
@@ -1,78 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
processResources {
exclude '.cache'
}
jar {
finalizedBy 'remapJar'
from sourceSets.main.output.classesDirs
from sourceSets.api.output.classesDirs
from sourceSets.main.output.resourcesDir
from sourceSets.api.output.resourcesDir
manifest {
attributes([
"Specification-Title": "Applied Energistics 2",
"Specification-Vendor": "TeamAppliedEnergistics",
"Specification-Version": "${project.version}",
"Implementation-Title": "${project.name}",
"Implementation-Version": "${project.version}",
"Implementation-Vendor" :"TeamAppliedEnergistics",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
])
}
}
task javadocs(type: Javadoc) {
classpath = sourceSets.main.compileClasspath
source = sourceSets.api.java
include "appeng/api/**"
options.addStringOption('Xdoclint:none', '-quiet')
options.encoding = 'UTF-8'
options.charSet = 'UTF-8'
}
task javadocJar(type: Jar, dependsOn: javadocs) {
classifier = "javadoc"
from javadoc.destinationDir
}
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this task, sources will not be generated.
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = "sources"
from sourceSets.main.allSource
from sourceSets.api.allSource
}
task apiJar(type: Jar) {
classifier = "api"
from sourceSets.api.output
include "appeng/api/**"
}
artifacts {
archives javadocJar
archives sourcesJar
archives apiJar
}
-50
View File
@@ -1,50 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2020, TeamAppliedEnergistics, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*g GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
def isAlpha = project.version.contains("alpha")
def isBeta = project.version.contains("beta")
def cfReleaseType = "release"
if (isAlpha) {
cfReleaseType = "alpha"
} else if (isBeta) {
cfReleaseType = "beta"
}
if (System.getenv("CURSEFORGE") && !version.endsWith("-SNAPSHOT")) {
curseforge {
apiKey = System.getenv("CURSEFORGE")
project {
id = project.curseforge_project
changelogType = "markdown"
changelog = System.getenv("CHANGELOG") ?: "Please visit our [releases](https://github.com/AppliedEnergistics/Applied-Energistics-2/releases) for a changelog"
releaseType = cfReleaseType
addGameVersion project.minecraft_version
addGameVersion "Fabric"
mainArtifact(remapJar.archiveFile) {
displayName = "${project.version} [FABRIC]"
}
}
options {
forgeGradleIntegration = false
}
afterEvaluate {
tasks.getByName("curseforge${project.curseforge_project}").dependsOn remapJar
}
}
}
-42
View File
@@ -1,42 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
repositories {
mavenLocal()
maven { // modmaven, maven proxy
name 'modmaven'
url "https://modmaven.k-4u.nl/"
}
}
dependencies {
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
// compile against provided APIs
compileOnly "mezz.jei:jei-${jei_minecraft_version}:${jei_version}:api"
compileOnly "mcjty.theoneprobe:TheOneProbe-${minecraft_release}:${minecraft_release}-${top_version}:api"
// Runtime, Mods
// FIXME 1.16.2 runtimeOnly fg.deobf("mezz.jei:jei-${jei_minecraft_version}:${jei_version}")
// FIXME 1.16.2 runtimeOnly fg.deobf("mcjty.theoneprobe:TheOneProbe-${minecraft_release}:${minecraft_release}-${top_version}")
//runtimeOnly fg.deobf("team.chisel.ctm:CTM:${ctm_version}")
// unit test dependencies
testCompile "junit:junit:4.13"
}
-32
View File
@@ -1,32 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2020, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*g GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
spotless {
java {
target 'src/*/java/appeng/**/*.java'
indentWithSpaces()
eclipse().configFile 'codeformat/codeformat.xml'
importOrderFile 'codeformat/ae2.importorder'
}
format 'json', {
target 'src/*/resources/**/*.json'
targetExclude 'src/generated/resources/**'
prettier().config(['parser': 'json'])
}
}
-1
View File
@@ -10,7 +10,6 @@ pluginManagement {
plugins {
id "fabric-loom" version loom_version
id "org.jetbrains.kotlin.jvm" version kotlin_version
}
}
@@ -53,10 +53,10 @@ public interface ICraftingHelper {
* @param stack If null, a new item will be created to hold the encoded pattern.
* Otherwise the given item must already contains an encoded
* pattern that will be overwritten.
* @throws IllegalArgumentException If either in or out contain only empty
* ItemStacks.
* @return A new encoded pattern, or the given stack with the pattern encoded in
* it.
* @throws IllegalArgumentException If either in or out contain only empty
* ItemStacks.
*/
ItemStack encodeProcessingPattern(@Nullable ItemStack stack, ItemStack[] in, ItemStack[] out);
@@ -82,11 +82,6 @@ public interface IRegistryContainer {
*/
IPlayerRegistry players();
/**
* get access to the world-gen api.
*/
IWorldGen worldgen();
/**
* Register your IPart models before using them.
*/
@@ -1,40 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2013 AlgorithmX2
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package appeng.api.features;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
public interface IWorldGen {
void enableWorldGenForDimension(WorldGenType type, Identifier dimID);
void disableWorldGenForDimension(WorldGenType type, Identifier dimID);
boolean isWorldGenEnabled(WorldGenType type, ServerWorld w);
enum WorldGenType {
CERTUS_QUARTZ, CHARGED_CERTUS_QUARTZ, METEORITES
}
}
@@ -23,13 +23,23 @@
package appeng.api.implementations.items;
import net.minecraft.block.Block;
import net.minecraft.block.Material;
import javax.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public interface IGrowableCrystal {
ItemStack triggerGrowth(ItemStack is);
float getMultiplier(Block blk, Material mat);
/**
* Gets the crystal growth multiplier based on the material it is submerged in.
*
* @param state The blockstate of the block the crystal is currently in.
* @return The multiplier for the growth tick progress. Zero if the crystal
* cannot grow in the current material.
*/
float getMultiplier(BlockState state, @Nullable World world, @Nullable BlockPos pos);
}
@@ -28,4 +28,9 @@ public enum GridNotification {
* the visible connections for this node have changed, useful for cable.
*/
CONNECTIONS_CHANGED,
/**
* the owner of the grid node has changed, and the node needs to be re-saved
*/
OWNER_CHANGED
}
@@ -87,7 +87,8 @@ public interface IGridBlock {
AEColor getGridColor();
/**
* Notifies your IGridBlock that changes were made to your connections
* Called by the {@link IGridNode} to notify its {@link IGridBlock} about
* events.
*/
void onGridNotification(@Nonnull GridNotification notification);
@@ -4,6 +4,9 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint;
import net.minecraft.Bootstrap;
import net.minecraft.data.DataGenerator;
@@ -11,16 +14,22 @@ import net.minecraft.data.DataGenerator;
import appeng.data.providers.loot.BlockDropProvider;
import appeng.data.providers.recipes.SlabStairRecipes;
import appeng.data.providers.tags.ConventionTagProvider;
import appeng.data.providers.tags.ToolTagProviders;
public class Entrypoint implements PreLaunchEntrypoint {
private static final Logger LOGGER = LogManager.getLogger();
public static void dump() throws Exception {
Path output = Paths.get("../src/generated/resources");
LOGGER.info("Writing generated resources to {}", output.toAbsolutePath());
DataGenerator generator = new DataGenerator(output, Collections.emptyList());
generator.install(new BlockDropProvider(output));
generator.install(new SlabStairRecipes(output));
generator.install(new ConventionTagProvider(output));
generator.install(new ToolTagProviders(output));
generator.run();
}
@@ -11,7 +11,7 @@ import appeng.core.AppEng;
public class ConventionTagProvider extends TagProvider {
public ConventionTagProvider(Path outputPath) {
super(outputPath);
super("c", outputPath);
}
@Override
@@ -24,15 +24,17 @@ import appeng.data.providers.IAE2DataProvider;
public abstract class TagProvider implements IAE2DataProvider {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
protected static final String CONVENTION_NAMESPACE = "c";
protected static final String TYPE_ITEMS = "items";
protected static final String TYPE_BLOCKS = "blocks";
private final String defaultNamespace;
private final Path outputPath;
private DataCache cache;
protected TagProvider(Path outputPath) {
protected TagProvider(String defaultNamespace, Path outputPath) {
this.defaultNamespace = defaultNamespace;
this.outputPath = outputPath;
}
@@ -49,15 +51,19 @@ public abstract class TagProvider implements IAE2DataProvider {
protected abstract void generate() throws IOException;
protected void addItemTag(String name, ItemConvertible... items) throws IOException {
Identifier id = parseId(name);
List<String> itemIds = Arrays.stream(items).map(ItemConvertible::asItem).map(Registry.ITEM::getId)
.map(Identifier::toString).collect(Collectors.toList());
writeTagFile(CONVENTION_NAMESPACE, TYPE_ITEMS, name, itemIds);
writeTagFile(id.getNamespace(), TYPE_ITEMS, id.getPath(), itemIds);
}
protected void addBlockTag(String name, Block... blocks) throws IOException {
Identifier id = parseId(name);
List<String> itemIds = Arrays.stream(blocks).map(Registry.BLOCK::getId).map(Identifier::toString)
.collect(Collectors.toList());
writeTagFile(CONVENTION_NAMESPACE, TYPE_BLOCKS, name, itemIds);
writeTagFile(id.getNamespace(), TYPE_BLOCKS, id.getPath(), itemIds);
}
protected void writeTagFile(String namespace, String tagType, String tagName, List<String> entries)
@@ -75,7 +81,15 @@ public abstract class TagProvider implements IAE2DataProvider {
@Override
public String getName() {
return AppEng.MOD_NAME + " Convention Tags";
return AppEng.MOD_NAME + " Tags (" + defaultNamespace + ")";
}
private Identifier parseId(String name) {
if (name.contains(":")) {
return new Identifier(name);
} else {
return new Identifier(defaultNamespace, name);
}
}
}
@@ -0,0 +1,28 @@
package appeng.data.providers.tags;
import java.io.IOException;
import java.nio.file.Path;
import appeng.core.AppEng;
public class ToolTagProviders extends TagProvider {
public ToolTagProviders(Path outputPath) {
super("fabric", outputPath);
}
@Override
protected void generate() throws IOException {
addItemTag("axes", ITEMS.netherQuartzAxe(), ITEMS.certusQuartzAxe());
addItemTag("hoes", ITEMS.netherQuartzHoe(), ITEMS.certusQuartzHoe());
addItemTag("pickaxes", ITEMS.netherQuartzPick(), ITEMS.certusQuartzPick());
addItemTag("shovels", ITEMS.netherQuartzShovel(), ITEMS.certusQuartzShovel());
addItemTag("swords", ITEMS.netherQuartzSword(), ITEMS.certusQuartzSword());
}
@Override
public String getName() {
return AppEng.MOD_NAME + " Tool Tags";
}
}
@@ -48,7 +48,7 @@ public final class MEAttributes {
return null;
}
return attribute.getFirstOrNull(world, be.getPos().offset(side), SearchOptions.inDirection(side.getOpposite()));
return attribute.getFirstOrNull(world, be.getPos(), SearchOptions.inDirection(side.getOpposite()));
}
// Convenience function to get an attribute of the block that is in front of a
@@ -232,7 +232,7 @@ public abstract class AEBaseTileBlock<T extends AEBaseBlockEntity> extends AEBas
Platform.spawnDrops(world, pos, itemsToDrop);
}
return ActionResult.FAIL;
return ActionResult.SUCCESS;
}
if (heldItem.getItem() instanceof IMemoryCard && !(this instanceof CableBusBlock)) {
@@ -161,4 +161,9 @@ public class CrankBlock extends AEBaseTileBlock<CrankBlockEntity> {
}
}
@Override
protected boolean hasCustomRotation() {
return true;
}
}
@@ -41,6 +41,8 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.IntProperty;
import net.minecraft.util.ActionResult;
import net.minecraft.util.DyeColor;
import net.minecraft.util.Hand;
@@ -80,8 +82,12 @@ public class CableBusBlock extends AEBaseTileBlock<CableBusBlockEntity> implemen
private static final ICableBusContainer NULL_CABLE_BUS = new NullCableBusContainer();
private static final IntProperty LIGHT_LEVEL = IntProperty.of("light_level", 0, 15);
public CableBusBlock() {
super(defaultProps(AEMaterials.GLASS).nonOpaque().dropsNothing().dynamicBounds());
super(defaultProps(AEMaterials.GLASS).nonOpaque().dropsNothing().dynamicBounds()
.luminance(state -> state.get(LIGHT_LEVEL)));
setDefaultState(getDefaultState().with(LIGHT_LEVEL, 0));
}
static {
@@ -134,16 +140,13 @@ public class CableBusBlock extends AEBaseTileBlock<CableBusBlockEntity> implemen
// OPPOSITE!?
}
// FIXME Dynamic light seems unsupported (?) Must maybe use blockstates... :|
// FIXME FABRIC @Override
// FIXME FABRIC public int getLightValue(final BlockState state, final BlockView world, final BlockPos pos) {
// FIXME FABRIC if (state.getBlock() != this) {
// FIXME FABRIC return state.getLuminance();
// FIXME FABRIC }
// FIXME FABRIC return this.cb(world, pos).getLightValue();
// FIXME FABRIC }
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(LIGHT_LEVEL);
}
// FIXME: Must hook isClimbing ourselves
// FIXME: Must hook isClimbing ourselves
// FIXME FABRIC @Override
// FIXME FABRIC public boolean isLadder(BlockState state, WorldView world, BlockPos pos, LivingEntity entity) {
// FIXME FABRIC return this.cb(world, pos).isLadder(entity);
@@ -399,4 +402,13 @@ public class CableBusBlock extends AEBaseTileBlock<CableBusBlockEntity> implemen
}
}
@Override
protected BlockState updateBlockStateFromTileEntity(BlockState currentState, CableBusBlockEntity te) {
if (currentState.getBlock() != this) {
return currentState;
}
int lightLevel = te.getCableBus().getLightValue();
return super.updateBlockStateFromTileEntity(currentState, te).with(LIGHT_LEVEL, lightLevel);
}
}
@@ -38,11 +38,11 @@ import appeng.helpers.Splotch;
*/
class PaintSplotchesBakedModel implements BakedModel, FabricBakedModel {
private static final SpriteIdentifier TEXTURE_PAINT1 = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
private static final SpriteIdentifier TEXTURE_PAINT1 = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, "block/paint1"));
private static final SpriteIdentifier TEXTURE_PAINT2 = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
private static final SpriteIdentifier TEXTURE_PAINT2 = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, "block/paint2"));
private static final SpriteIdentifier TEXTURE_PAINT3 = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
private static final SpriteIdentifier TEXTURE_PAINT3 = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, "block/paint3"));
private final Sprite[] textures;
@@ -36,18 +36,18 @@ import appeng.core.AppEng;
class QnbFormedBakedModel implements BakedModel, FabricBakedModel {
private static final SpriteIdentifier TEXTURE_LINK = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
private static final SpriteIdentifier TEXTURE_LINK = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, "block/quantum_link"));
private static final SpriteIdentifier TEXTURE_RING = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
private static final SpriteIdentifier TEXTURE_RING = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, "block/quantum_ring"));
private static final SpriteIdentifier TEXTURE_RING_LIGHT = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "block/quantum_ring_light"));
private static final SpriteIdentifier TEXTURE_RING_LIGHT = new SpriteIdentifier(
SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, new Identifier(AppEng.MOD_ID, "block/quantum_ring_light"));
private static final SpriteIdentifier TEXTURE_RING_LIGHT_CORNER = new SpriteIdentifier(
SpriteAtlasTexture.BLOCK_ATLAS_TEX, new Identifier(AppEng.MOD_ID, "block/quantum_ring_light_corner"));
private static final SpriteIdentifier TEXTURE_CABLE_GLASS = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "part/cable/glass/transparent"));
SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, new Identifier(AppEng.MOD_ID, "block/quantum_ring_light_corner"));
private static final SpriteIdentifier TEXTURE_CABLE_GLASS = new SpriteIdentifier(
SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, new Identifier(AppEng.MOD_ID, "part/cable/glass/transparent"));
private static final SpriteIdentifier TEXTURE_COVERED_CABLE = new SpriteIdentifier(
SpriteAtlasTexture.BLOCK_ATLAS_TEX, new Identifier(AppEng.MOD_ID, "part/cable/covered/transparent"));
SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, new Identifier(AppEng.MOD_ID, "part/cable/covered/transparent"));
private static final float DEFAULT_RENDER_MIN = 2.0f;
private static final float DEFAULT_RENDER_MAX = 14.0f;
@@ -11,7 +11,6 @@ import com.google.common.base.Preconditions;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.rendereregistry.v1.BlockEntityRendererRegistry;
import net.minecraft.block.Block;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.util.Identifier;
@@ -19,6 +18,7 @@ import net.minecraft.util.registry.Registry;
import appeng.api.features.AEFeature;
import appeng.block.AEBaseTileBlock;
import appeng.bootstrap.components.BlockEntityRendererComponent;
import appeng.bootstrap.components.ITileEntityRegistrationComponent;
import appeng.bootstrap.definitions.TileEntityDefinition;
import appeng.core.AppEng;
@@ -115,7 +115,8 @@ public class BlockEntityBuilder<T extends AEBaseBlockEntity> {
@Environment(EnvType.CLIENT)
private void buildClient() {
if (tileEntityRendering.tileEntityRenderer != null) {
BlockEntityRendererRegistry.INSTANCE.register(type, tileEntityRendering.tileEntityRenderer);
factory.addBootstrapComponent(
new BlockEntityRendererComponent<>(type, tileEntityRendering.tileEntityRenderer));
}
}
@@ -0,0 +1,33 @@
package appeng.bootstrap.components;
import java.util.function.Function;
import net.fabricmc.fabric.api.client.rendereregistry.v1.BlockEntityRendererRegistry;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
/**
* Registers a block entity renderer for a given block entity type. This must
* occur late in the client's initialization, since the constructors of our
* block entity renderers rely on the client being fully initialized.
*/
public class BlockEntityRendererComponent<T extends BlockEntity> implements IClientSetupComponent {
private final BlockEntityType<T> type;
private final Function<BlockEntityRenderDispatcher, BlockEntityRenderer<T>> renderer;
public BlockEntityRendererComponent(BlockEntityType<T> type,
Function<BlockEntityRenderDispatcher, BlockEntityRenderer<T>> renderer) {
this.type = type;
this.renderer = renderer;
}
@Override
public void setup() {
BlockEntityRendererRegistry.INSTANCE.register(type, renderer);
}
}
@@ -13,6 +13,7 @@ import javax.annotation.Nonnull;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry;
@@ -184,7 +185,9 @@ public final class AppEngClient extends AppEngBase {
ModelsReloadCallback.EVENT.register(this::onModelsReloaded);
callDeferredBootstrapComponents(IClientSetupComponent.class, IClientSetupComponent::setup);
ClientLifecycleEvents.CLIENT_STARTED.register(client -> {
callDeferredBootstrapComponents(IClientSetupComponent.class, IClientSetupComponent::setup);
});
registerModelProviders();
registerParticleRenderers();
registerEntityRenderers();
@@ -28,6 +28,7 @@ import java.util.stream.Collectors;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
import com.mojang.blaze3d.systems.RenderSystem;
import org.lwjgl.glfw.GLFW;
@@ -58,6 +59,7 @@ import net.minecraft.util.Identifier;
import alexiil.mc.lib.attributes.fluid.render.FluidRenderFace;
import alexiil.mc.lib.attributes.fluid.render.FluidVolumeRenderer;
import alexiil.mc.lib.attributes.fluid.volume.FluidVolume;
import me.shedaniel.math.Rectangle;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IAEItemStack;
@@ -104,6 +106,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
private Stopwatch dbl_clickTimer = Stopwatch.createStarted();
private ItemStack dbl_whichItem = ItemStack.EMPTY;
private Slot bl_clicked;
private boolean handlingRightClick;
protected final List<CustomSlotWidget> guiSlots = new ArrayList<>();
public AEBaseScreen(T container, PlayerInventory playerInventory, Text title) {
@@ -282,12 +285,18 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
public boolean mouseClicked(final double xCoord, final double yCoord, final int btn) {
this.drag_click.clear();
// Forward right-clicks as-if they were left-clicks
if (btn == 1) {
for (final Object o : this.buttons) {
final AbstractButtonWidget widget = (AbstractButtonWidget) o;
if (widget.isMouseOver(xCoord, yCoord)) {
return super.mouseClicked(xCoord, yCoord, 0);
handlingRightClick = true;
try {
for (final Object o : this.buttons) {
final AbstractButtonWidget widget = (AbstractButtonWidget) o;
if (widget.isMouseOver(xCoord, yCoord)) {
return super.mouseClicked(xCoord, yCoord, 0);
}
}
} finally {
handlingRightClick = false;
}
}
@@ -298,22 +307,36 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
}
}
if (this.getScrollBar() != null) {
this.getScrollBar().click(xCoord - this.x, yCoord - this.y);
// Forward left mouse button down events to the scrollbar
if (btn == 0 && this.getScrollBar() != null) {
if (this.getScrollBar().mouseDown(xCoord - this.x, yCoord - this.y)) {
return true;
}
}
return super.mouseClicked(xCoord, yCoord, btn);
}
@Override
public boolean mouseDragged(double mouseX, double mouseY, int mouseButton, double dragX, double dragY) {
public boolean mouseReleased(double mouseX, double mouseY, int button) {
// Forward left mouse button up events to the scrollbar
if (button == 0 && this.getScrollBar() != null) {
if (this.getScrollBar().mouseUp(mouseX - this.x, mouseY - this.y)) {
return true;
}
}
return super.mouseReleased(mouseX, mouseY, button);
}
@Override
public boolean mouseDragged(double mouseX, double mouseY, int mouseButton, double dragX, double dragY) {
final Slot slot = this.getSlot((int) mouseX, (int) mouseY);
final ItemStack itemstack = getPlayer().inventory.getCursorStack();
if (this.getScrollBar() != null) {
// FIXME: Coordinate system of mouseX/mouseY is unclear
this.getScrollBar().click((int) mouseX - this.x, (int) mouseY - this.y);
this.getScrollBar().mouseDragged((int) mouseX - this.x, (int) mouseY - this.y);
}
if (slot instanceof FakeSlot && !itemstack.isEmpty()) {
@@ -620,15 +643,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
}
protected Text getGuiDisplayName(final Text in) {
return this.hasCustomInventoryName() ? new LiteralText(this.getInventoryName()) : in;
}
private boolean hasCustomInventoryName() {
return this.handler.getCustomName() != null;
}
private String getInventoryName() {
return this.handler.getCustomName();
return title.getString().isEmpty() ? in : title;
}
/**
@@ -796,6 +811,11 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
public void tick() {
super.tick();
if (this.getScrollBar() != null) {
this.getScrollBar().tick();
}
for (Element child : children) {
if (child instanceof ITickingWidget) {
((ITickingWidget) child).tick();
@@ -803,4 +823,15 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
}
}
/**
* Returns true while the current event being handled is a click of the right
* mouse button.
*/
public boolean isHandlingRightClick() {
return handlingRightClick;
}
public List<Rectangle> getExclusionZones() {
return Lists.newArrayList(new Rectangle(x, y, backgroundWidth, backgroundHeight));
}
}
@@ -12,8 +12,6 @@ import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot;
import net.minecraft.util.Identifier;
import appeng.client.me.SlotME;
/**
* A proxy for a slot that will always return an itemstack with size 1, if there
* is an item in the slot. Used to prevent the default item count from
@@ -21,9 +19,9 @@ import appeng.client.me.SlotME;
*/
class Size1Slot extends Slot {
private final SlotME delegate;
private final Slot delegate;
public Size1Slot(SlotME delegate) {
public Size1Slot(Slot delegate) {
super(delegate.inventory, -1, delegate.x, delegate.y);
this.delegate = delegate;
}
@@ -46,22 +46,28 @@ public class CraftAmountScreen extends AEBaseScreen<CraftAmountContainer> {
public void init() {
super.init();
this.amountToCraft = new NumberEntryWidget(this, 20, 30, 138, 62, NumberEntryType.CRAFT_ITEM_COUNT, value -> {
});
this.amountToCraft = new NumberEntryWidget(this, 20, 30, 138, 62, NumberEntryType.CRAFT_ITEM_COUNT);
this.amountToCraft.setValue(1);
this.amountToCraft.setTextFieldBounds(62, 57, 50);
this.amountToCraft.setMinValue(1);
this.amountToCraft.setHideValidationIcon(true);
this.amountToCraft.addButtons(children::add, this::addButton);
this.next = this
.addButton(new ButtonWidget(this.x + 128, this.y + 51, 38, 20, GuiText.Next.text(), this::confirm));
this.amountToCraft.setOnConfirm(() -> this.confirm(this.next));
subGui.addBackButton(this::addButton, 154, 0);
changeFocus(true);
}
private void confirm(ButtonWidget button) {
NetworkHandler.instance()
.sendToServer(new CraftRequestPacket((int) this.amountToCraft.getValue(), hasShiftDown()));
int amount = this.amountToCraft.getIntValue().orElse(0);
if (amount <= 0) {
return;
}
NetworkHandler.instance().sendToServer(new CraftRequestPacket(amount, hasShiftDown()));
}
@Override
@@ -77,23 +83,9 @@ public class CraftAmountScreen extends AEBaseScreen<CraftAmountContainer> {
this.bindTexture("guis/craft_amt.png");
drawTexture(matrices, offsetX, offsetY, 0, 0, this.backgroundWidth, this.backgroundHeight);
this.next.active = this.amountToCraft.getValue() > 0;
this.next.active = this.amountToCraft.getIntValue().orElse(0) > 0;
this.amountToCraft.render(matrices, offsetX, offsetY, partialTicks);
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int p_keyPressed_3_) {
if (keyCode == 28) {
this.next.onPress();
return true;
} else {
return super.keyPressed(keyCode, scanCode, p_keyPressed_3_);
}
}
protected String getBackground() {
return "guis/craftAmt.png";
}
}
@@ -25,6 +25,8 @@ import java.util.List;
import com.mojang.blaze3d.systems.RenderSystem;
import org.lwjgl.glfw.GLFW;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
@@ -73,10 +75,6 @@ public class CraftConfirmScreen extends AEBaseScreen<CraftConfirmContainer> {
this.setScrollBar(scrollbar);
}
boolean isAutoStart() {
return this.handler.isAutoStart();
}
@Override
public void init() {
super.init();
@@ -87,12 +85,14 @@ public class CraftConfirmScreen extends AEBaseScreen<CraftConfirmContainer> {
this.addButton(this.start);
this.selectCPU = new ButtonWidget(this.x + (219 - 180) / 2, this.y + this.backgroundHeight - 68, 180, 20,
GuiText.CraftingCPU.withSuffix(": ").append(GuiText.Automatic.text()), btn -> selectNextCpu());
getNextCpuButtonLabel(), btn -> selectNextCpu());
this.selectCPU.active = false;
this.addButton(this.selectCPU);
addButton(new ButtonWidget(this.x + 6, this.y + this.backgroundHeight - 25, 50, 20, GuiText.Cancel.text(),
btn -> subGui.goBack()));
this.setScrollBar();
}
@Override
@@ -133,22 +133,22 @@ public class CraftConfirmScreen extends AEBaseScreen<CraftConfirmContainer> {
}
private void updateCPUButtonText() {
Text btnTextText = GuiText.CraftingCPU.withSuffix(": ").append(GuiText.Automatic.text());
if (this.handler.getSelectedCpu() >= 0)// && status.selectedCpu < status.cpus.size() )
{
if (this.handler.getName() != null) {
final String name = this.handler.getName().asTruncatedString(20);
btnTextText = GuiText.CraftingCPU.withSuffix(": " + name);
} else {
btnTextText = GuiText.CraftingCPU.withSuffix(": #" + this.handler.getSelectedCpu());
}
}
this.selectCPU.setMessage(getNextCpuButtonLabel());
}
private Text getNextCpuButtonLabel() {
if (this.handler.hasNoCPU()) {
btnTextText = GuiText.NoCraftingCPUs.text();
return GuiText.NoCraftingCPUs.text();
}
this.selectCPU.setMessage(btnTextText);
Text cpuName;
if (this.handler.cpuName == null) {
cpuName = GuiText.Automatic.text();
} else {
cpuName = this.handler.cpuName;
}
return GuiText.CraftingCPU.withSuffix(": ").append(cpuName);
}
private boolean isSimulation() {
@@ -440,7 +440,7 @@ public class CraftConfirmScreen extends AEBaseScreen<CraftConfirmContainer> {
@Override
public boolean keyPressed(int keyCode, int scanCode, int p_keyPressed_3_) {
if (!this.checkHotbarKeys(keyCode, scanCode)) {
if (keyCode == 28) {
if (keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_KP_ENTER) {
this.start();
return true;
}
@@ -449,7 +449,7 @@ public class CraftConfirmScreen extends AEBaseScreen<CraftConfirmContainer> {
}
private void selectNextCpu() {
final boolean backwards = getClient().mouse.wasRightButtonClicked();
final boolean backwards = isHandlingRightClick();
NetworkHandler.instance().sendToServer(new ConfigValuePacket("Terminal.Cpu", backwards ? "Prev" : "Next"));
}
@@ -44,12 +44,12 @@ public class CraftingStatusScreen extends CraftingCPUScreen<CraftingStatusContai
super.init();
this.selectCPU = new ButtonWidget(this.x + 8, this.y + this.backgroundHeight - 25, 150, 20,
GuiText.CraftingCPU.withSuffix(": ").append(GuiText.NoCraftingCPUs.text()), btn -> selectNextCpu());
getNextCpuButtonLabel(), btn -> selectNextCpu());
this.addButton(this.selectCPU);
subGui.addBackButton(btn -> {
addButton(btn);
btn.setHideEdge(13);
btn.setHideEdge(true);
}, 213, -4);
}
@@ -60,23 +60,14 @@ public class CraftingStatusScreen extends CraftingCPUScreen<CraftingStatusContai
}
private void updateCPUButtonText() {
Text btnTextText = GuiText.NoCraftingJobs.text();
if (this.handler.selectedCpu >= 0)// && status.selectedCpu < status.cpus.size() )
{
if (this.handler.myName != null) {
final String name = this.handler.myName.asTruncatedString(20);
btnTextText = GuiText.CPUs.withSuffix(": " + name);
} else {
btnTextText = GuiText.CPUs.withSuffix(": #" + this.handler.selectedCpu);
}
}
this.selectCPU.setMessage(getNextCpuButtonLabel());
}
private Text getNextCpuButtonLabel() {
if (this.handler.noCPU) {
btnTextText = GuiText.NoCraftingJobs.text();
return GuiText.NoCraftingJobs.text();
}
this.selectCPU.setMessage(btnTextText);
return GuiText.CraftingCPU.withSuffix(": ").append(handler.cpuName);
}
@Override
@@ -84,9 +75,8 @@ public class CraftingStatusScreen extends CraftingCPUScreen<CraftingStatusContai
return in; // the cup name is on the button
}
// FIXME: Extract to separate class? Shared with GuiCraftConfirm
private void selectNextCpu() {
final boolean backwards = client.mouse.wasRightButtonClicked();
final boolean backwards = isHandlingRightClick();
NetworkHandler.instance().sendToServer(new ConfigValuePacket("Terminal.Cpu", backwards ? "Prev" : "Next"));
}
@@ -87,7 +87,7 @@ public class InterfaceScreen extends UpgradeableScreen<InterfaceContainer> {
}
private void selectNextInterfaceMode() {
final boolean backwards = getClient().mouse.wasRightButtonClicked();
final boolean backwards = isHandlingRightClick();
NetworkHandler.instance().sendToServer(new ConfigButtonPacket(Settings.INTERFACE_TERMINAL, backwards));
}
@@ -70,8 +70,7 @@ public class InterfaceTerminalScreen extends AEBaseScreen<InterfaceTerminalConta
public InterfaceTerminalScreen(InterfaceTerminalContainer container, PlayerInventory playerInventory, Text title) {
super(container, playerInventory, title);
final Scrollbar scrollbar = new Scrollbar();
this.setScrollBar(scrollbar);
this.setScrollBar(new Scrollbar().setLeft(175).setTop(18).setHeight(106));
this.backgroundWidth = 195;
this.backgroundHeight = 222;
}
@@ -80,16 +79,14 @@ public class InterfaceTerminalScreen extends AEBaseScreen<InterfaceTerminalConta
public void init() {
super.init();
this.getScrollBar().setLeft(175);
this.getScrollBar().setHeight(106);
this.getScrollBar().setTop(18);
this.searchField = new AETextField(this.textRenderer, this.x + 104, this.y + 4, 65, 12);
this.searchField.setHasBorder(false);
this.searchField.setMaxLength(25);
this.searchField.setEditableColor(0xFFFFFF);
this.searchField.setVisible(true);
this.searchField.setFocused(true);
this.searchField.setChangedListener(str -> this.refreshList());
this.addChild(this.searchField);
this.changeFocus(true);
}
@Override
@@ -128,11 +125,8 @@ public class InterfaceTerminalScreen extends AEBaseScreen<InterfaceTerminalConta
@Override
public boolean mouseClicked(final double xCoord, final double yCoord, final int btn) {
if (this.searchField.mouseClicked(xCoord, yCoord, btn)) {
if (btn == 1 && this.searchField.isMouseOver(xCoord, yCoord)) {
this.searchField.setText("");
this.refreshList();
}
if (btn == 1 && this.searchField.isMouseOver(xCoord, yCoord)) {
this.searchField.setText("");
return true;
}
@@ -170,11 +164,7 @@ public class InterfaceTerminalScreen extends AEBaseScreen<InterfaceTerminalConta
if (character == ' ' && this.searchField.getText().isEmpty()) {
return true;
}
if (this.searchField.charTyped(character, key)) {
this.refreshList();
return true;
}
return false;
return super.charTyped(character, key);
}
@Override
@@ -34,8 +34,6 @@ import appeng.client.gui.widgets.ServerSettingToggleButton;
import appeng.client.gui.widgets.SettingToggleButton;
import appeng.container.implementations.LevelEmitterContainer;
import appeng.core.localization.GuiText;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ConfigValuePacket;
public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer> {
@@ -51,15 +49,18 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
public void init() {
super.init();
this.level = new NumberEntryWidget(this, 20, 17, 138, 62, NumberEntryType.LEVEL_ITEM_COUNT,
this::onLevelChange);
this.level = new NumberEntryWidget(this, 20, 17, 138, 62, NumberEntryType.LEVEL_ITEM_COUNT);
this.level.setTextFieldBounds(25, 44, 75);
this.level.addButtons(children::add, this::addButton);
handler.setTextField(this.level);
this.level.setValue(handler.getReportingValue());
this.level.setOnChange(this::saveReportingValue);
this.level.setOnConfirm(this::onClose);
this.changeFocus(true);
}
private void onLevelChange(long level) {
NetworkHandler.instance().sendToServer(new ConfigValuePacket("LevelEmitter.Value", String.valueOf(level)));
private void saveReportingValue() {
this.level.getLongValue().ifPresent(handler::setReportingValue);
}
@Override
@@ -26,8 +26,11 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import me.shedaniel.math.Rectangle;
import appeng.api.config.SearchBoxMode;
import appeng.api.config.Settings;
import appeng.api.config.SortDir;
@@ -49,6 +52,7 @@ import appeng.client.gui.widgets.SettingToggleButton;
import appeng.client.gui.widgets.TabButton;
import appeng.client.me.InternalSlotME;
import appeng.client.me.ItemRepo;
import appeng.client.render.StackSizeRenderer;
import appeng.container.implementations.CraftingStatusContainer;
import appeng.container.implementations.MEMonitorableContainer;
import appeng.container.slot.AppEngSlot;
@@ -235,7 +239,7 @@ public class MEMonitorableScreen<T extends MEMonitorableContainer> extends AEBas
if (this.viewCell || this instanceof WirelessTermScreen) {
this.craftingStatusBtn = this.addButton(new TabButton(this.x + 170, this.y - 4, 2 + 11 * 16,
GuiText.CraftingStatus.text(), this.itemRenderer, btn -> showCraftingStatus()));
this.craftingStatusBtn.setHideEdge(13);
this.craftingStatusBtn.setHideEdge(true);
}
this.isAutoFocus = SearchBoxMode.AUTOSEARCH == searchMode || SearchBoxMode.JEI_AUTOSEARCH == searchMode
@@ -281,6 +285,8 @@ public class MEMonitorableScreen<T extends MEMonitorableContainer> extends AEBas
craftingGridOffsetX -= 25;
craftingGridOffsetY -= 6;
this.setScrollBar();
}
@Override
@@ -290,6 +296,16 @@ public class MEMonitorableScreen<T extends MEMonitorableContainer> extends AEBas
this.currentMouseX = mouseX;
this.currentMouseY = mouseY;
// Show the number of active crafting jobs
if (this.craftingStatusBtn != null && handler.activeCraftingJobs != -1) {
// The stack size renderer expects a 16x16 slot, while the button is normally
// bigger
int x = this.craftingStatusBtn.x + (this.craftingStatusBtn.getWidth() - 16) / 2;
int y = this.craftingStatusBtn.y + (this.craftingStatusBtn.getHeight() - 16) / 2;
StackSizeRenderer.renderSizeLabel(textRenderer, x - this.x, y - this.y,
new LiteralText(String.valueOf(handler.activeCraftingJobs)));
}
}
@Override
@@ -354,6 +370,7 @@ public class MEMonitorableScreen<T extends MEMonitorableContainer> extends AEBas
if (this.searchField != null) {
this.searchField.render(matrices, mouseX, mouseY, partialTicks);
}
}
protected String getBackground() {
@@ -519,4 +536,14 @@ public class MEMonitorableScreen<T extends MEMonitorableContainer> extends AEBas
this.init();
}
@Override
public List<Rectangle> getExclusionZones() {
List<Rectangle> zones = super.getExclusionZones();
// Button toolbar on the left
zones.add(new Rectangle(x - 18, y + 8, 18, 160));
// View-cells on the right
zones.add(new Rectangle(x + 197, y, 46, 128));
return zones;
}
}
@@ -2,41 +2,58 @@ package appeng.client.gui.implementations;
import java.util.ArrayList;
import java.util.List;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.function.Consumer;
import java.util.function.LongConsumer;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.NumberEntryType;
import appeng.client.gui.widgets.ITickingWidget;
import appeng.client.gui.widgets.NumberBox;
import appeng.client.gui.widgets.ConfirmableTextField;
import appeng.client.gui.widgets.ValidationIcon;
import appeng.core.AEConfig;
/**
* A utility widget that consists of a text-field to enter a number with
* attached buttons to increment/decrement the number in fixed intervals.
*/
public class NumberEntryWidget implements ITickingWidget {
public class NumberEntryWidget extends DrawableHelper {
private static final Text INVALID_NUMBER = new TranslatableText("gui.appliedenergistics2.validation.InvalidNumber");
private static final String NUMBER_LESS_THAN_MIN_VALUE = "gui.appliedenergistics2.validation.NumberLessThanMinValue";
private static final Text PLUS = Text.of("+");
private static final Text MINUS = Text.of("-");
private static final int TEXT_COLOR_ERROR = 0xFF1900;
private static final int TEXT_COLOR_NORMAL = 0xFFFFFF;
private final AEBaseScreen<?> parent;
private final int x;
private final int y;
private final NumberBox level;
private final ConfirmableTextField textField;
private final NumberEntryType type;
private List<ButtonWidget> buttons;
private long minValue;
private ValidationIcon validationIcon;
public NumberEntryWidget(AEBaseScreen<?> parent, int x, int y, int width, int height, NumberEntryType type,
LongConsumer changeListener) {
// Called when the value changes
private Runnable onChange;
// Called when the user presses enter while there's a valid number in the field
private Runnable onConfirm;
private boolean hideValidationIcon;
public NumberEntryWidget(AEBaseScreen<?> parent, int x, int y, int width, int height, NumberEntryType type) {
this.parent = parent;
this.x = x;
this.y = y;
@@ -45,27 +62,50 @@ public class NumberEntryWidget implements ITickingWidget {
TextRenderer font = parent.getClient().textRenderer;
int inputX = parent.getX() + x;
int inputY = parent.getY() + y;
this.level = new NumberBox(font, inputX, inputY, width, font.fontHeight, type.getInputType(), changeListener);
this.level.setHasBorder(false);
this.level.setMaxLength(16);
this.level.setEditableColor(0xFFFFFF);
this.level.setVisible(true);
parent.setInitialFocus(this.level);
this.textField = new ConfirmableTextField(font, inputX, inputY, width, font.fontHeight, LiteralText.EMPTY);
this.textField.setHasBorder(false);
this.textField.setMaxLength(16);
this.textField.setEditableColor(TEXT_COLOR_NORMAL);
this.textField.setVisible(true);
this.textField.setSelected(true);
parent.setInitialFocus(this.textField);
this.textField.setChangedListener(text -> {
validate();
if (onChange != null) {
this.onChange.run();
}
});
this.textField.setOnConfirm(() -> {
// Only confirm if it's actually valid
if (this.onConfirm != null && getLongValue().isPresent()) {
this.onConfirm.run();
}
});
validate();
}
public void setOnConfirm(Runnable callback) {
this.onConfirm = callback;
}
public void setOnChange(Runnable callback) {
this.onChange = callback;
}
public void setActive(boolean active) {
this.level.active = active;
this.textField.active = active;
this.buttons.forEach(b -> b.active = active);
}
public void setTextFieldBounds(int x, int y, int width) {
this.level.x = parent.getX() + x;
this.level.y = parent.getY() + y;
this.level.setWidth(width);
this.textField.x = parent.getX() + x;
this.textField.y = parent.getY() + y;
this.textField.setWidth(width);
}
public void setMinValue(long minValue) {
this.level.setMinValue(minValue);
this.minValue = minValue;
validate();
}
public void addButtons(Consumer<Element> addChildren, Consumer<ButtonWidget> addButton) {
@@ -78,54 +118,116 @@ public class NumberEntryWidget implements ITickingWidget {
int left = parent.getX() + x;
int top = parent.getY() + y;
List<ButtonWidget> buttons = new ArrayList<>(8);
List<ButtonWidget> buttons = new ArrayList<>(9);
buttons.add(new ButtonWidget(left, top, 22, 20, makeLabel(PLUS, a), btn -> addQty(a)));
buttons.add(new ButtonWidget(left + 28, top, 28, 20, makeLabel(PLUS, b), btn -> addQty(b)));
buttons.add(new ButtonWidget(left + 62, top, 32, 20, makeLabel(PLUS, c), btn -> addQty(c)));
buttons.add(new ButtonWidget(left + 100, top, 38, 20, makeLabel(PLUS, d), btn -> addQty(d)));
// Need to add these now for sensible tab-order
buttons.forEach(addButton);
// Placing this here will give a sensible tab order
addChildren.accept(this.level);
addChildren.accept(this.textField);
buttons.add(new ButtonWidget(left, top + 42, 22, 20, makeLabel(MINUS, a), btn -> addQty(-a)));
buttons.add(new ButtonWidget(left + 28, top + 42, 28, 20, makeLabel(MINUS, b), btn -> addQty(-b)));
buttons.add(new ButtonWidget(left + 62, top + 42, 32, 20, makeLabel(MINUS, c), btn -> addQty(-c)));
buttons.add(new ButtonWidget(left + 100, top + 42, 38, 20, makeLabel(MINUS, d), btn -> addQty(-d)));
// This element is not focusable
if (!hideValidationIcon) {
this.validationIcon = new ValidationIcon(left + 104, top + 27);
buttons.add(this.validationIcon);
}
// Add the rest to the tab order
buttons.subList(4, buttons.size()).forEach(addButton);
this.buttons = buttons;
this.buttons.forEach(addButton);
// we need to re-validate because the icon may now be present and needs it's
// initial state
this.validate();
}
private void addQty(final long i) {
long currentValue = this.level.getValue();
long minValue = this.level.getMinValue();
this.level.setText(String.valueOf(Math.max(minValue, currentValue + i)));
/**
* Returns the integer value currently in the text-field, if it is a valid
* number and is within the allowed min/max value.
*/
public OptionalInt getIntValue() {
String text = textField.getText().trim();
try {
int value = Integer.parseInt(text, 10);
if (value < minValue) {
return OptionalInt.empty();
}
return OptionalInt.of(value);
} catch (NumberFormatException ignored) {
return OptionalInt.empty();
}
}
public void render(MatrixStack matrices, int mouseX, int mouseY, float partialTicks) {
this.level.render(matrices, mouseX, mouseY, partialTicks);
}
public void setValue(long value, boolean skipNotify) {
this.level.setValue(value, skipNotify);
/**
* Returns the long value currently in the text-field, if it is a valid number
* and is within the allowed min/max value.
*/
public OptionalLong getLongValue() {
String text = textField.getText().trim();
try {
long value = Long.parseLong(text, 10);
if (value < minValue) {
return OptionalLong.empty();
}
return OptionalLong.of(value);
} catch (NumberFormatException ignored) {
return OptionalLong.empty();
}
}
public void setValue(long value) {
setValue(value, false);
this.textField.setText(String.valueOf(Math.max(minValue, value)));
this.textField.setCursorToEnd();
this.textField.setSelectionStart(0);
validate();
}
public long getValue() {
return level.getValue();
private void addQty(final long i) {
getLongValue().ifPresent(currentValue -> setValue(currentValue + i));
}
@Override
public void tick() {
this.level.tick();
public void render(MatrixStack matrices, int mouseX, int mouseY, float partialTicks) {
this.textField.render(matrices, mouseX, mouseY, partialTicks);
}
private void validate() {
List<Text> validationErrors = new ArrayList<>();
String text = textField.getText().trim();
try {
long value = Long.parseLong(text, 10);
if (value < minValue) {
validationErrors.add(new TranslatableText(NUMBER_LESS_THAN_MIN_VALUE, minValue));
}
} catch (NumberFormatException ignored) {
validationErrors.add(INVALID_NUMBER);
}
boolean valid = validationErrors.isEmpty();
this.textField.setEditableColor(valid ? TEXT_COLOR_NORMAL : TEXT_COLOR_ERROR);
if (this.validationIcon != null) {
this.validationIcon.setValid(valid);
this.validationIcon.setTooltip(validationErrors);
}
}
private Text makeLabel(Text prefix, int amount) {
return prefix.copy().append(String.valueOf(amount));
}
public void setHideValidationIcon(boolean hideValidationIcon) {
this.hideValidationIcon = hideValidationIcon;
}
}
@@ -18,6 +18,8 @@
package appeng.client.gui.implementations;
import java.util.OptionalInt;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.text.Text;
@@ -26,8 +28,6 @@ import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.NumberEntryType;
import appeng.container.implementations.PriorityContainer;
import appeng.core.localization.GuiText;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ConfigValuePacket;
public class PriorityScreen extends AEBaseScreen<PriorityContainer> {
@@ -38,24 +38,38 @@ public class PriorityScreen extends AEBaseScreen<PriorityContainer> {
public PriorityScreen(PriorityContainer container, PlayerInventory playerInventory, Text title) {
super(container, playerInventory, title);
this.subGui = new AESubScreen(this, container.getPriorityHost());
// This is the effective size of the background image
backgroundWidth = 175;
backgroundHeight = 128;
}
@Override
public void init() {
super.init();
this.priority = new NumberEntryWidget(this, 20, 30, 138, 62, NumberEntryType.PRIORITY, this::onPriorityChange);
this.priority = new NumberEntryWidget(this, 20, 30, 138, 62, NumberEntryType.PRIORITY);
this.priority.setTextFieldBounds(62, 57, 50);
this.priority.setMinValue(Integer.MIN_VALUE);
handler.setTextField(this.priority);
this.priority.setValue(this.handler.getPriorityValue());
this.priority.addButtons(children::add, this::addButton);
this.subGui.addBackButton(this::addButton, 154, 0);
this.priority.setOnChange(this::savePriority);
this.priority.setOnConfirm(() -> {
savePriority();
this.subGui.goBack();
});
changeFocus(true);
}
private void onPriorityChange(long priority) {
NetworkHandler.instance()
.sendToServer(new ConfigValuePacket("PriorityHost.Priority", String.valueOf(priority)));
private void savePriority() {
OptionalInt priority = this.priority.getIntValue();
if (priority.isPresent()) {
handler.setPriority(priority.getAsInt());
}
}
@Override
@@ -66,13 +80,10 @@ public class PriorityScreen extends AEBaseScreen<PriorityContainer> {
@Override
public void drawBG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY,
float partialTicks) {
this.bindTexture(getBackground());
this.bindTexture("guis/priority.png");
drawTexture(matrices, offsetX, offsetY, 0, 0, this.backgroundWidth, this.backgroundHeight);
this.priority.render(matrices, mouseX, mouseY, partialTicks);
}
protected String getBackground() {
return "guis/priority.png";
}
}
@@ -18,10 +18,14 @@
package appeng.client.gui.implementations;
import java.util.List;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.text.Text;
import me.shedaniel.math.Rectangle;
import appeng.api.config.FuzzyMode;
import appeng.api.config.RedstoneMode;
import appeng.api.config.SchedulingMode;
@@ -146,4 +150,11 @@ public class UpgradeableScreen<T extends UpgradeableContainer> extends AEBaseScr
return this.bc instanceof ImportBusPart ? GuiText.ImportBus : GuiText.ExportBus;
}
@Override
public List<Rectangle> getExclusionZones() {
List<Rectangle> zones = super.getExclusionZones();
zones.add(new Rectangle(x - 18, y + 8, 18, 60));
return zones;
}
}
@@ -48,9 +48,9 @@ public class WirelessScreen extends AEBaseScreen<WirelessContainer> {
this.textRenderer.draw(matrices, GuiText.inventory.text(), 8, this.backgroundHeight - 96 + 3, 4210752);
if (handler.getRange() > 0) {
final String firstMessage = GuiText.Range.text() + ": " + (handler.getRange() / 10.0) + " m";
final String secondMessage = GuiText.PowerUsageRate.text() + ": "
+ Platform.formatPowerLong(handler.getDrain(), true);
final Text firstMessage = GuiText.Range.withSuffix(": " + (handler.getRange() / 10.0) + " m");
final Text secondMessage = GuiText.PowerUsageRate
.withSuffix(": " + Platform.formatPowerLong(handler.getDrain(), true));
final int strWidth = Math.max(this.textRenderer.getWidth(firstMessage),
this.textRenderer.getWidth(secondMessage));
@@ -0,0 +1,51 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
import org.lwjgl.glfw.GLFW;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.text.Text;
public class ConfirmableTextField extends TextFieldWidget {
private Runnable onConfirm;
public ConfirmableTextField(TextRenderer fontRenderer, int x, int y, int width, int height, Text text) {
super(fontRenderer, x, y, width, height, text);
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
if (isActive() && (keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_KP_ENTER)) {
if (this.onConfirm != null) {
this.onConfirm.run();
}
return true;
}
return super.keyPressed(keyCode, scanCode, modifiers);
}
public void setOnConfirm(Runnable onConfirm) {
this.onConfirm = onConfirm;
}
}
@@ -0,0 +1,96 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
import java.time.Duration;
/**
* This class can be used to implement repeating events such as holding down a
* button to fire an event repeatedly while the button is still being held, or
* repeatedly scrolling down a page, while the mouse is held down on the
* scrollbar.
*/
public class EventRepeater {
/**
* -1 if no repeat event is scheduled. Otherwise contains the
* {@link System#nanoTime()} at which the next event should occur.
*/
private long nextEventTime = -1;
private EventCallback eventCallback = null;
private final long eventDelay; // In nanoseconds
private final long eventInterval; // In nanoseconds
public EventRepeater(Duration delay, Duration interval) {
this.eventDelay = delay.toNanos();
this.eventInterval = interval.toNanos();
}
public void tick() {
if (this.eventCallback == null) {
return; // No event scheduled
}
// Use nanoTime here because it is monotonically increasing, while
// System.currentTimeMillis is not
long nanoTime = System.nanoTime();
if (nanoTime < this.nextEventTime) {
return; // Event time not reached
}
// Before triggering, recompute the next event, since
// the event callback itself may reschedule/cancel, and
// we should not overwrite that
this.nextEventTime = nanoTime + this.eventInterval;
this.eventCallback.trigger();
}
/**
* Schedule the given callback to be called after a given initial delay, and
* then after the given interval repeatedly.
*
* <p>
* Replaces any previously queued callback.
*/
public void repeat(EventCallback callback) {
long time = System.nanoTime();
this.eventCallback = callback;
this.nextEventTime = time + eventDelay;
}
public boolean isRepeating() {
return this.eventCallback != null;
}
/**
* Stop repeating the event.
*/
public void stop() {
this.eventCallback = null;
}
@FunctionalInterface
public interface EventCallback {
void trigger();
}
}
@@ -22,6 +22,7 @@ import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.sound.SoundManager;
import net.minecraft.client.texture.TextureManager;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
@@ -33,6 +34,10 @@ public abstract class IconButton extends ButtonWidget implements ITooltip {
private boolean halfSize = false;
private boolean disableClickSound = false;
private boolean disableBackground = false;
public IconButton(final int x, final int y, PressAction onPress) {
super(x, y, 16, 16, LiteralText.EMPTY, onPress);
}
@@ -42,6 +47,13 @@ public abstract class IconButton extends ButtonWidget implements ITooltip {
this.active = vis;
}
@Override
public void playDownSound(SoundManager soundManager) {
if (!disableClickSound) {
super.playDownSound(soundManager);
}
}
@Override
public void renderButton(MatrixStack matrices, final int mouseX, final int mouseY, float partial) {
@@ -72,7 +84,9 @@ public abstract class IconButton extends ButtonWidget implements ITooltip {
final int uv_y = iconIndex / 16;
final int uv_x = iconIndex - uv_y * 16;
drawTexture(matrices, 0, 0, 256 - 16, 256 - 16, 16, 16);
if (!disableBackground) {
drawTexture(matrices, 0, 0, 256 - 16, 256 - 16, 16, 16);
}
drawTexture(matrices, 0, 0, uv_x * 16, uv_y * 16, 16, 16);
RenderSystem.popMatrix();
} else {
@@ -85,12 +99,18 @@ public abstract class IconButton extends ButtonWidget implements ITooltip {
final int uv_y = iconIndex / 16;
final int uv_x = iconIndex - uv_y * 16;
drawTexture(matrices, this.x, this.y, 256 - 16, 256 - 16, 16, 16);
if (!disableBackground) {
drawTexture(matrices, this.x, this.y, 256 - 16, 256 - 16, 16, 16);
}
drawTexture(matrices, this.x, this.y, uv_x * 16, uv_y * 16, 16, 16);
}
RenderSystem.enableDepthTest();
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
if (isHovered()) {
renderToolTip(matrices, mouseX, mouseY);
}
}
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
}
protected abstract int getIconIndex();
@@ -133,4 +153,20 @@ public abstract class IconButton extends ButtonWidget implements ITooltip {
this.halfSize = halfSize;
}
public boolean isDisableClickSound() {
return disableClickSound;
}
public void setDisableClickSound(boolean disableClickSound) {
this.disableClickSound = disableClickSound;
}
public boolean isDisableBackground() {
return disableBackground;
}
public void setDisableBackground(boolean disableBackground) {
this.disableBackground = disableBackground;
}
}
@@ -1,153 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
import java.util.function.LongConsumer;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.text.LiteralText;
public class NumberBox extends TextFieldWidget {
private final LongConsumer changeListener;
private long lastValue;
private long minValue = 0;
private long maxValue;
public NumberBox(final TextRenderer fontRenderer, final int x, final int y, final int width, final int height,
final Class<?> type, LongConsumer changeListener) {
super(fontRenderer, x, y, width, height, new LiteralText("0"));
this.setText("0");
setChangedListener(this::handleTextChanged);
this.lastValue = 0;
this.changeListener = changeListener;
if (type == int.class || type == Integer.class) {
maxValue = Integer.MAX_VALUE;
} else {
maxValue = Long.MAX_VALUE;
}
}
// NOTE: This method MUST NOT BE NAMED like a method in the superclass because
// of a ForgeGradle remapping bug
// since it'll not remap this method's name, but it will remap the name of the
// method reference above.
private void handleTextChanged(String text) {
if (text.isEmpty()) {
setText("0"); // Will call onTextChanged recursively
return;
}
boolean canBeNegative = canBeNegative();
if (canBeNegative && text.equals("-")) {
// Allow this as a special case to make typing in a negative number easier
return;
}
StringBuilder sanitized = new StringBuilder(text);
boolean encounteredNonZero = false;
for (int i = 0; i < sanitized.length(); i++) {
char ch = sanitized.charAt(i);
if (canBeNegative && i == 0 && ch == '-') {
continue; // Allow leading minus sign
}
if (ch >= '1' && ch <= '9') {
encounteredNonZero = true;
continue;
}
if (ch != '0' || !encounteredNonZero) {
sanitized.deleteCharAt(i--);
}
}
if (sanitized.length() == 0) {
sanitized.append('0');
}
String sanitizedStr = sanitized.toString();
if (!sanitizedStr.equals(text)) {
setText(sanitizedStr); // Will call onTextChanged recursively
return;
}
if (getValue() < minValue) {
setText(String.valueOf(minValue)); // Will call onTextChanged recursively
return;
}
if (getValue() > maxValue) {
setText(String.valueOf(maxValue)); // Will call onTextChanged recursively
return;
}
reportChange();
}
private void reportChange() {
long value = getValue();
if (value != lastValue) {
lastValue = value;
changeListener.accept(value);
}
}
public void setValue(long value, boolean skipNotify) {
// This check avoid changing the cursor position needlessly
if (value == this.getValue()) {
return;
}
if (skipNotify) {
lastValue = value;
}
setText(String.valueOf(value));
}
public long getValue() {
if (getText().equals("-") && canBeNegative()) {
return lastValue; // Allow this as a special case to type in a negative number more easily
}
return Long.parseLong(getText());
}
@Override
public boolean keyPressed(int p_keyPressed_1_, int p_keyPressed_2_, int p_keyPressed_3_) {
if (super.keyPressed(p_keyPressed_1_, p_keyPressed_2_, p_keyPressed_3_)) {
return true;
}
// Swallow key presses for numbers because they would otherwise trigger the
// hotbar swapping unintentionally
return isFocused() && p_keyPressed_1_ >= '0' && p_keyPressed_1_ <= '9';
}
public void setMinValue(long minValue) {
this.minValue = minValue;
}
public long getMinValue() {
return minValue;
}
private boolean canBeNegative() {
return minValue < 0;
}
}
@@ -18,18 +18,74 @@
package appeng.client.gui.widgets;
import com.mojang.blaze3d.systems.RenderSystem;
import java.time.Duration;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.util.Rect2i;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import appeng.client.gui.AEBaseScreen;
public class Scrollbar implements IScrollSource {
/**
* Implements a vertical scrollbar using Vanilla's scrollbar handle texture from
* the creative tab.
* <p>
* It is expected that the background of the UI contains a pre-baked scrollbar
* track border, and that the exact rectangle of that track is set on this
* object via {@link #setLeft(int)}, {@link #setTop(int)} and
* {@link #setHeight(int)}. While the width of the track can also be set, the
* drawn handle will use vanilla's sprite width (see {@link #HANDLE_WIDTH}.
*/
public class Scrollbar extends DrawableHelper implements IScrollSource {
/**
* Width of the scrollbar handle sprite in the source texture.
*/
private static final int HANDLE_WIDTH = 12;
/**
* Height of the scrollbar handle sprite in the source texture.
*/
private static final int HANDLE_HEIGHT = 15;
/**
* Texture containing the scrollbar handle sprites.
*/
private static final Identifier TEXTURE = new Identifier("minecraft",
"textures/gui/container/creative_inventory/tabs.png");
/**
* Rectangle in the source texture that contains the sprite for an enabled
* handle.
*/
private static final Rect2i ENABLED = new Rect2i(232, 0, HANDLE_WIDTH, HANDLE_HEIGHT);
/**
* Rectangle in the source texture that contains the sprite for a disabled
* handle.
*/
private static final Rect2i DISABLED = new Rect2i(232 + HANDLE_WIDTH, 0, HANDLE_WIDTH, HANDLE_HEIGHT);
/**
* The screen x-coordinate of the scrollbar's inner track.
*/
private int displayX = 0;
/**
* The screen y-coordinate of the scrollbar's inner track.
*/
private int displayY = 0;
private int width = 12;
/**
* The inner width of the scrollbar track.
*/
private int width = HANDLE_WIDTH;
/**
* The inner height of the scrollbar track.
*/
private int height = 16;
private int pageSize = 1;
@@ -37,20 +93,58 @@ public class Scrollbar implements IScrollSource {
private int minScroll = 0;
private int currentScroll = 0;
private final DrawableHelper drawable = new DrawableHelper() {
};
/**
* True if the scrollbar's handle is currently being dragged.
*/
private boolean dragging;
/**
* The y-coordinate relative to the upper edge of the scrollbar handle, where
* the user pressed the mouse button to drag. While dragging, this is applied as
* an offset to the effective scrollbar position.
*/
private int dragYOffset;
private final EventRepeater eventRepeater = new EventRepeater(Duration.ofMillis(250), Duration.ofMillis(150));
/**
* Draws the handle of the scrollbar.
* <p>
* The GUI is assumed to already contain a prebaked scrollbar track in its
* background.
*/
public void draw(MatrixStack matrices, final AEBaseScreen<?> g) {
g.bindTexture("minecraft", "gui/container/creative_inventory/tabs.png");
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
setZOffset(g.getZOffset());
drawable.setZOffset(g.getZOffset());
// Draw the track (nice for debugging)
// fill(matrices, displayX, displayY, this.displayX + width, this.displayY +
// height, 0xffff0000);
g.bindTexture(TEXTURE);
int yOffset;
Rect2i sourceRect;
if (this.getRange() == 0) {
drawable.drawTexture(matrices, this.displayX, this.displayY, 232 + this.width, 0, this.width, 15);
yOffset = 0;
sourceRect = DISABLED;
} else {
final int offset = (this.currentScroll - this.minScroll) * (this.height - 15) / this.getRange();
drawable.drawTexture(matrices, this.displayX, offset + this.displayY, 232, 0, this.width, 15);
yOffset = getHandleYOffset();
sourceRect = ENABLED;
}
drawTexture(matrices, this.displayX, this.displayY + yOffset, sourceRect.getX(), sourceRect.getY(),
sourceRect.getWidth(), sourceRect.getHeight());
}
/**
* Returns the y-position of the scrollbar handle in relation to the upper edge
* of the scrollbar's track.
*/
private int getHandleYOffset() {
if (getRange() == 0) {
return 0;
}
int availableHeight = this.height - HANDLE_HEIGHT;
return (this.currentScroll - this.minScroll) * availableHeight / this.getRange();
}
private int getRange() {
@@ -114,24 +208,96 @@ public class Scrollbar implements IScrollSource {
return this.currentScroll;
}
public void click(final double x, final double y) {
if (this.getRange() == 0) {
public boolean mouseDown(double x, double y) {
this.dragging = false;
// Clicks to the left or right of the scrollbar don't do anything
if (x < displayX || x >= displayX + width) {
return false;
}
// Clicks to the top or bottom don't do anything either
int relY = (int) Math.round(y - displayY);
if (relY < 0 || relY >= height) {
return false;
}
// Do nothing when there's no range, but swallow the event
if (getRange() == 0) {
return true;
}
int handleYOffset = getHandleYOffset();
if (relY < handleYOffset) {
// Clicks above the handle will page up, repeatedly
pageUp();
eventRepeater.repeat(this::pageUp);
} else if (relY < handleYOffset + HANDLE_HEIGHT) {
// Clicks on the handle will initiate dragging it
this.dragging = true;
this.dragYOffset = relY - handleYOffset;
} else {
// Clicks below the handle will page down, repeatedly
pageDown();
eventRepeater.repeat(this::pageDown);
}
return true;
}
public boolean mouseUp(double x, double y) {
this.dragging = false;
this.eventRepeater.stop();
return false;
}
public void mouseDragged(double x, double y) {
if (this.getRange() == 0 || !this.dragging || this.eventRepeater.isRepeating()) {
return;
}
if (x > this.displayX && x <= this.displayX + this.width) {
if (y > this.displayY && y <= this.displayY + this.height) {
this.currentScroll = (int) (y - this.displayY);
this.currentScroll = this.minScroll + ((this.currentScroll * 2 * this.getRange() / this.height));
this.currentScroll = (this.currentScroll + 1) >> 1;
this.applyRange();
}
}
// Compute the position of the mouse (adjusted for where it grabbed the handle,
// so as if it grabbed
// the upper edge of it) within the scrollable area of the track (minus the
// handle height).
double handleUpperEdgeY = y - this.displayY - this.dragYOffset;
double availableHeight = this.height - HANDLE_HEIGHT;
double position = MathHelper.clamp(handleUpperEdgeY / availableHeight, 0.0, 1.0);
this.currentScroll = this.minScroll + (int) Math.round(position * this.getRange());
this.applyRange();
}
public void wheel(double delta) {
// Do nothing when there's no range
if (getRange() == 0) {
return;
}
delta = Math.max(Math.min(-delta, 1), -1);
this.currentScroll += delta * this.pageSize;
this.applyRange();
}
/**
* Ticks the scrollbar for the purposes of input-repeats (since mouse-downs are
* not repeat-triggered), used to repeatedly page-up or page-down when the mouse
* is held in the area above or below the scrollbar handle.
*/
public void tick() {
this.eventRepeater.tick();
}
private void pageUp() {
this.currentScroll -= this.pageSize;
this.applyRange();
}
private void pageDown() {
this.currentScroll += this.pageSize;
this.applyRange();
}
}
@@ -25,6 +25,7 @@ import java.util.function.Predicate;
import java.util.regex.Pattern;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
@@ -47,6 +48,7 @@ import appeng.api.config.StorageFilter;
import appeng.api.config.TerminalStyle;
import appeng.api.config.ViewItems;
import appeng.api.config.YesNo;
import appeng.client.gui.AEBaseScreen;
import appeng.core.localization.ButtonToolTips;
import appeng.util.EnumCycler;
@@ -89,9 +91,11 @@ public class SettingToggleButton<T extends Enum<T>> extends IconButton {
registerApp(16 * 7, Settings.CONDENSER_OUTPUT, CondenserOutput.TRASH, ButtonToolTips.CondenserOutput,
ButtonToolTips.Trash);
registerApp(16 * 7 + 1, Settings.CONDENSER_OUTPUT, CondenserOutput.MATTER_BALLS,
ButtonToolTips.CondenserOutput, ButtonToolTips.MatterBalls);
ButtonToolTips.CondenserOutput,
ButtonToolTips.MatterBalls.text(CondenserOutput.MATTER_BALLS.requiredPower));
registerApp(16 * 7 + 2, Settings.CONDENSER_OUTPUT, CondenserOutput.SINGULARITY,
ButtonToolTips.CondenserOutput, ButtonToolTips.Singularity);
ButtonToolTips.CondenserOutput,
ButtonToolTips.Singularity.text(CondenserOutput.SINGULARITY.requiredPower));
registerApp(16 * 9 + 1, Settings.ACCESS, AccessRestriction.READ, ButtonToolTips.IOMode,
ButtonToolTips.Read);
@@ -230,7 +234,13 @@ public class SettingToggleButton<T extends Enum<T>> extends IconButton {
}
private void triggerPress() {
boolean backwards = MinecraftClient.getInstance().mouse.wasRightButtonClicked();
boolean backwards = false;
// This isn't great, but we don't get any information about right-clicks
// otherwise
Screen currentScreen = MinecraftClient.getInstance().currentScreen;
if (currentScreen instanceof AEBaseScreen) {
backwards = ((AEBaseScreen<?>) currentScreen).isHandlingRightClick();
}
onPress.handle(this, backwards);
}
@@ -31,7 +31,7 @@ import net.minecraft.util.Identifier;
public class TabButton extends ButtonWidget implements ITooltip {
public static final Identifier TEXTURE_STATES = new Identifier("appliedenergistics2", "textures/guis/states.png");
private final ItemRenderer itemRenderer;
private int hideEdge = 0;
private boolean hideEdge;
private int myIcon = -1;
private ItemStack myItem;
@@ -69,14 +69,17 @@ public class TabButton extends ButtonWidget implements ITooltip {
RenderSystem.enableAlphaTest();
int uv_x = (this.hideEdge > 0 ? 11 : 13);
// Selects the button border from the sprite-sheet, where each type occupies a
// 2x2 slot
int uv_x = 8 + (this.hideEdge ? 0 : 2);
int uv_y = 12 + (this.isFocused() ? 2 : 0);
final int offsetX = this.hideEdge > 0 ? 1 : 0;
final int offsetX = this.hideEdge ? 1 : 0;
drawTexture(matrices, this.x, this.y, uv_x * 16, 0, 25, 22);
drawTexture(matrices, this.x, this.y, uv_x * 16, uv_y * 16, 25, 22);
if (this.myIcon >= 0) {
final int uv_y = this.myIcon / 16;
uv_y = this.myIcon / 16;
uv_x = this.myIcon - uv_y * 16;
drawTexture(matrices, offsetX + this.x + 3, this.y + 3, uv_x * 16, uv_y * 16, 16, 16);
@@ -122,11 +125,11 @@ public class TabButton extends ButtonWidget implements ITooltip {
return this.visible;
}
public int getHideEdge() {
public boolean getHideEdge() {
return this.hideEdge;
}
public void setHideEdge(final int hideEdge) {
public void setHideEdge(final boolean hideEdge) {
this.hideEdge = hideEdge;
}
}
@@ -0,0 +1,64 @@
package appeng.client.gui.widgets;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;
/**
* Displays a small icon that shows validation errors for some input control.
*/
public class ValidationIcon extends IconButton {
private final List<Text> tooltip = new ArrayList<>();
private boolean valid;
public ValidationIcon(int x, int y) {
super(x, y, btn -> {
});
setDisableBackground(true);
setDisableClickSound(true);
setHalfSize(true);
}
public void setValid(boolean valid) {
setVisibility(!valid);
if (valid) {
this.tooltip.clear();
}
}
public void setTooltip(List<Text> lines) {
this.tooltip.clear();
this.tooltip.addAll(lines);
}
@Override
protected int getIconIndex() {
return 16 * 8;
}
@Override
public boolean changeFocus(boolean flag) {
return false; // Cannot focus this element
}
@Override
public void renderToolTip(MatrixStack matrices, int mouseX, int mouseY) {
if (this.tooltip.isEmpty()) {
return;
}
MinecraftClient client = MinecraftClient.getInstance();
Screen screen = client.currentScreen;
if (screen == null) {
return;
}
screen.renderTooltip(matrices, this.tooltip, x, y);
}
}
@@ -41,11 +41,6 @@ import appeng.fluids.util.FluidSorters;
import appeng.util.Platform;
import appeng.util.prioritylist.IPartitionList;
/**
* @author BrockWS
* @version rv6 - 22/05/2018
* @since rv6 22/05/2018
*/
public class FluidRepo {
private final IItemList<IAEFluidStack> list = Api.instance().storage().getStorageChannel(IFluidStorageChannel.class)
.createList();
@@ -21,23 +21,22 @@ package appeng.client.me;
import javax.annotation.Nonnull;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.inventory.SimpleInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot;
import appeng.api.storage.data.IAEFluidStack;
import appeng.fluids.container.slots.IMEFluidSlot;
/**
* @author BrockWS
* @version rv6 - 22/05/2018
* @since rv6 22/05/2018
*/
public class SlotFluidME extends Slot implements IMEFluidSlot {
private static final Inventory EMPTY_INVENTORY = new SimpleInventory(0);
private final InternalFluidSlotME slot;
public SlotFluidME(InternalFluidSlotME slot) {
super(null, 0, slot.getxPosition(), slot.getyPosition());
super(EMPTY_INVENTORY, 0, slot.getxPosition(), slot.getyPosition());
this.slot = slot;
}
@@ -69,7 +68,7 @@ public class SlotFluidME extends Slot implements IMEFluidSlot {
}
@Override
public void setStack(final ItemStack par1ItemStack) {
public void setStack(final ItemStack stack) {
}
@@ -85,7 +84,7 @@ public class SlotFluidME extends Slot implements IMEFluidSlot {
}
@Override
public boolean canTakeItems(final PlayerEntity par1PlayerEntity) {
public boolean canTakeItems(final PlayerEntity player) {
return false;
}
}
+13 -9
View File
@@ -19,6 +19,8 @@
package appeng.client.me;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.inventory.SimpleInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot;
@@ -26,16 +28,18 @@ import appeng.api.storage.data.IAEItemStack;
public class SlotME extends Slot {
private final InternalSlotME mySlot;
private static final Inventory EMPTY_INVENTORY = new SimpleInventory(0);
public SlotME(final InternalSlotME me) {
super(null, 0, me.getxPosition(), me.getyPosition());
this.mySlot = me;
private final InternalSlotME slot;
public SlotME(final InternalSlotME slot) {
super(EMPTY_INVENTORY, 0, slot.getxPosition(), slot.getyPosition());
this.slot = slot;
}
public IAEItemStack getAEStack() {
if (this.mySlot.hasPower()) {
return this.mySlot.getAEStack();
if (this.slot.hasPower()) {
return this.slot.getAEStack();
}
return null;
}
@@ -47,15 +51,15 @@ public class SlotME extends Slot {
@Override
public ItemStack getStack() {
if (this.mySlot.hasPower()) {
return this.mySlot.getStack();
if (this.slot.hasPower()) {
return this.slot.getStack();
}
return ItemStack.EMPTY;
}
@Override
public boolean hasStack() {
if (this.mySlot.hasPower()) {
if (this.slot.hasPower()) {
return !this.getStack().isEmpty();
}
return false;
@@ -104,7 +104,7 @@ class CableBuilder {
throw new IllegalStateException("Cable type " + cableType + " does not support connections.");
}
return new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
return new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, textureFolder + color.name().toLowerCase(Locale.ROOT)));
}
@@ -20,7 +20,6 @@ package appeng.client.render.cablebus;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -30,6 +29,10 @@ import java.util.function.Supplier;
import javax.annotation.Nullable;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.renderer.v1.Renderer;
@@ -61,10 +64,15 @@ import appeng.api.util.AEColor;
@Environment(EnvType.CLIENT)
public class CableBusBakedModel implements BakedModel, FabricBakedModel {
private static final Mesh EMPTY_MESH = consumer -> {
};
private static final Renderer RENDERER = RendererAccess.INSTANCE.getRenderer();
// FIXME: This entire cache seems dumb as shit
private static final Map<CableBusRenderState, Mesh> CABLE_MODEL_CACHE = new HashMap<>();
// The number of meshes overall that will be cached
private static final int CACHE_MESH_COUNT = 100;
private final LoadingCache<CableBusRenderState, Mesh> cableModelCache;
private final CableBuilder cableBuilder;
@@ -80,6 +88,15 @@ public class CableBusBakedModel implements BakedModel, FabricBakedModel {
this.facadeBuilder = facadeBuilder;
this.partModels = partModels;
this.particleTexture = particleTexture;
this.cableModelCache = CacheBuilder.newBuilder()//
.maximumSize(CACHE_MESH_COUNT)//
.build(new CacheLoader<CableBusRenderState, Mesh>() {
@Override
public Mesh load(CableBusRenderState renderState) {
Mesh mesh = buildCableModel(renderState);
return mesh != null ? mesh : EMPTY_MESH;
}
});
}
@Override
@@ -109,8 +126,8 @@ public class CableBusBakedModel implements BakedModel, FabricBakedModel {
}
// First, handle the cable at the center of the cable bus
final Mesh cableModel = CABLE_MODEL_CACHE.computeIfAbsent(renderState, this::buildCableModel);
if (cableModel != null) {
final Mesh cableModel = cableModelCache.getUnchecked(renderState);
if (cableModel != EMPTY_MESH) {
context.meshConsumer().accept(cableModel);
}
@@ -359,10 +376,6 @@ public class CableBusBakedModel implements BakedModel, FabricBakedModel {
return ModelOverrideList.EMPTY;
}
public static void clearCache() {
CABLE_MODEL_CACHE.clear();
}
@Override
public boolean isVanillaAdapter() {
return false;
@@ -23,7 +23,6 @@ public class CableBusModelLoader implements ModelResourceProvider {
public UnbakedModel loadModelResource(Identifier resourceId, ModelProviderContext context)
throws ModelProviderException {
if (CABLE_BUS_MODEL.equals(resourceId)) {
CableBusBakedModel.clearCache();
return new CableBusModel(partModels);
} else {
return null;
@@ -74,7 +74,7 @@ public enum CableCoreType {
}
public SpriteIdentifier getTexture(AEColor color) {
return new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
return new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, this.textureFolder + "/" + color.name().toLowerCase(Locale.ROOT)));
}
@@ -258,7 +258,9 @@ public class FacadeBuilder {
for (Box box : holeStrips) {
emitter.fromVanilla(quad.getVertexData(), 0, false);
emitter.cullFace(cullFace);
// Keep the cull-face for faces that are flush with the outer block-face on the
// side the facade is attached to, but clear it for anything that faces inwards
emitter.cullFace(cullFace == side ? side : null);
emitter.nominalFace(quad.getFace());
interpolator.setInputQuad(emitter);
@@ -18,7 +18,7 @@ import appeng.core.AppEng;
public class P2PTunnelFrequencyModel implements BasicUnbakedModel {
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, "part/p2p_tunnel_frequency"));
@Nullable
@@ -24,7 +24,6 @@ import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Quaternion;
@@ -93,10 +92,6 @@ public class QuadRotator implements RenderContext.QuadTransform {
}
}
// FIXME FABRIC: Wait for Grondags response about this one
MutableQuadViewImpl quadImpl = (MutableQuadViewImpl) quad;
quadImpl.lightFace(rotation.rotate(quad.lightFace()));
// Transform the nominal face, setting the cull face will also overwrite the
// nominialFace,
// hence saving both first and the order here.
@@ -47,7 +47,8 @@ public class SmartCableTextures {
new Identifier(AppEng.MOD_ID, "part/cable/smart/channels_12"), //
new Identifier(AppEng.MOD_ID, "part/cable/smart/channels_13"), //
new Identifier(AppEng.MOD_ID, "part/cable/smart/channels_14")//
}).map(e -> new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX, e)).toArray(SpriteIdentifier[]::new);
}).map(e -> new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, e))
.toArray(SpriteIdentifier[]::new);
// Textures used to display channels on smart cables. There's two sets of 5
// textures each, and
@@ -115,7 +115,7 @@ public class CraftingCubeModel implements BasicUnbakedModel {
}
private static SpriteIdentifier texture(String name) {
return new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
return new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, "block/crafting/" + name));
}
}
@@ -25,7 +25,7 @@ import appeng.core.AppEng;
public class BiometricCardModel implements BasicUnbakedModel {
public static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "item/biometric_card_base");
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, "item/biometric_card_hash"));
@Override
@@ -26,11 +26,11 @@ public class ColorApplicatorModel implements BasicUnbakedModel {
private static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "item/color_applicator_colored");
private static final SpriteIdentifier TEXTURE_DARK = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
private static final SpriteIdentifier TEXTURE_DARK = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, "item/color_applicator_tip_dark"));
private static final SpriteIdentifier TEXTURE_MEDIUM = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
private static final SpriteIdentifier TEXTURE_MEDIUM = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, "item/color_applicator_tip_medium"));
private static final SpriteIdentifier TEXTURE_BRIGHT = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
private static final SpriteIdentifier TEXTURE_BRIGHT = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, "item/color_applicator_tip_bright"));
@Override
@@ -62,13 +62,13 @@ class GlassBakedModel implements BakedModel, FabricBakedModel {
private static final byte[][][] OFFSETS = generateOffsets();
// Alternating textures based on position
static final SpriteIdentifier TEXTURE_A = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
static final SpriteIdentifier TEXTURE_A = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier("appliedenergistics2:block/glass/quartz_glass_a"));
static final SpriteIdentifier TEXTURE_B = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
static final SpriteIdentifier TEXTURE_B = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier("appliedenergistics2:block/glass/quartz_glass_b"));
static final SpriteIdentifier TEXTURE_C = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
static final SpriteIdentifier TEXTURE_C = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier("appliedenergistics2:block/glass/quartz_glass_c"));
static final SpriteIdentifier TEXTURE_D = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
static final SpriteIdentifier TEXTURE_D = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier("appliedenergistics2:block/glass/quartz_glass_d"));
// Frame texture
@@ -81,7 +81,7 @@ class GlassBakedModel implements BakedModel, FabricBakedModel {
private static SpriteIdentifier[] generateTexturesFrame() {
return IntStream.range(1, 16).mapToObj(Integer::toBinaryString).map(s -> Strings.padStart(s, 4, '0'))
.map(s -> new Identifier("appliedenergistics2:block/glass/quartz_glass_frame" + s))
.map(rl -> new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX, rl))
.map(rl -> new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, rl))
.toArray(SpriteIdentifier[]::new);
}
@@ -25,7 +25,7 @@ import appeng.core.AppEng;
public class MemoryCardModel implements BasicUnbakedModel {
public static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "item/memory_card_base");
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, "item/memory_card_hash"));
@Override
@@ -59,7 +59,7 @@ public class SpatialPylonModel implements BasicUnbakedModel {
}
private static SpriteIdentifier getTexturePath(SpatialPylonTextureType type) {
return new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
return new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, "block/spatial_pylon/" + type.name().toLowerCase(Locale.ROOT)));
}
@@ -1,5 +1,7 @@
package appeng.client.render.tesr;
import java.util.Random;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.MinecraftClient;
@@ -9,12 +11,12 @@ import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
@@ -36,7 +38,7 @@ public final class InscriberTESR extends BlockEntityRenderer<InscriberBlockEntit
private static final float ITEM_RENDER_SCALE = 1.0f / 1.2f;
private static final SpriteIdentifier TEXTURE_INSIDE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
private static final SpriteIdentifier TEXTURE_INSIDE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE,
new Identifier(AppEng.MOD_ID, "block/inscriber_inside"));
public static final ImmutableList<SpriteIdentifier> SPRITES = ImmutableList.of(TEXTURE_INSIDE);
@@ -197,9 +199,12 @@ public final class InscriberTESR extends BlockEntityRenderer<InscriberBlockEntit
ItemRenderer itemRenderer = MinecraftClient.getInstance().getItemRenderer();
// heuristic to scale items down much further than blocks
boolean renderAsCube = (stack.getItem() instanceof BlockItem);
if (!renderAsCube) {
// heuristic to scale items down much further than blocks,
// the assumption here is that the generated item models will return their faces
// for direction=null, while a block-model will have their faces for
// cull-faces, but not direction=null
BakedModel model = itemRenderer.getModels().getModel(stack);
if (!model.getQuads(null, null, new Random()).isEmpty()) {
ms.scale(0.5f, 0.5f, 0.5f);
}
@@ -66,10 +66,8 @@ import appeng.container.slot.PlayerInvSlot;
import appeng.core.AELog;
import appeng.core.Api;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ConfigValuePacket;
import appeng.core.sync.packets.InventoryActionPacket;
import appeng.core.sync.packets.TargetItemStackPacket;
import appeng.helpers.ICustomNameObject;
import appeng.helpers.InventoryAction;
import appeng.me.helpers.PlayerSource;
import appeng.mixins.ScreenHandlerListeners;
@@ -88,11 +86,9 @@ public abstract class AEBaseContainer extends ScreenHandler {
private final IGuiItemObject obj;
private final HashMap<Integer, SyncData> syncData = new HashMap<>();
private boolean isContainerValid = true;
private String customName;
private ContainerLocator locator;
private IMEInventoryHandler<IAEItemStack> cellInv;
private IEnergySource powerSrc;
private boolean sentCustomName;
private int ticksSinceCheck = 900;
private IAEItemStack clientRequestedTargetItem = null;
@@ -317,9 +313,7 @@ public abstract class AEBaseContainer extends ScreenHandler {
@Override
public void sendContentUpdates() {
this.sendCustomName();
if (Platform.isServer()) {
if (isServer()) {
if (this.tileEntity != null
&& this.tileEntity.getWorld().getBlockEntity(this.tileEntity.getPos()) != this.tileEntity) {
this.setValidContainer(false);
@@ -886,43 +880,6 @@ public abstract class AEBaseContainer extends ScreenHandler {
this.sendContentUpdates();
}
private void sendCustomName() {
// FIXME: Trash this, this is handled by NamedContainerProvider now
if (!this.sentCustomName) {
this.sentCustomName = true;
if (Platform.isServer()) {
ICustomNameObject name = null;
if (this.part instanceof ICustomNameObject) {
name = (ICustomNameObject) this.part;
}
if (this.tileEntity instanceof ICustomNameObject) {
name = (ICustomNameObject) this.tileEntity;
}
if (this.obj instanceof ICustomNameObject) {
name = (ICustomNameObject) this.obj;
}
if (this instanceof ICustomNameObject) {
name = (ICustomNameObject) this;
}
if (name != null) {
if (name.hasCustomInventoryName()) {
this.setCustomName(name.getCustomInventoryName().getString());
}
if (this.getCustomName() != null) {
NetworkHandler.instance().sendTo(new ConfigValuePacket("CustomName", this.getCustomName()),
(ServerPlayerEntity) this.getPlayerInventory().player);
}
}
}
}
}
public void swapSlotContents(final int slotA, final int slotB) {
final Slot a = this.getSlot(slotA);
final Slot b = this.getSlot(slotB);
@@ -1012,14 +969,6 @@ public abstract class AEBaseContainer extends ScreenHandler {
this.cellInv = cellInv;
}
public String getCustomName() {
return this.customName;
}
public void setCustomName(final String customName) {
this.customName = customName;
}
public PlayerInventory getPlayerInventory() {
return this.invPlayer;
}
@@ -1048,4 +997,18 @@ public abstract class AEBaseContainer extends ScreenHandler {
this.powerSrc = powerSrc;
}
/**
* Returns whether this container instance lives on the client.
*/
protected boolean isClient() {
return invPlayer.player.getEntityWorld().isClient();
}
/**
* Returns whether this container instance lives on the server.
*/
protected boolean isServer() {
return !isClient();
}
}
@@ -89,6 +89,8 @@ public class SyncData {
NetworkHandler.instance().sendTo(new ConfigValuePacket("SyncDat." + this.channel, json),
(ServerPlayerEntity) o);
}
this.clientVersion = val;
return;
}
// Types other than Text must be non-null
@@ -50,7 +50,6 @@ import appeng.container.slot.RestrictedInputSlot;
import appeng.core.Api;
import appeng.tile.misc.CellWorkbenchBlockEntity;
import appeng.util.EnumCycler;
import appeng.util.Platform;
import appeng.util.helpers.ItemHandlerUtil;
import appeng.util.inv.WrapperSupplierItemHandler;
import appeng.util.iterators.NullIterator;
@@ -143,7 +142,7 @@ public class CellWorkbenchContainer extends UpgradeableContainer {
@Override
public void sendContentUpdates() {
final ItemStack is = this.workBench.getInventoryByName("cell").getInvStack(0);
if (Platform.isServer()) {
if (isServer()) {
for (final ScreenHandlerListener listener : this.getListeners()) {
if (this.prevStack != is) {
// if the bars changed an item was probably made, so just send shit!
@@ -34,7 +34,6 @@ import appeng.container.interfaces.IProgressProvider;
import appeng.container.slot.OutputSlot;
import appeng.container.slot.RestrictedInputSlot;
import appeng.tile.misc.CondenserBlockEntity;
import appeng.util.Platform;
public class CondenserContainer extends AEBaseContainer implements IProgressProvider {
@@ -76,13 +75,13 @@ public class CondenserContainer extends AEBaseContainer implements IProgressProv
@Override
public void sendContentUpdates() {
if (Platform.isServer()) {
if (isServer()) {
final double maxStorage = this.condenser.getStorage();
final double requiredEnergy = this.condenser.getRequiredPower();
this.requiredEnergy = requiredEnergy == 0 ? (int) maxStorage : (int) Math.min(requiredEnergy, maxStorage);
this.storedPower = (int) this.condenser.getStoredPower();
this.setOutput((CondenserOutput) this.condenser.getConfigManager().getSetting(Settings.CONDENSER_OUTPUT));
this.output = (CondenserOutput) this.condenser.getConfigManager().getSetting(Settings.CONDENSER_OUTPUT);
}
super.sendContentUpdates();
@@ -102,7 +101,4 @@ public class CondenserContainer extends AEBaseContainer implements IProgressProv
return this.output;
}
private void setOutput(final CondenserOutput output) {
this.output = output;
}
}
@@ -1,5 +1,7 @@
package appeng.container.implementations;
import java.util.function.Function;
import javax.annotation.Nullable;
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
@@ -12,9 +14,7 @@ import net.minecraft.screen.ScreenHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import appeng.api.config.SecurityPermissions;
import appeng.api.features.IWirelessTermHandler;
@@ -44,6 +44,8 @@ public final class ContainerHelper<C extends AEBaseContainer, I> {
private final SecurityPermissions requiredPermission;
private Function<I, Text> containerTitleStrategy = this::getDefaultContainerTitle;
public ContainerHelper(ContainerFactory<C, I> factory, Class<I> interfaceClass) {
this(factory, interfaceClass, null);
}
@@ -55,19 +57,47 @@ public final class ContainerHelper<C extends AEBaseContainer, I> {
this.factory = factory;
}
/**
* Specifies a custom strategy for obtaining a custom container name.
* <p>
* The stratgy should return {@link LiteralText#EMPTY} if there's no custom
* name.
*/
public ContainerHelper<C, I> withContainerTitle(Function<I, Text> containerTitleStrategy) {
this.containerTitleStrategy = containerTitleStrategy;
return this;
}
/**
* Opens a container that is based around a single block entity. The tile
* entity's position is encoded in the packet buffer.
*/
public C fromNetwork(int windowId, PlayerInventory inv, PacketByteBuf packetBuf) {
return fromNetwork(windowId, inv, packetBuf, (accessObj, container, buffer) -> {
});
}
/**
* Same as {@link #open}, but allows or additional data to be read from the
* packet, and passed onto the container.
*/
public C fromNetwork(int windowId, PlayerInventory inv, PacketByteBuf packetBuf,
InitialDataDeserializer<C, I> initialDataDeserializer) {
I host = getHostFromLocator(inv.player, ContainerLocator.read(packetBuf));
if (host != null) {
return factory.create(windowId, inv, host);
C container = factory.create(windowId, inv, host);
initialDataDeserializer.deserializeInitialData(host, container, packetBuf);
return container;
}
return null;
}
public boolean open(PlayerEntity player, ContainerLocator locator) {
return open(player, locator, (accessObj, buffer) -> {
});
}
public boolean open(PlayerEntity player, ContainerLocator locator, InitialDataSerializer<I> initialDataSerializer) {
if (!(player instanceof ServerPlayerEntity)) {
// Cannot open containers on the client or for non-players
// FIXME logging?
@@ -84,9 +114,9 @@ public final class ContainerHelper<C extends AEBaseContainer, I> {
return false;
}
Text title = findContainerTitle(player.world, locator, accessInterface);
Text title = containerTitleStrategy.apply(accessInterface);
player.openHandledScreen(new HandlerFactory(locator, title, accessInterface));
player.openHandledScreen(new HandlerFactory(locator, title, accessInterface, initialDataSerializer));
return true;
}
@@ -99,15 +129,20 @@ public final class ContainerHelper<C extends AEBaseContainer, I> {
private final Text title;
public HandlerFactory(ContainerLocator locator, Text title, I accessInterface) {
private final InitialDataSerializer<I> initialDataSerializer;
public HandlerFactory(ContainerLocator locator, Text title, I accessInterface,
InitialDataSerializer<I> initialDataSerializer) {
this.locator = locator;
this.title = title;
this.accessInterface = accessInterface;
this.initialDataSerializer = initialDataSerializer;
}
@Override
public void writeScreenOpeningData(ServerPlayerEntity player, PacketByteBuf buf) {
locator.write(buf);
initialDataSerializer.serializeInitialData(accessInterface, buf);
}
@Override
@@ -127,28 +162,6 @@ public final class ContainerHelper<C extends AEBaseContainer, I> {
}
private Text findContainerTitle(World world, ContainerLocator locator, I accessInterface) {
if (accessInterface instanceof ICustomNameObject) {
ICustomNameObject customNameObject = (ICustomNameObject) accessInterface;
if (customNameObject.hasCustomInventoryName()) {
return customNameObject.getCustomInventoryName();
}
}
// Use block name at position
// FIXME: this is not right, we'd need to check the part's item stack, or custom
// naming interface impl
// FIXME: Should move this up, because at this point, it's hard to know where
// the terminal host came from (part or tile)
if (locator.hasBlockPos()) {
return new TranslatableText(world.getBlockState(locator.getBlockPos()).getBlock().getTranslationKey());
}
return new LiteralText("Unknown");
}
private I getHostFromLocator(PlayerEntity player, ContainerLocator locator) {
if (locator.hasItemIndex()) {
return getHostFromPlayerInventory(player, locator);
@@ -225,6 +238,24 @@ public final class ContainerHelper<C extends AEBaseContainer, I> {
C create(int windowId, PlayerInventory playerInv, I accessObj);
}
/**
* Strategy used to serialize initial data for opening the container on the
* client-side into the packet that is sent to the client.
*/
@FunctionalInterface
public interface InitialDataSerializer<I> {
void serializeInitialData(I host, PacketByteBuf buffer);
}
/**
* Strategy used to deserialize initial data for opening the container on the
* client-side from the packet received by the server.
*/
@FunctionalInterface
public interface InitialDataDeserializer<C, I> {
void deserializeInitialData(I host, C container, PacketByteBuf buffer);
}
private boolean checkPermission(PlayerEntity player, Object accessInterface) {
if (requiredPermission != null) {
@@ -235,4 +266,15 @@ public final class ContainerHelper<C extends AEBaseContainer, I> {
}
private Text getDefaultContainerTitle(I accessInterface) {
if (accessInterface instanceof ICustomNameObject) {
ICustomNameObject customNameObject = (ICustomNameObject) accessInterface;
if (customNameObject.hasCustomInventoryName()) {
return customNameObject.getCustomInventoryName();
}
}
return LiteralText.EMPTY;
}
}
@@ -19,14 +19,8 @@
package appeng.container.implementations;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.Future;
import javax.annotation.Nullable;
import com.google.common.collect.ImmutableSet;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.network.PacketByteBuf;
@@ -66,9 +60,8 @@ import appeng.me.helpers.PlayerSource;
import appeng.parts.reporting.CraftingTerminalPart;
import appeng.parts.reporting.PatternTerminalPart;
import appeng.parts.reporting.TerminalPart;
import appeng.util.Platform;
public class CraftConfirmContainer extends AEBaseContainer {
public class CraftConfirmContainer extends AEBaseContainer implements CraftingCPUCyclingContainer {
public static ScreenHandlerType<CraftConfirmContainer> TYPE;
@@ -83,98 +76,51 @@ public class CraftConfirmContainer extends AEBaseContainer {
return helper.open(player, locator);
}
private final ArrayList<CraftingCPURecord> cpus = new ArrayList<>();
private final CraftingCPUCycler cpuCycler;
private ICraftingCPU selectedCpu;
private Future<ICraftingJob> job;
private ICraftingJob result;
@GuiSync(0)
public long bytesUsed;
@GuiSync(1)
public long cpuBytesAvail;
@GuiSync(2)
public int cpuCoProcessors;
@GuiSync(3)
public boolean autoStart = false;
@GuiSync(4)
public boolean simulation = true;
@GuiSync(5)
public int selectedCpu = -1;
// Indicates whether any CPUs are available
@GuiSync(6)
public boolean noCPU = true;
// Properties of the currently selected crafting CPU, this can be null
// if no CPUs are available, or if an automatic one is selected
@GuiSync(1)
public long cpuBytesAvail;
@GuiSync(2)
public int cpuCoProcessors;
@GuiSync(7)
public Text myName;
public Text cpuName;
public CraftConfirmContainer(int id, PlayerInventory ip, ITerminalHost te) {
super(TYPE, id, ip, te);
this.cpuCycler = new CraftingCPUCycler(this::cpuMatches, this::onCPUSelectionChanged);
// A player can select no crafting CPU to use a suitable one automatically
this.cpuCycler.setAllowNoSelection(true);
}
public void cycleCpu(final boolean next) {
if (next) {
this.setSelectedCpu(this.getSelectedCpu() + 1);
} else {
this.setSelectedCpu(this.getSelectedCpu() - 1);
}
if (this.getSelectedCpu() < -1) {
this.setSelectedCpu(this.cpus.size() - 1);
} else if (this.getSelectedCpu() >= this.cpus.size()) {
this.setSelectedCpu(-1);
}
if (this.getSelectedCpu() == -1) {
this.setCpuAvailableBytes(0);
this.setCpuCoProcessors(0);
this.setName(null);
} else {
CraftingCPURecord cpu = this.cpus.get(this.getSelectedCpu());
this.setName(cpu.getName());
this.setCpuAvailableBytes(cpu.getSize());
this.setCpuCoProcessors(cpu.getProcessors());
}
@Override
public void cycleSelectedCPU(final boolean next) {
this.cpuCycler.cycleCpu(next);
}
@Override
public void sendContentUpdates() {
if (Platform.isClient()) {
if (isClient()) {
return;
}
final ICraftingGrid cc = this.getGrid().getCache(ICraftingGrid.class);
final ImmutableSet<ICraftingCPU> cpuSet = cc.getCpus();
int matches = 0;
boolean changed = false;
for (final ICraftingCPU c : cpuSet) {
boolean found = false;
for (final CraftingCPURecord ccr : this.cpus) {
if (ccr.getCpu() == c) {
found = true;
break;
}
}
final boolean matched = this.cpuMatches(c);
if (matched) {
matches++;
}
if (found == !matched) {
changed = true;
}
}
if (changed || this.cpus.size() != matches) {
this.cpus.clear();
for (final ICraftingCPU c : cpuSet) {
if (this.cpuMatches(c)) {
this.cpus.add(new CraftingCPURecord(c.getAvailableStorage(), c.getCoProcessors(), c));
}
}
this.sendCPUs();
}
this.setNoCPU(this.cpus.isEmpty());
this.cpuCycler.detectAndSendChanges(this.getGrid());
super.sendContentUpdates();
@@ -277,22 +223,6 @@ public class CraftConfirmContainer extends AEBaseContainer {
return c.getAvailableStorage() >= this.getUsedBytes() && !c.isBusy();
}
private void sendCPUs() {
Collections.sort(this.cpus);
if (this.getSelectedCpu() >= this.cpus.size()) {
this.setSelectedCpu(-1);
this.setCpuAvailableBytes(0);
this.setCpuCoProcessors(0);
this.setName(null);
} else if (this.getSelectedCpu() != -1) {
CraftingCPURecord cpu = this.cpus.get(this.getSelectedCpu());
this.setName(cpu.getName());
this.setCpuAvailableBytes(cpu.getSize());
this.setCpuCoProcessors(cpu.getProcessors());
}
}
public void startJob() {
ScreenHandlerType<?> originalGui = null;
@@ -315,9 +245,7 @@ public class CraftConfirmContainer extends AEBaseContainer {
if (this.result != null && !this.isSimulation()) {
final ICraftingGrid cc = this.getGrid().getCache(ICraftingGrid.class);
final ICraftingLink g = cc.submitJob(this.result, null,
this.getSelectedCpu() == -1 ? null : this.cpus.get(this.getSelectedCpu()).getCpu(), true,
this.getActionSrc());
final ICraftingLink g = cc.submitJob(this.result, null, this.selectedCpu, true, this.getActionSrc());
this.setAutoStart(false);
if (g != null && originalGui != null && this.getLocator() != null) {
ContainerOpener.openContainer(originalGui, getPlayerInventory().player, getLocator());
@@ -347,6 +275,22 @@ public class CraftConfirmContainer extends AEBaseContainer {
}
}
private void onCPUSelectionChanged(CraftingCPURecord cpuRecord, boolean cpusAvailable) {
noCPU = !cpusAvailable;
if (cpuRecord == null) {
cpuBytesAvail = 0;
cpuCoProcessors = 0;
cpuName = null;
selectedCpu = null;
} else {
cpuBytesAvail = cpuRecord.getSize();
cpuCoProcessors = cpuRecord.getProcessors();
cpuName = cpuRecord.getName();
selectedCpu = cpuRecord.getCpu();
}
}
public World getWorld() {
return this.getPlayerInv().player.world;
}
@@ -371,42 +315,18 @@ public class CraftConfirmContainer extends AEBaseContainer {
return this.cpuBytesAvail;
}
private void setCpuAvailableBytes(final long cpuBytesAvail) {
this.cpuBytesAvail = cpuBytesAvail;
}
public int getCpuCoProcessors() {
return this.cpuCoProcessors;
}
private void setCpuCoProcessors(final int cpuCoProcessors) {
this.cpuCoProcessors = cpuCoProcessors;
}
public int getSelectedCpu() {
return this.selectedCpu;
}
private void setSelectedCpu(final int selectedCpu) {
this.selectedCpu = selectedCpu;
}
public Text getName() {
return this.myName;
}
private void setName(@Nullable final Text myName) {
this.myName = myName;
return this.cpuName;
}
public boolean hasNoCPU() {
return this.noCPU;
}
private void setNoCPU(final boolean noCPU) {
this.noCPU = noCPU;
}
public boolean isSimulation() {
return this.simulation;
}
@@ -26,7 +26,7 @@ import net.minecraft.network.PacketByteBuf;
import net.minecraft.screen.ScreenHandlerListener;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.text.LiteralText;
import appeng.api.config.SecurityPermissions;
import appeng.api.networking.IGrid;
@@ -46,24 +46,28 @@ import appeng.core.Api;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ConfigValuePacket;
import appeng.core.sync.packets.MEInventoryUpdatePacket;
import appeng.helpers.ICustomNameObject;
import appeng.me.cluster.implementations.CraftingCPUCluster;
import appeng.tile.crafting.CraftingBlockEntity;
import appeng.util.Platform;
public class CraftingCPUContainer extends AEBaseContainer
implements IMEMonitorHandlerReceiver<IAEItemStack>, ICustomNameObject {
public class CraftingCPUContainer extends AEBaseContainer implements IMEMonitorHandlerReceiver<IAEItemStack> {
public static ScreenHandlerType<CraftingCPUContainer> TYPE;
private static final ContainerHelper<CraftingCPUContainer, CraftingBlockEntity> helper = new ContainerHelper<>(
CraftingCPUContainer::new, CraftingBlockEntity.class, SecurityPermissions.CRAFT);
CraftingCPUContainer::new, CraftingBlockEntity.class, SecurityPermissions.CRAFT)
.withContainerTitle(craftingTileEntity -> {
// Use the cluster's custom name instead of the right-clicked block entities one
CraftingCPUCluster cluster = craftingTileEntity.getCluster();
if (cluster != null && cluster.getName() != null) {
return cluster.getName();
}
return LiteralText.EMPTY;
});
private final IItemList<IAEItemStack> list = Api.instance().storage().getStorageChannel(IItemStorageChannel.class)
.createList();
private IGrid network;
private final IGrid network;
private CraftingCPUCluster monitor = null;
private Text cpuName = null;
@GuiSync(0)
public long eta = -1;
@@ -77,14 +81,16 @@ public class CraftingCPUContainer extends AEBaseContainer
final IActionHost host = (IActionHost) (te instanceof IActionHost ? te : null);
if (host != null && host.getActionableNode() != null) {
this.setNetwork(host.getActionableNode().getGrid());
this.network = host.getActionableNode().getGrid();
} else {
this.network = null;
}
if (te instanceof CraftingBlockEntity) {
this.setCPU(((CraftingBlockEntity) te).getCluster());
}
if (this.getNetwork() == null && Platform.isServer()) {
if (this.getNetwork() == null && isServer()) {
this.setValidContainer(false);
}
}
@@ -114,15 +120,13 @@ public class CraftingCPUContainer extends AEBaseContainer
}
if (c instanceof CraftingCPUCluster) {
this.cpuName = c.getName();
this.setMonitor((CraftingCPUCluster) c);
this.monitor = (CraftingCPUCluster) c;
this.list.resetStatus();
this.getMonitor().getListOfItem(this.list, CraftingItemList.ALL);
this.getMonitor().addListener(this, null);
this.setEstimatedTime(0);
} else {
this.setMonitor(null);
this.cpuName = null;
this.monitor = null;
this.setEstimatedTime(-1);
}
}
@@ -153,7 +157,7 @@ public class CraftingCPUContainer extends AEBaseContainer
@Override
public void sendContentUpdates() {
if (Platform.isServer() && this.getMonitor() != null && !this.list.isEmpty()) {
if (isServer() && this.getMonitor() != null && !this.list.isEmpty()) {
try {
if (this.getEstimatedTime() >= 0) {
final long elapsedTime = this.getMonitor().getElapsedTime();
@@ -218,16 +222,6 @@ public class CraftingCPUContainer extends AEBaseContainer
}
@Override
public Text getCustomInventoryName() {
return this.cpuName;
}
@Override
public boolean hasCustomInventoryName() {
return this.cpuName != null;
}
public long getEstimatedTime() {
return this.eta;
}
@@ -240,15 +234,8 @@ public class CraftingCPUContainer extends AEBaseContainer
return this.monitor;
}
private void setMonitor(final CraftingCPUCluster monitor) {
this.monitor = monitor;
}
IGrid getNetwork() {
return this.network;
}
private void setNetwork(final IGrid network) {
this.network = network;
}
}
@@ -0,0 +1,131 @@
package appeng.container.implementations;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
import com.google.common.collect.ImmutableSet;
import net.minecraft.text.LiteralText;
import appeng.api.networking.IGrid;
import appeng.api.networking.crafting.ICraftingCPU;
import appeng.api.networking.crafting.ICraftingGrid;
/**
* Utility class for dialogs that can cycle through crafting CPUs
*/
class CraftingCPUCycler {
@FunctionalInterface
public interface ChangeListener {
void onChange(CraftingCPURecord selectedCpu, boolean cpusAvailable);
}
private final Predicate<ICraftingCPU> cpuFilter;
private final ChangeListener changeListener;
private final List<CraftingCPURecord> cpus = new ArrayList<>();
private int selectedCpu = -1;
private boolean initialDataSent = false;
private boolean allowNoSelection;
public CraftingCPUCycler(Predicate<ICraftingCPU> cpuFilter, ChangeListener changeListener) {
this.cpuFilter = cpuFilter;
this.changeListener = changeListener;
}
public void detectAndSendChanges(IGrid network) {
final ICraftingGrid cc = network.getCache(ICraftingGrid.class);
final ImmutableSet<ICraftingCPU> cpuSet = cc.getCpus();
int matches = 0;
boolean changed = !initialDataSent;
initialDataSent = true;
for (final ICraftingCPU c : cpuSet) {
boolean found = false;
for (final CraftingCPURecord ccr : this.cpus) {
if (ccr.getCpu() == c) {
found = true;
break;
}
}
final boolean matched = this.cpuFilter.test(c);
if (matched) {
matches++;
}
if (found == !matched) {
changed = true;
}
}
if (changed || this.cpus.size() != matches) {
this.cpus.clear();
for (final ICraftingCPU c : cpuSet) {
if (this.cpuFilter.test(c)) {
this.cpus.add(new CraftingCPURecord(c.getAvailableStorage(), c.getCoProcessors(), c));
}
}
// Sort and assign numeric IDs in case they have no names
Collections.sort(this.cpus);
for (int i = 0; i < this.cpus.size(); i++) {
CraftingCPURecord cpu = cpus.get(i);
if (cpu.getName() == null) {
cpu.setName(new LiteralText("#" + (i + 1)));
}
}
this.notifyListener();
}
}
public void cycleCpu(final boolean next) {
if (next) {
this.selectedCpu++;
} else {
this.selectedCpu--;
}
// If "no CPU" is a valid selection, then -1 is the first potential item
int lowerLimit = this.allowNoSelection ? -1 : 0;
if (this.selectedCpu < lowerLimit) {
this.selectedCpu = this.cpus.size() - 1;
} else if (this.selectedCpu >= this.cpus.size()) {
this.selectedCpu = lowerLimit;
}
this.notifyListener();
}
public boolean isAllowNoSelection() {
return allowNoSelection;
}
public void setAllowNoSelection(boolean allowNoSelection) {
this.allowNoSelection = allowNoSelection;
}
private void notifyListener() {
if (this.selectedCpu >= this.cpus.size()) {
this.selectedCpu = -1;
}
// Force the selected CPU to the first available CPU unless no-selection is
// explicitly allowed
if (!this.allowNoSelection && this.selectedCpu == -1 && !this.cpus.isEmpty()) {
this.selectedCpu = 0;
}
if (this.selectedCpu != -1) {
this.changeListener.onChange(this.cpus.get(this.selectedCpu), true);
} else {
this.changeListener.onChange(null, !this.cpus.isEmpty());
}
}
}
@@ -0,0 +1,12 @@
package appeng.container.implementations;
/**
* Implemented on screens that show information about a crafting CPU and allow
* the CPU to be cycled. Is triggered by receiving a config value packet with
* name <code>Terminal.Cpu</code>.
*/
public interface CraftingCPUCyclingContainer {
void cycleSelectedCPU(boolean forward);
}
@@ -25,16 +25,16 @@ import net.minecraft.text.Text;
import appeng.api.networking.crafting.ICraftingCPU;
public class CraftingCPURecord implements Comparable<CraftingCPURecord> {
private final Text myName;
private final ICraftingCPU cpu;
private final long size;
private final int processors;
private Text name;
public CraftingCPURecord(final long size, final int coProcessors, final ICraftingCPU server) {
this.size = size;
this.processors = coProcessors;
this.cpu = server;
this.myName = server.getName();
this.name = server.getName();
}
@Override
@@ -50,10 +50,6 @@ public class CraftingCPURecord implements Comparable<CraftingCPURecord> {
return this.cpu;
}
Text getName() {
return this.myName;
}
int getProcessors() {
return this.processors;
}
@@ -61,4 +57,13 @@ public class CraftingCPURecord implements Comparable<CraftingCPURecord> {
long getSize() {
return this.size;
}
public Text getName() {
return name;
}
public void setName(Text name) {
this.name = name;
}
}
@@ -18,12 +18,6 @@
package appeng.container.implementations;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.google.common.collect.ImmutableSet;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.network.PacketByteBuf;
@@ -31,14 +25,13 @@ import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.text.Text;
import appeng.api.config.SecurityPermissions;
import appeng.api.networking.IGrid;
import appeng.api.networking.crafting.ICraftingCPU;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.storage.ITerminalHost;
import appeng.container.ContainerLocator;
import appeng.container.guisync.GuiSync;
import appeng.util.Platform;
public class CraftingStatusContainer extends CraftingCPUContainer {
public class CraftingStatusContainer extends CraftingCPUContainer implements CraftingCPUCyclingContainer {
public static ScreenHandlerType<CraftingStatusContainer> TYPE;
@@ -53,13 +46,13 @@ public class CraftingStatusContainer extends CraftingCPUContainer {
return helper.open(player, locator);
}
private final List<CraftingCPURecord> cpus = new ArrayList<>();
@GuiSync(5)
public int selectedCpu = -1;
private final CraftingCPUCycler cpuCycler = new CraftingCPUCycler(this::cpuMatches, this::onCPUSelectionChanged);
@GuiSync(6)
public boolean noCPU = true;
@GuiSync(7)
public Text myName;
public Text cpuName;
public CraftingStatusContainer(int id, final PlayerInventory ip, final ITerminalHost te) {
super(TYPE, id, ip, te);
@@ -67,43 +60,9 @@ public class CraftingStatusContainer extends CraftingCPUContainer {
@Override
public void sendContentUpdates() {
if (Platform.isServer() && this.getNetwork() != null) {
final ICraftingGrid cc = this.getNetwork().getCache(ICraftingGrid.class);
final ImmutableSet<ICraftingCPU> cpuSet = cc.getCpus();
int matches = 0;
boolean changed = false;
for (final ICraftingCPU c : cpuSet) {
boolean found = false;
for (final CraftingCPURecord ccr : this.cpus) {
if (ccr.getCpu() == c) {
found = true;
}
}
final boolean matched = this.cpuMatches(c);
if (matched) {
matches++;
}
if (found == !matched) {
changed = true;
}
}
if (changed || this.cpus.size() != matches) {
this.cpus.clear();
for (final ICraftingCPU c : cpuSet) {
if (this.cpuMatches(c)) {
this.cpus.add(new CraftingCPURecord(c.getAvailableStorage(), c.getCoProcessors(), c));
}
}
this.sendCPUs();
}
this.noCPU = this.cpus.isEmpty();
IGrid network = this.getNetwork();
if (isServer() && network != null) {
cpuCycler.detectAndSendChanges(network);
}
super.sendContentUpdates();
@@ -113,52 +72,20 @@ public class CraftingStatusContainer extends CraftingCPUContainer {
return c.isBusy();
}
private void sendCPUs() {
Collections.sort(this.cpus);
if (this.selectedCpu >= this.cpus.size()) {
this.selectedCpu = -1;
this.myName = null;
} else if (this.selectedCpu != -1) {
this.myName = this.cpus.get(this.selectedCpu).getName();
}
if (this.selectedCpu == -1 && this.cpus.size() > 0) {
this.selectedCpu = 0;
}
if (this.selectedCpu != -1) {
if (this.cpus.get(this.selectedCpu).getCpu() != this.getMonitor()) {
this.setCPU(this.cpus.get(this.selectedCpu).getCpu());
}
private void onCPUSelectionChanged(CraftingCPURecord cpuRecord, boolean cpusAvailable) {
noCPU = !cpusAvailable;
if (cpuRecord == null) {
cpuName = null;
setCPU(null);
} else {
this.setCPU(null);
cpuName = cpuRecord.getName();
setCPU(cpuRecord.getCpu());
}
}
public void cycleCpu(final boolean next) {
if (next) {
this.selectedCpu++;
} else {
this.selectedCpu--;
}
if (this.selectedCpu < -1) {
this.selectedCpu = this.cpus.size() - 1;
} else if (this.selectedCpu >= this.cpus.size()) {
this.selectedCpu = -1;
}
if (this.selectedCpu == -1 && this.cpus.size() > 0) {
this.selectedCpu = 0;
}
if (this.selectedCpu == -1) {
this.myName = null;
this.setCPU(null);
} else {
this.myName = this.cpus.get(this.selectedCpu).getName();
this.setCPU(this.cpus.get(this.selectedCpu).getCpu());
}
@Override
public void cycleSelectedCPU(boolean forward) {
this.cpuCycler.cycleCpu(forward);
}
}
@@ -36,7 +36,6 @@ import appeng.container.slot.FakeTypeOnlySlot;
import appeng.container.slot.OptionalTypeOnlyFakeSlot;
import appeng.container.slot.RestrictedInputSlot;
import appeng.parts.automation.FormationPlanePart;
import appeng.util.Platform;
public class FormationPlaneContainer extends UpgradeableContainer {
@@ -108,7 +107,7 @@ public class FormationPlaneContainer extends UpgradeableContainer {
public void sendContentUpdates() {
this.verifyPermissions(SecurityPermissions.BUILD, false);
if (Platform.isServer()) {
if (isServer()) {
this.setFuzzyMode((FuzzyMode) this.getUpgradeable().getConfigManager().getSetting(Settings.FUZZY_MODE));
this.setPlaceMode((YesNo) this.getUpgradeable().getConfigManager().getSetting(Settings.PLACE_BLOCK));
}
@@ -35,7 +35,6 @@ import appeng.container.guisync.GuiSync;
import appeng.container.slot.OutputSlot;
import appeng.container.slot.RestrictedInputSlot;
import appeng.tile.storage.IOPortBlockEntity;
import appeng.util.Platform;
public class IOPortContainer extends UpgradeableContainer {
@@ -112,7 +111,7 @@ public class IOPortContainer extends UpgradeableContainer {
public void sendContentUpdates() {
this.verifyPermissions(SecurityPermissions.BUILD, false);
if (Platform.isServer()) {
if (isServer()) {
this.setOperationMode(
(OperationMode) this.getUpgradeable().getConfigManager().getSetting(Settings.OPERATION_MODE));
this.setFullMode(
@@ -36,7 +36,6 @@ import appeng.container.slot.RestrictedInputSlot;
import appeng.core.Api;
import appeng.tile.misc.InscriberBlockEntity;
import appeng.tile.misc.InscriberRecipes;
import appeng.util.Platform;
/**
* @author AlgorithmX2
@@ -120,7 +119,7 @@ public class InscriberContainer extends UpgradeableContainer implements IProgres
public void sendContentUpdates() {
this.standardDetectAndSendChanges();
if (Platform.isServer()) {
if (isServer()) {
this.maxProcessingTime = this.ti.getMaxProcessingTime();
this.processingTime = this.ti.getProcessingTime();
}
@@ -33,6 +33,8 @@ import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import alexiil.mc.lib.attributes.item.FixedItemInv;
import alexiil.mc.lib.attributes.item.LimitedFixedItemInv;
import alexiil.mc.lib.attributes.item.SingleItemSlot;
import appeng.api.config.SecurityPermissions;
import appeng.api.config.Settings;
@@ -43,7 +45,7 @@ import appeng.api.networking.security.IActionHost;
import appeng.container.AEBaseContainer;
import appeng.container.ContainerLocator;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.CompressedNBTPacket;
import appeng.core.sync.packets.MEInterfaceUpdatePacket;
import appeng.helpers.DualityInterface;
import appeng.helpers.IInterfaceHost;
import appeng.helpers.InventoryAction;
@@ -53,12 +55,9 @@ import appeng.parts.reporting.InterfaceTerminalPart;
import appeng.tile.inventory.AppEngInternalInventory;
import appeng.tile.misc.InterfaceBlockEntity;
import appeng.util.InventoryAdaptor;
import appeng.util.Platform;
import appeng.util.helpers.ItemHandlerUtil;
import appeng.util.inv.AdaptorFixedInv;
import appeng.util.inv.WrapperCursorItemHandler;
import appeng.util.inv.WrapperFilteredItemHandler;
import appeng.util.inv.filter.IAEItemFilter;
public final class InterfaceTerminalContainer extends AEBaseContainer {
@@ -88,7 +87,7 @@ public final class InterfaceTerminalContainer extends AEBaseContainer {
public InterfaceTerminalContainer(int id, final PlayerInventory ip, final InterfaceTerminalPart anchor) {
super(TYPE, id, ip, anchor);
if (Platform.isServer()) {
if (isServer()) {
this.grid = anchor.getActionableNode().getGrid();
}
@@ -97,7 +96,7 @@ public final class InterfaceTerminalContainer extends AEBaseContainer {
@Override
public void sendContentUpdates() {
if (Platform.isClient()) {
if (isClient()) {
return;
}
@@ -177,7 +176,7 @@ public final class InterfaceTerminalContainer extends AEBaseContainer {
if (!this.data.isEmpty()) {
try {
NetworkHandler.instance().sendTo(new CompressedNBTPacket(this.data),
NetworkHandler.instance().sendTo(new MEInterfaceUpdatePacket(this.data),
(ServerPlayerEntity) this.getPlayerInv().player);
} catch (final IOException e) {
// :P
@@ -196,35 +195,37 @@ public final class InterfaceTerminalContainer extends AEBaseContainer {
final InventoryAdaptor playerHand = new AdaptorFixedInv(new WrapperCursorItemHandler(player.inventory));
final FixedItemInv theSlot = new WrapperFilteredItemHandler(inv.server.getSubInv(slot, slot + 1),
new PatternSlotFilter());
final InventoryAdaptor interfaceSlot = new AdaptorFixedInv(theSlot);
// Create a wrapper around the targetted slot that will only allow insertions of
// patterns
LimitedFixedItemInv limitedSlotInv = inv.server.createLimitedFixedInv();
limitedSlotInv.getAllRule().filterInserts(this::isValidPattern);
SingleItemSlot theSlot = limitedSlotInv.getSlot(slot);
switch (action) {
case PICKUP_OR_SET_DOWN:
if (hasItemInHand) {
ItemStack inSlot = theSlot.getInvStack(0);
ItemStack inSlot = theSlot.get();
if (inSlot.isEmpty()) {
player.inventory.setCursorStack(interfaceSlot.addItems(player.inventory.getCursorStack()));
player.inventory.setCursorStack(theSlot.insert(player.inventory.getCursorStack()));
} else {
inSlot = inSlot.copy();
final ItemStack inHand = player.inventory.getCursorStack().copy();
ItemHandlerUtil.setStackInSlot(theSlot, 0, ItemStack.EMPTY);
theSlot.set(ItemStack.EMPTY);
player.inventory.setCursorStack(ItemStack.EMPTY);
player.inventory.setCursorStack(interfaceSlot.addItems(inHand.copy()));
player.inventory.setCursorStack(theSlot.insert(inHand.copy()));
if (player.inventory.getCursorStack().isEmpty()) {
player.inventory.setCursorStack(inSlot);
} else {
player.inventory.setCursorStack(inHand);
ItemHandlerUtil.setStackInSlot(theSlot, 0, inSlot);
theSlot.set(inSlot);
}
}
} else {
ItemHandlerUtil.setStackInSlot(theSlot, 0, playerHand.addItems(theSlot.getInvStack(0)));
theSlot.set(playerHand.addItems(theSlot.get()));
}
break;
@@ -233,18 +234,18 @@ public final class InterfaceTerminalContainer extends AEBaseContainer {
if (hasItemInHand) {
ItemStack extra = playerHand.removeItems(1, ItemStack.EMPTY, null);
if (!extra.isEmpty()) {
extra = interfaceSlot.addItems(extra);
extra = theSlot.insert(extra);
}
if (!extra.isEmpty()) {
playerHand.addItems(extra);
}
} else if (!is.isEmpty()) {
ItemStack extra = interfaceSlot.removeItems((is.getCount() + 1) / 2, ItemStack.EMPTY, null);
ItemStack extra = theSlot.extract((is.getCount() + 1) / 2);
if (!extra.isEmpty()) {
extra = playerHand.addItems(extra);
}
if (!extra.isEmpty()) {
interfaceSlot.addItems(extra);
theSlot.insert(extra);
}
}
@@ -252,8 +253,7 @@ public final class InterfaceTerminalContainer extends AEBaseContainer {
case SHIFT_CLICK:
final InventoryAdaptor playerInv = InventoryAdaptor.getAdaptor(player);
ItemHandlerUtil.setStackInSlot(theSlot, 0, playerInv.addItems(theSlot.getInvStack(0)));
theSlot.set(playerInv.addItems(theSlot.get()));
break;
case MOVE_REGION:
@@ -279,6 +279,10 @@ public final class InterfaceTerminalContainer extends AEBaseContainer {
}
}
private boolean isValidPattern(ItemStack stack) {
return !stack.isEmpty() && stack.getItem() instanceof EncodedPatternItem;
}
private void regenList(final CompoundTag data) {
this.byId.clear();
this.diList.clear();
@@ -369,15 +373,4 @@ public final class InterfaceTerminalContainer extends AEBaseContainer {
}
}
private static class PatternSlotFilter implements IAEItemFilter {
@Override
public boolean allowExtract(FixedItemInv inv, int slot, int amount) {
return true;
}
@Override
public boolean allowInsert(FixedItemInv inv, int slot, ItemStack stack) {
return !stack.isEmpty() && stack.getItem() instanceof EncodedPatternItem;
}
}
}
@@ -18,8 +18,6 @@
package appeng.container.implementations;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.network.PacketByteBuf;
@@ -33,13 +31,13 @@ import appeng.api.config.RedstoneMode;
import appeng.api.config.SecurityPermissions;
import appeng.api.config.Settings;
import appeng.api.config.YesNo;
import appeng.client.gui.implementations.NumberEntryWidget;
import appeng.container.ContainerLocator;
import appeng.container.guisync.GuiSync;
import appeng.container.slot.FakeTypeOnlySlot;
import appeng.container.slot.RestrictedInputSlot;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ConfigValuePacket;
import appeng.parts.automation.LevelEmitterPart;
import appeng.util.Platform;
public class LevelEmitterContainer extends UpgradeableContainer {
@@ -49,38 +47,46 @@ public class LevelEmitterContainer extends UpgradeableContainer {
LevelEmitterContainer::new, LevelEmitterPart.class, SecurityPermissions.BUILD);
public static LevelEmitterContainer fromNetwork(int windowId, PlayerInventory inv, PacketByteBuf buf) {
return helper.fromNetwork(windowId, inv, buf);
return helper.fromNetwork(windowId, inv, buf, (host, container, buffer) -> {
container.reportingValue = buffer.readVarLong();
});
}
public static boolean open(PlayerEntity player, ContainerLocator locator) {
return helper.open(player, locator);
return helper.open(player, locator, (host, buffer) -> {
buffer.writeVarLong(host.getReportingValue());
});
}
private final LevelEmitterPart lvlEmitter;
@Environment(EnvType.CLIENT)
private NumberEntryWidget textField;
@GuiSync(2)
public LevelType lvType;
@GuiSync(3)
public long EmitterValue = -1;
@GuiSync(4)
public YesNo cmType;
// Only synced once on container-open, and only used on client
private long reportingValue;
public LevelEmitterContainer(int id, final PlayerInventory ip, final LevelEmitterPart te) {
super(TYPE, id, ip, te);
this.lvlEmitter = te;
}
@Environment(EnvType.CLIENT)
public void setTextField(final NumberEntryWidget level) {
this.textField = level;
this.textField.setValue(this.EmitterValue);
public long getReportingValue() {
return reportingValue;
}
public void setLevel(final long l, final PlayerEntity player) {
this.lvlEmitter.setReportingValue(l);
this.EmitterValue = l;
public void setReportingValue(long reportingValue) {
if (isClient()) {
if (reportingValue != this.reportingValue) {
this.reportingValue = reportingValue;
NetworkHandler.instance()
.sendToServer(new ConfigValuePacket("LevelEmitter.Value", String.valueOf(reportingValue)));
}
} else {
this.lvlEmitter.setReportingValue(reportingValue);
}
}
@Override
@@ -116,7 +122,6 @@ public class LevelEmitterContainer extends UpgradeableContainer {
@Override
public int availableUpgrades() {
return 1;
}
@@ -124,8 +129,7 @@ public class LevelEmitterContainer extends UpgradeableContainer {
public void sendContentUpdates() {
this.verifyPermissions(SecurityPermissions.BUILD, false);
if (Platform.isServer()) {
this.EmitterValue = this.lvlEmitter.getReportingValue();
if (isServer()) {
this.setCraftingMode(
(YesNo) this.getUpgradeable().getConfigManager().getSetting(Settings.CRAFT_VIA_REDSTONE));
this.setLevelMode((LevelType) this.getUpgradeable().getConfigManager().getSetting(Settings.LEVEL_TYPE));
@@ -137,15 +141,6 @@ public class LevelEmitterContainer extends UpgradeableContainer {
this.standardDetectAndSendChanges();
}
@Override
public void onUpdate(final String field, final Object oldValue, final Object newValue) {
if (field.equals("EmitterValue")) {
if (this.textField != null) {
this.textField.setValue(this.EmitterValue);
}
}
}
@Override
public YesNo getCraftingMode() {
return this.cmType;
@@ -163,4 +158,5 @@ public class LevelEmitterContainer extends UpgradeableContainer {
private void setLevelMode(final LevelType lvType) {
this.lvType = lvType;
}
}
@@ -46,6 +46,8 @@ import appeng.api.implementations.tiles.IViewCellStorage;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.ICraftingCPU;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.energy.IEnergySource;
import appeng.api.networking.security.IActionHost;
@@ -73,7 +75,6 @@ import appeng.core.sync.packets.MEInventoryUpdatePacket;
import appeng.me.helpers.ChannelPowerSrc;
import appeng.util.ConfigManager;
import appeng.util.IConfigManagerHost;
import appeng.util.Platform;
public class MEMonitorableContainer extends AEBaseContainer
implements IConfigManagerHost, IConfigurableObject, IMEMonitorHandlerReceiver<IAEItemStack> {
@@ -101,6 +102,13 @@ public class MEMonitorableContainer extends AEBaseContainer
public boolean canAccessViewCells = false;
@GuiSync(98)
public boolean hasPower = false;
/**
* The number of active crafting jobs in the network. -1 means unknown and will
* hide the label on the screen.
*/
@GuiSync(100)
public int activeCraftingJobs = -1;
private IConfigManagerHost gui;
private IConfigManager serverCM;
private IGridNode networkNode;
@@ -122,7 +130,7 @@ public class MEMonitorableContainer extends AEBaseContainer
this.clientCM.registerSetting(Settings.VIEW_MODE, ViewItems.ALL);
this.clientCM.registerSetting(Settings.SORT_DIRECTION, SortDir.ASCENDING);
if (Platform.isServer()) {
if (isServer()) {
this.serverCM = monitorable.getConfigManager();
this.monitor = monitorable
@@ -183,12 +191,14 @@ public class MEMonitorableContainer extends AEBaseContainer
@Override
public void sendContentUpdates() {
if (Platform.isServer()) {
if (isServer()) {
if (this.monitor != this.host
.getInventory(Api.instance().storage().getStorageChannel(IItemStorageChannel.class))) {
this.setValidContainer(false);
}
this.updateActiveCraftingJobs();
for (final Settings set : this.serverCM.getSettings()) {
final Enum<?> sideLocal = this.serverCM.getSetting(set);
final Enum<?> sideRemote = this.clientCM.getSetting(set);
@@ -286,8 +296,38 @@ public class MEMonitorableContainer extends AEBaseContainer
this.queueInventory(c);
}
private void updateActiveCraftingJobs() {
IGridNode hostNode = networkNode;
if (hostNode == null) {
// Wireless terminals do not directly expose the target grid (even though they
// have one)
if (host instanceof IActionHost) {
hostNode = ((IActionHost) host).getActionableNode();
}
}
IGrid grid = null;
if (hostNode != null) {
grid = hostNode.getGrid();
}
if (grid == null) {
// No grid to query crafting jobs from
this.activeCraftingJobs = -1;
return;
}
int activeJobs = 0;
ICraftingGrid craftingGrid = grid.getCache(ICraftingGrid.class);
for (ICraftingCPU cpus : craftingGrid.getCpus()) {
if (cpus.isBusy()) {
activeJobs++;
}
}
this.activeCraftingJobs = activeJobs;
}
private void queueInventory(final ScreenHandlerListener c) {
if (Platform.isServer() && c instanceof PlayerEntity && this.monitor != null) {
if (isServer() && c instanceof PlayerEntity && this.monitor != null) {
try {
MEInventoryUpdatePacket piu = new MEInventoryUpdatePacket();
final IItemList<IAEItemStack> monitorCache = this.monitor.getStorageList();
@@ -356,7 +396,7 @@ public class MEMonitorableContainer extends AEBaseContainer
@Override
public IConfigManager getConfigManager() {
if (Platform.isServer()) {
if (isServer()) {
return this.serverCM;
}
return this.clientCM;
@@ -42,7 +42,6 @@ import appeng.container.slot.RestrictedInputSlot;
import appeng.core.Api;
import appeng.items.misc.EncodedPatternItem;
import appeng.tile.crafting.MolecularAssemblerBlockEntity;
import appeng.util.Platform;
public class MolecularAssemblerContainer extends UpgradeableContainer implements IProgressProvider {
@@ -148,7 +147,7 @@ public class MolecularAssemblerContainer extends UpgradeableContainer implements
public void sendContentUpdates() {
this.verifyPermissions(SecurityPermissions.BUILD, false);
if (Platform.isServer()) {
if (isServer()) {
this.setRedStoneMode(
(RedstoneMode) this.getUpgradeable().getConfigManager().getSetting(Settings.REDSTONE_CONTROLLED));
}
@@ -43,7 +43,6 @@ import appeng.container.guisync.GuiSync;
import appeng.core.Api;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.MEInventoryUpdatePacket;
import appeng.util.Platform;
import appeng.util.item.AEItemStack;
public class NetworkStatusContainer extends AEBaseContainer {
@@ -83,7 +82,7 @@ public class NetworkStatusContainer extends AEBaseContainer {
}
}
if (this.network == null && Platform.isServer()) {
if (this.network == null && isServer()) {
this.setValidContainer(false);
}
}
@@ -100,7 +99,7 @@ public class NetworkStatusContainer extends AEBaseContainer {
@Override
public void sendContentUpdates() {
this.delay++;
if (Platform.isServer() && this.delay > 15 && this.network != null) {
if (isServer() && this.delay > 15 && this.network != null) {
this.delay = 0;
final IEnergyGrid eg = this.network.getCache(IEnergyGrid.class);
@@ -297,9 +297,9 @@ public class PatternTermContainer extends MEMonitorableContainer
@Override
public boolean isSlotEnabled(final int idx) {
if (idx == 1) {
return Platform.isServer() ? !this.getPatternTerminal().isCraftingRecipe() : !this.isCraftingMode();
return isServer() ? !this.getPatternTerminal().isCraftingRecipe() : !this.isCraftingMode();
} else if (idx == 2) {
return Platform.isServer() ? this.getPatternTerminal().isCraftingRecipe() : this.isCraftingMode();
return isServer() ? this.getPatternTerminal().isCraftingRecipe() : this.isCraftingMode();
} else {
return false;
}
@@ -401,7 +401,7 @@ public class PatternTermContainer extends MEMonitorableContainer
@Override
public void sendContentUpdates() {
super.sendContentUpdates();
if (Platform.isServer()) {
if (isServer()) {
if (this.isCraftingMode() != this.getPatternTerminal().isCraftingRecipe()) {
this.setCraftingMode(this.getPatternTerminal().isCraftingRecipe());
this.updateOrderOfOutputSlots();
@@ -423,7 +423,7 @@ public class PatternTermContainer extends MEMonitorableContainer
@Override
public void onSlotChange(final Slot s) {
if (s == this.patternSlotOUT && Platform.isServer()) {
if (s == this.patternSlotOUT && isServer()) {
for (final ScreenHandlerListener listener : this.getListeners()) {
for (int i = 0; i < this.slots.size(); i++) {
Slot slot = this.slots.get(i);
@@ -438,7 +438,7 @@ public class PatternTermContainer extends MEMonitorableContainer
this.sendContentUpdates();
}
if (s == this.craftSlot && Platform.isClient()) {
if (s == this.craftSlot && isClient()) {
this.getAndUpdateOutput();
}
}
@@ -18,8 +18,6 @@
package appeng.container.implementations;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
@@ -28,12 +26,11 @@ import net.minecraft.screen.ScreenHandlerType;
import appeng.api.config.SecurityPermissions;
import appeng.api.parts.IPart;
import appeng.client.gui.implementations.NumberEntryWidget;
import appeng.container.AEBaseContainer;
import appeng.container.ContainerLocator;
import appeng.container.guisync.GuiSync;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ConfigValuePacket;
import appeng.helpers.IPriorityHost;
import appeng.util.Platform;
public class PriorityContainer extends AEBaseContainer {
@@ -43,59 +40,53 @@ public class PriorityContainer extends AEBaseContainer {
PriorityContainer::new, IPriorityHost.class, SecurityPermissions.BUILD);
public static PriorityContainer fromNetwork(int windowId, PlayerInventory inv, PacketByteBuf buf) {
return helper.fromNetwork(windowId, inv, buf);
return helper.fromNetwork(windowId, inv, buf, (host, container, buffer) -> {
container.priorityValue = buffer.readVarInt();
});
}
public static boolean open(PlayerEntity player, ContainerLocator locator) {
return helper.open(player, locator);
return helper.open(player, locator, (host, buffer) -> buffer.writeVarInt(host.getPriority()));
}
private final IPriorityHost priHost;
@Environment(EnvType.CLIENT)
private NumberEntryWidget textField;
@GuiSync(2)
public long PriorityValue = -1;
private int priorityValue;
public PriorityContainer(int id, final PlayerInventory ip, final IPriorityHost te) {
super(TYPE, id, ip, (BlockEntity) (te instanceof BlockEntity ? te : null),
(IPart) (te instanceof IPart ? te : null));
this.priHost = te;
this.priorityValue = te.getPriority();
}
@Environment(EnvType.CLIENT)
public void setTextField(final NumberEntryWidget level) {
this.textField = level;
this.textField.setValue(this.PriorityValue, true);
}
public void setPriority(final int newValue, final PlayerEntity player) {
this.priHost.setPriority(newValue);
this.PriorityValue = newValue;
public void setPriority(final int newValue) {
if (newValue != priorityValue) {
if (isClient()) {
// If for whatever reason the client enters the value first, do not update based
// on incoming server data
this.priorityValue = newValue;
NetworkHandler.instance()
.sendToServer(new ConfigValuePacket("PriorityHost.Priority", String.valueOf(newValue)));
} else {
this.priHost.setPriority(newValue);
this.priorityValue = newValue;
}
}
}
@Override
public void sendContentUpdates() {
super.sendContentUpdates();
this.verifyPermissions(SecurityPermissions.BUILD, false);
if (Platform.isServer()) {
this.PriorityValue = this.priHost.getPriority();
}
}
@Override
public void onUpdate(final String field, final Object oldValue, final Object newValue) {
if (field.equals("PriorityValue")) {
if (this.textField != null) {
this.textField.setValue(this.PriorityValue, true);
}
}
super.onUpdate(field, oldValue, newValue);
public int getPriorityValue() {
return priorityValue;
}
public IPriorityHost getPriorityHost() {
return this.priHost;
}
}
@@ -37,7 +37,6 @@ import appeng.core.Api;
import appeng.items.contents.QuartzKnifeObj;
import appeng.items.materials.MaterialItem;
import appeng.tile.inventory.AppEngInternalInventory;
import appeng.util.Platform;
public class QuartzKnifeContainer extends AEBaseContainer {
@@ -142,10 +141,12 @@ public class QuartzKnifeContainer extends AEBaseContainer {
}
private void makePlate() {
if (Platform.isServer()) {
if (!this.takeStack(1).isEmpty()) {
if (isServer()) {
if (!inSlot.getSlot(0).extract(1).isEmpty()) {
final ItemStack item = QuartzKnifeContainer.this.toolInv.getItemStack();
final ItemStack before = item.copy();
// FIXME FABRIC: Quartz Knife currently is not damageable due to recipe
// remainder concerns
item.damage(1, QuartzKnifeContainer.this.getPlayerInv().player, p -> {
QuartzKnifeContainer.this.getPlayerInv()
.setStack(QuartzKnifeContainer.this.getPlayerInv().selectedSlot, ItemStack.EMPTY);
@@ -35,7 +35,6 @@ import appeng.container.guisync.GuiSync;
import appeng.container.slot.OutputSlot;
import appeng.container.slot.RestrictedInputSlot;
import appeng.tile.spatial.SpatialIOPortBlockEntity;
import appeng.util.Platform;
public class SpatialIOPortContainer extends AEBaseContainer {
@@ -65,7 +64,7 @@ public class SpatialIOPortContainer extends AEBaseContainer {
public SpatialIOPortContainer(int id, final PlayerInventory ip, final SpatialIOPortBlockEntity spatialIOPort) {
super(TYPE, id, ip, spatialIOPort, null);
if (Platform.isServer()) {
if (isServer()) {
this.network = spatialIOPort.getGridNode(AEPartLocation.INTERNAL).getGrid();
}
@@ -89,7 +88,7 @@ public class SpatialIOPortContainer extends AEBaseContainer {
public void sendContentUpdates() {
this.verifyPermissions(SecurityPermissions.BUILD, false);
if (Platform.isServer()) {
if (isServer()) {
this.delay++;
if (this.delay > 15 && this.network != null) {
this.delay = 0;
@@ -45,7 +45,6 @@ import appeng.container.slot.OptionalTypeOnlyFakeSlot;
import appeng.container.slot.RestrictedInputSlot;
import appeng.core.Api;
import appeng.parts.misc.StorageBusPart;
import appeng.util.Platform;
import appeng.util.helpers.ItemHandlerUtil;
import appeng.util.iterators.NullIterator;
@@ -125,7 +124,7 @@ public class StorageBusContainer extends UpgradeableContainer {
public void sendContentUpdates() {
this.verifyPermissions(SecurityPermissions.BUILD, false);
if (Platform.isServer()) {
if (isServer()) {
this.setFuzzyMode((FuzzyMode) this.getUpgradeable().getConfigManager().getSetting(Settings.FUZZY_MODE));
this.setReadWriteMode(
(AccessRestriction) this.getUpgradeable().getConfigManager().getSetting(Settings.ACCESS));
@@ -52,7 +52,6 @@ import appeng.container.slot.RestrictedInputSlot;
import appeng.items.contents.NetworkToolViewer;
import appeng.items.tools.NetworkToolItem;
import appeng.parts.automation.ExportBusPart;
import appeng.util.Platform;
public class UpgradeableContainer extends AEBaseContainer implements IOptionalSlotHost {
@@ -200,7 +199,7 @@ public class UpgradeableContainer extends AEBaseContainer implements IOptionalSl
public void sendContentUpdates() {
this.verifyPermissions(SecurityPermissions.BUILD, false);
if (Platform.isServer()) {
if (isServer()) {
final IConfigManager cm = this.getUpgradeable().getConfigManager();
this.loadSettingsFromHost(cm);
}
@@ -29,7 +29,6 @@ import appeng.container.guisync.GuiSync;
import appeng.container.interfaces.IProgressProvider;
import appeng.container.slot.RestrictedInputSlot;
import appeng.tile.misc.VibrationChamberBlockEntity;
import appeng.util.Platform;
public class VibrationChamberContainer extends AEBaseContainer implements IProgressProvider {
@@ -65,7 +64,7 @@ public class VibrationChamberContainer extends AEBaseContainer implements IProgr
@Override
public void sendContentUpdates() {
if (Platform.isServer()) {
if (isServer()) {
this.remainingBurnTime = this.vibrationChamber.getMaxBurnTime() <= 0 ? 0
: (int) (100.0 * this.vibrationChamber.getBurnTime() / this.vibrationChamber.getMaxBurnTime());
this.burnSpeed = this.remainingBurnTime <= 0 ? 0 : this.vibrationChamber.getBurnSpeed();
@@ -28,7 +28,6 @@ import appeng.container.ContainerLocator;
import appeng.core.AEConfig;
import appeng.core.localization.PlayerMessages;
import appeng.helpers.WirelessTerminalGuiObject;
import appeng.util.Platform;
public class WirelessTermContainer extends MEPortableCellContainer {
@@ -57,7 +56,7 @@ public class WirelessTermContainer extends MEPortableCellContainer {
super.sendContentUpdates();
if (!this.wirelessTerminalGUIObject.rangeCheck()) {
if (Platform.isServer() && this.isValidContainer()) {
if (isServer() && this.isValidContainer()) {
this.getPlayerInv().player.sendSystemMessage(PlayerMessages.OutOfRange.get(), Util.NIL_UUID);
}
@@ -165,7 +165,7 @@ public class RestrictedInputSlot extends AppEngSlot {
case ORE:
return GrinderRecipes.isValidIngredient(p.player.world, stack);
case FUEL:
return FuelRegistry.INSTANCE.get(stack.getItem()) > 0;
return FuelRegistry.INSTANCE.get(stack.getItem()) != null;
case POWERED_TOOL:
return Platform.isChargeable(stack);
case QE_SINGULARITY:
+45 -12
View File
@@ -25,14 +25,14 @@ import java.util.Collection;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.DoubleSupplier;
import java.util.stream.Collectors;
import net.minecraft.world.dimension.DimensionType;
import javax.annotation.Nullable;
import com.google.common.base.Strings;
import appeng.api.config.CondenserOutput;
import appeng.api.config.PowerMultiplier;
@@ -50,6 +50,7 @@ import appeng.core.config.DoubleOption;
import appeng.core.config.EnumOption;
import appeng.core.config.IntegerOption;
import appeng.core.config.StringListOption;
import appeng.core.config.StringOption;
import appeng.core.settings.TickRates;
import appeng.util.EnumCycler;
@@ -81,6 +82,13 @@ public final class AEConfig {
result.save(); // Save a default file
} else {
result.load();
// Re-save immediately to write-out new defaults
try {
result.save();
} catch (Exception e) {
AELog.warn(e);
}
}
return result;
}
@@ -137,7 +145,6 @@ public final class AEConfig {
// Meteors
private int meteoriteMaximumSpawnHeight;
private Set<String> meteoriteDimensionWhitelist;
// Wireless
private double wirelessBaseCost;
@@ -175,7 +182,6 @@ public final class AEConfig {
this.oreDoublePercentage = (float) commonConfig.oreDoublePercentage.get();
this.meteoriteMaximumSpawnHeight = commonConfig.meteoriteMaximumSpawnHeight.get();
this.meteoriteDimensionWhitelist = new HashSet<>(commonConfig.meteoriteDimensionWhitelist.get());
this.wirelessBaseCost = commonConfig.wirelessBaseCost.get();
this.wirelessCostMultiplier = commonConfig.wirelessCostMultiplier.get();
@@ -389,8 +395,21 @@ public final class AEConfig {
return this.meteoriteMaximumSpawnHeight;
}
public Set<String> getMeteoriteDimensionWhitelist() {
return this.meteoriteDimensionWhitelist;
public List<String> getMeteoriteBiomeBlacklist() {
return commonConfig.meteoriteBiomeBlacklist.get();
}
public List<String> getQuartzOreBiomeBlacklist() {
return commonConfig.quartzOreBiomeBlacklist.get();
}
@Nullable
public String getImprovedFluidTag() {
return Strings.emptyToNull(commonConfig.improvedFluidTag.get());
}
public float getImprovedFluidMultiplier() {
return (float) commonConfig.improvedFluidMultiplier.get();
}
// Setters keep visibility as low as possible.
@@ -478,10 +497,11 @@ public final class AEConfig {
public final DoubleOption spawnChargedChance;
public final IntegerOption quartzOresPerCluster;
public final IntegerOption quartzOresClusterAmount;
public final StringListOption quartzOreBiomeBlacklist;
// Meteors
public final IntegerOption meteoriteMaximumSpawnHeight;
public final StringListOption meteoriteDimensionWhitelist;
public final StringListOption meteoriteBiomeBlacklist;
// Wireless
public final DoubleOption wirelessBaseCost;
@@ -504,6 +524,11 @@ public final class AEConfig {
public final IntegerOption condenserMatterBallsPower;
public final IntegerOption condenserSingularityPower;
// In-World Purification
// Settings for improved speed depending on fluid the crystal is in
public final StringOption improvedFluidTag;
public final DoubleOption improvedFluidMultiplier;
public final Map<TickRates, IntegerOption> tickRateMin = new HashMap<>();
public final Map<TickRates, IntegerOption> tickRateMax = new HashMap<>();
@@ -562,13 +587,13 @@ public final class AEConfig {
this.spawnChargedChance = worldGen.addDouble("spawnChargedChance", 0.08, 0.0, 1.0);
this.meteoriteMaximumSpawnHeight = worldGen.addInt("meteoriteMaximumSpawnHeight", 180);
List<String> defaultDimensionWhitelist = new ArrayList<>();
defaultDimensionWhitelist.add(DimensionType.OVERWORLD_REGISTRY_KEY.getValue().toString());
this.meteoriteDimensionWhitelist = worldGen.addStringList("meteoriteDimensionWhitelist",
defaultDimensionWhitelist);
this.meteoriteBiomeBlacklist = worldGen.addStringList("meteoriteBiomeBlacklist", new ArrayList<>(),
"Biome IDs in which meteorites should NOT be generated (i.e. minecraft:plains).");
this.quartzOresPerCluster = worldGen.addInt("quartzOresPerCluster", 4);
this.quartzOresClusterAmount = worldGen.addInt("quartzOresClusterAmount", 20);
this.quartzOreBiomeBlacklist = worldGen.addStringList("quartzOreBiomeBlacklist", new ArrayList<>(),
"Biome IDs in which quartz ores should NOT be generated (i.e. minecraft:plains).");
ConfigSection wireless = root.subsection("wireless");
this.wirelessBaseCost = wireless.addDouble("wirelessBaseCost", 8.0);
@@ -598,6 +623,14 @@ public final class AEConfig {
tickRateMin.put(tickRate, tickrates.addInt(tickRate.name() + "Min", tickRate.getDefaultMin()));
tickRateMax.put(tickRate, tickrates.addInt(tickRate.name() + "Max", tickRate.getDefaultMax()));
}
ConfigSection inWorldPurification = root.subsection("inWorldPurification",
"Settings for in-world purification of crystals.");
improvedFluidTag = inWorldPurification.addString("improvedFluidTag", "",
"A fluid tag that identifies fluids that improve crystal purification speed. Does not affect purification with water/lava.");
improvedFluidMultiplier = inWorldPurification.addDouble("improvedFluidMultiplier", 2.0, 1.0, 10.0,
"The speed multiplier to use when the crystals are submerged in the improved fluid.");
}
}
-24
View File
@@ -30,14 +30,8 @@ import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.World;
import net.minecraft.world.dimension.DimensionType;
import team.reborn.energy.Energy;
import team.reborn.energy.EnergyHandler;
import team.reborn.energy.EnergyHolder;
import appeng.api.config.Upgrades;
import appeng.api.definitions.IBlocks;
@@ -45,8 +39,6 @@ import appeng.api.definitions.IItems;
import appeng.api.definitions.IParts;
import appeng.api.features.IRegistryContainer;
import appeng.api.features.IWirelessTermHandler;
import appeng.api.features.IWorldGen;
import appeng.api.implementations.items.IAEItemPowerStorage;
import appeng.api.movable.IMovableRegistry;
import appeng.api.networking.IGridCacheRegistry;
import appeng.api.networking.crafting.ICraftingGrid;
@@ -57,7 +49,6 @@ import appeng.api.networking.spatial.ISpatialCache;
import appeng.api.networking.storage.IStorageGrid;
import appeng.api.networking.ticking.ITickManager;
import appeng.api.parts.CableRenderMode;
import appeng.block.AEBaseBlockItemChargeable;
import appeng.bootstrap.IBootstrapComponent;
import appeng.bootstrap.components.ITileEntityRegistrationComponent;
import appeng.client.render.effects.ParticleTypes;
@@ -351,21 +342,6 @@ public abstract class AppEngBase implements AppEng {
*/
mr.whiteListBlockEntity(AEBaseBlockEntity.class);
/*
* world gen
*/
for (final IWorldGen.WorldGenType type : IWorldGen.WorldGenType.values()) {
// FIXME: registries.worldgen().disableWorldGenForProviderID( type,
// StorageWorldProvider.class );
registries.worldgen().disableWorldGenForDimension(type, DimensionType.THE_NETHER_REGISTRY_KEY.getValue());
}
// whitelist from config
for (final String dimension : AEConfig.instance().getMeteoriteDimensionWhitelist()) {
registries.worldgen().enableWorldGenForDimension(IWorldGen.WorldGenType.METEORITES,
new Identifier(dimension));
}
}
protected void registerParticleTypes() {
+43 -9
View File
@@ -1,9 +1,16 @@
package appeng.core;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.fabricmc.fabric.api.event.registry.RegistryEntryAddedCallback;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.block.BlockState;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.GenerationStep;
import net.minecraft.world.gen.decorator.Decorator;
@@ -54,11 +61,21 @@ public final class AppEngBootstrap {
ConfiguredFeature<?, ?> quartzOreFeature = registerQuartzOreFeature();
ConfiguredFeature<?, ?> chargedQuartzOreFeature = registerChargedQuartzOreFeature();
// add to all standard biomes
// TODO: This means we'll not add these things to newly created biomes
BuiltinRegistries.BIOME.forEach(b -> {
addMeteoriteWorldGen(b);
addQuartzWorldGen(b, quartzOreFeature, chargedQuartzOreFeature);
Set<String> meteoriteBiomeBlacklist = new HashSet<>(AEConfig.instance().getMeteoriteBiomeBlacklist());
Set<String> quartzOreBiomeBlacklist = new HashSet<>(AEConfig.instance().getQuartzOreBiomeBlacklist());
// Add features to all existing biomes
for (Map.Entry<RegistryKey<Biome>, Biome> entry : BuiltinRegistries.BIOME.getEntries()) {
Identifier id = entry.getKey().getValue();
Biome b = entry.getValue();
addMeteoriteWorldGen(id, b, meteoriteBiomeBlacklist);
addQuartzWorldGen(id, b, quartzOreFeature, chargedQuartzOreFeature, quartzOreBiomeBlacklist);
}
// Listen to added biomes for post-processing
RegistryEntryAddedCallback.event(BuiltinRegistries.BIOME).register((i, id, biome) -> {
addMeteoriteWorldGen(id, biome, meteoriteBiomeBlacklist);
addQuartzWorldGen(id, biome, quartzOreFeature, chargedQuartzOreFeature, quartzOreBiomeBlacklist);
});
registerDimension();
@@ -78,12 +95,19 @@ public final class AppEngBootstrap {
MeteoriteStructure.CONFIGURED_INSTANCE);
}
private static void addMeteoriteWorldGen(Biome b) {
private static void addMeteoriteWorldGen(Identifier id, Biome b, Set<String> biomeBlacklist) {
if (!AEConfig.instance().isFeatureEnabled(AEFeature.METEORITE_WORLD_GEN)) {
AELog.debug("Not generating meteorites in %s because the feature is disabled", id);
return;
}
if (b.getCategory() == Biome.Category.THEEND || b.getCategory() == Biome.Category.NETHER) {
AELog.debug("Not generating meteorites in %s because it's of category %s", id, b.getCategory());
return;
}
if (biomeBlacklist.contains(id.toString())) {
AELog.debug("Not generating meteorites in %s because the biome is blacklisted in the config", id);
return;
}
@@ -91,14 +115,24 @@ public final class AppEngBootstrap {
modifier.addStructureFeature(MeteoriteStructure.CONFIGURED_INSTANCE);
}
private static void addQuartzWorldGen(Biome b, ConfiguredFeature<?, ?> quartzOre,
ConfiguredFeature<?, ?> chargedQuartz) {
private static void addQuartzWorldGen(Identifier id, Biome b, ConfiguredFeature<?, ?> quartzOre,
ConfiguredFeature<?, ?> chargedQuartz, Set<String> biomeBlacklist) {
if (!AEConfig.instance().isFeatureEnabled(AEFeature.CERTUS_QUARTZ_WORLD_GEN)) {
AELog.debug("Not generating quartz-ore in %s because the feature is disabled", id);
return;
}
if (b.getCategory() == Biome.Category.THEEND || b.getCategory() == Biome.Category.NETHER) {
AELog.debug("Not generating quartz ore in %s because it's of category %s", id, b.getCategory());
return;
}
if (biomeBlacklist.contains(id.toString())) {
AELog.debug("Not generating quartz-ore in %s because the biome is blacklisted in the config", id);
return;
}
BiomeModifier modifier = new BiomeModifier(b);
modifier.addFeature(GenerationStep.Feature.UNDERGROUND_ORES, quartzOre);
if (AEConfig.instance().isFeatureEnabled(AEFeature.CHARGED_CERTUS_ORE)) {

Some files were not shown because too many files have changed in this diff Show More