Compare commits

...

65 Commits

Author SHA1 Message Date
shartte 27b8c5f3ac Plane Connection Refactor (#4556) (#4565)
* Refactors all plane parts to use a common helper for
calculating connections to adjacent planes.
Also fixes problems with updating these connections on neighbor updates.

* Fix conflicting GuiSync ID.

* Slightly refactor PlaneConnectionHelper, and fix an issue where the bounding box was calculated incorrectly by using the wrong up-direction.

(cherry picked from commit 8617dc8340)
2020-08-05 22:39:04 +02:00
shartte 3043887915 Makes formation planes a bit more consistent and less violent. (#4553) (#4564)
* Makes formation planes a bit more consistent and less violent.

Items will now have a slower speed when spawning as well as a narrower area to avoid having them glitch into a wall and be teleported around

* Removed debug output, added clarifying parenthesis and extracted method.

* Fixes various other issues with the formation plane

Also removed now useless code

(cherry picked from commit 12e3fa9127)
2020-08-05 22:25:48 +02:00
yueh e0abe9b9a9 Fixes #4559: Use visual bounding box for overlay (#4562) 2020-08-05 22:08:48 +02:00
shartte e19991f1f9 Fixes #4547: Name clash between ITooltip#getWidth, ITooltip#getHeight and Vanilla Widget methods leads to missing methods at runtime, since the implementing methods will be remapped to SRG names, while referees of the interface will try to call the renamed methods by their name in the interface, leading to an AbstractMethodError. (#4558) 2020-08-05 18:21:13 +02:00
shartte 3d97b1e3ec Fixes #4551: Bounding box of annihilation planes is too small. (#4552) 2020-08-05 17:45:53 +02:00
yueh 6b1bccffb9 Apply the FE tunnel behaviour to the fluid tunnel (#4550) (#4555) 2020-08-04 23:37:15 +02:00
yueh 6fab7b91b7 Fixes 4529: Updated IPart to match new ICapabilityProvider (#4534) (#4536) 2020-08-01 21:57:26 +02:00
shartte 7b6bab4967 Fix #4521: Register RecipeTypes. (#4523) (#4525) 2020-07-31 20:34:44 +02:00
yueh 04766e5325 Limit gradle to 1 worker for 1.15 (#4526) 2020-07-31 18:51:41 +02:00
yueh 662dbca3e1 Fixes #4508: Correctly construct the sparse lists. (#4511)
* Fixes #4508: Correctly construct the sparse lists.

Also renamed all uncondensed getters to sparse and all condensed to the simple ones.

* Apply suggestions from code review

Co-authored-by: shartte <shartte@users.noreply.github.com>

* Streamlined collapsing the sparse lists

* Extracted helper to condense stacks

* Sort lists desc by stack size

Co-authored-by: shartte <shartte@users.noreply.github.com>
2020-07-27 11:21:06 +02:00
Sebastian Hartte 6cb6c21495 Mention spotlessApply. 2020-07-26 23:29:34 +02:00
Sebastian Hartte 79e9a3913a Update README.md to reflect that the data generation needs to be run. 2020-07-26 23:29:01 +02:00
shartte 7e89317dd5 Fix substitutions not being correctly recognized. (#4507) 2020-07-26 22:25:18 +02:00
shartte 59e40ccbd9 Fixes mouse handling for right-clicks to clear the search box and middle-click for crafting. (#4505) 2020-07-26 16:30:53 +02:00
yueh 774f88ee90 Clear searchfield on rightclick (#4503) 2020-07-26 15:28:52 +02:00
yueh 0528879833 Moved datagens to appeng.datagen (#4502) 2020-07-26 15:28:18 +02:00
yueh b6110e4f4a Remove all maven repos except modmaven (#4501)
Also upgrades gradle to 4.10.3
2020-07-26 15:27:32 +02:00
yueh 5b82e59264 Removed superfluous crash enhancement (#4498) 2020-07-26 12:42:48 +02:00
yueh 3a4b171443 Fixes #4468: Default to ae serverside (#4496) 2020-07-25 16:05:58 +02:00
yueh 2ac27fd9ce Fixes patterns always returning a recipe. (#4495) 2020-07-24 22:39:38 +02:00
shartte d01aa28cdc Use standard mechanics for damaging the quartz knife. (#4494) 2020-07-24 16:39:32 +02:00
shartte 21aa5ce33b Don't use PacketBuffer#readString since it's client-only. (#4489)
Fixes #4488
2020-07-22 10:22:28 +02:00
shartte f7ef6eb772 Same method name as in superclass leads to ForgeGradle reobf problems. (#4491)
Fixes #4490
2020-07-22 10:22:00 +02:00
shartte 10037a9ac5 Correct link to CurseForge page 2020-07-21 18:39:48 +02:00
yueh 888de430ba Also test for generated asset cache 2020-07-20 22:27:01 +02:00
A. Regnander 83d661ab2a Create sv_se.json (#4485) 2020-07-20 21:33:44 +02:00
shartte a537bcf0ee Merge pull request #4486 from AppliedEnergistics/number-entry-dialogs
Number Entry Dialogs
2020-07-20 20:13:04 +02:00
Sebastian Hartte 590e435ad6 Formatting fixes 2020-07-19 23:51:57 +02:00
Sebastian Hartte 8d92a51e4f Formatting fixes 2020-07-19 23:50:47 +02:00
Sebastian Hartte 4322910614 Added labels that specify the unit of power (AE) and the unit of fluid (mB) for the level emitters. 2020-07-19 23:50:18 +02:00
Sebastian Hartte ebe589a714 Ported the other number entry dialogs over to the shared widget. 2020-07-19 23:25:11 +02:00
Sebastian Hartte 6187e6a7bb Started refactoring number entry dialogs to use shared code. 2020-07-19 20:04:08 +02:00
shartte d5f113eb35 Merge pull request #4484 from AppliedEnergistics/energy-grid-failfast
Guard Against Concurrent EnergyGrid Modifications
2020-07-19 17:56:22 +02:00
shartte 9ad5bb21c0 Merge pull request #4480 from AppliedEnergistics/mb-fixes
Fix more MultiBlock issues
2020-07-19 17:31:06 +02:00
Sebastian Hartte 1c88ea7b78 Fail faster when something modifies the list of energy providers/requesters while an extract/inject operation is ongoing, since this would lead to ConcurrentModificationExceptions later, without a way of tracking down what caused the modification in the first place. 2020-07-19 16:39:37 +02:00
shartte 5a976ebfae Merge pull request #4483 from AppliedEnergistics/texture-cleanup
Texture Cleanup
2020-07-19 16:20:32 +02:00
Sebastian Hartte b45669bb82 Removed several unchecked casts. 2020-07-19 16:01:19 +02:00
Sebastian Hartte e52cc40dbf JSON Formatting Fix 2020-07-19 16:00:01 +02:00
Sebastian Hartte 8a20d3c1d7 Consolidated fluid models to reuse the item counterparts with different textures. 2020-07-19 15:00:46 +02:00
Sebastian Hartte 749ebeb91d Moved part textures from parts to part to be consistent with singular naming used in Minecraft (and for the model directory). 2020-07-19 14:14:18 +02:00
Sebastian Hartte 82586732e3 Removed unused crafting and fluid terminal models and associated textures.
Unified naming for textures used by the fluid terminal.
2020-07-19 14:09:57 +02:00
Sebastian Hartte e023d83e62 Deleted unused matrix frame related documentation images. 2020-07-19 13:40:42 +02:00
Sebastian Hartte de7cbc4949 Moved part-related textures from textures/item/part to textures/parts/ and adapted the level emitter item models to use the normal part texture. 2020-07-19 13:37:23 +02:00
Sebastian Hartte 71a91e51fb Naming improvements 2020-07-19 13:16:50 +02:00
yueh 223163aa0a Fixes #4330: Avoid mutating the input stack (#4481) 2020-07-19 13:13:20 +02:00
Sebastian Hartte bdd22093c3 Account for empty messages when drawing tooltips. 2020-07-19 12:05:26 +02:00
Sebastian Hartte 0367b35ce0 Never return null from Widget#getMessage since the
narrator will always dereference it, leading to a crash.
2020-07-19 12:04:15 +02:00
yueh 755ac12b8a Fix SortedSet using compare for equals (#4479)
Fix SortedSet using compare for equals
2020-07-19 11:43:20 +02:00
Sebastian Hartte e1f9e01404 Force cluster-rebuilds on the first detected change, if their bounds do not match.
Also use a client-side method to update connected textures
for crafting cubes if two previously distinct clusters are connected.
Refactored MBCalculator to use generics for type checks and remove more casts.
2020-07-19 00:16:33 +02:00
Sebastian Hartte 7121426fc9 Disable AO for the Spatial Pylon due to artifacts. 2020-07-19 00:12:35 +02:00
yueh a94e8504f8 Correctly convert milliseconds to microseconds (#4478) 2020-07-18 20:51:30 +02:00
yueh 9275bfe001 Split TickHandler#onTick into more specific event handlers (#4477) 2020-07-18 19:35:33 +02:00
shartte 5b3c4aef79 When blocks adjacent to multiblock-capable blocks are updated, (#4474)
do not always recalculate existing multiblocks. Only do so,
if the adjacent block is either part of the multiblock's bounding
box, or if the adjacent block would be a valid part of the multiblock.
2020-07-18 18:18:24 +02:00
yueh 4a289470e2 Added a priority to IAEPowerStorage (#4473)
Added a priority to IAEPowerStorage
2020-07-18 18:06:05 +02:00
shartte d79c0f642c Do not allow recursive creation of multiblocks. (#4472) 2020-07-18 18:00:40 +02:00
aoisensi 9ecad8749f Added new japanese translate (#4475)
* Added new japanese translate
2020-07-18 12:38:23 +02:00
shartte e8b57c6dc5 Multiblocks sometimes can't be broken because during removal, (#4469)
they update their own block-state to display the disconnected
state, effectively reversing their own removal. This occurs
because the cached block state in the tile entity base class is
outdated and doesn't reflect the removal.
2020-07-17 22:35:49 +02:00
shartte 8142eb90a6 Added new Cell Rendering to ME Chest (#4464)
Moved cell models to origin 0,0,0.
Implemented a TER to render cell models/LED in the ME chest as they are rendered in the drive.
2020-07-17 20:37:07 +02:00
Sebastian Hartte 08abd4a770 Fixed formatting. 2020-07-17 20:26:17 +02:00
Sebastian Hartte b8722dbbc0 Do not rely on exceptions for control flow, when the
cell has no fuzzy mode.
2020-07-17 19:51:59 +02:00
Sebastian Hartte 1ac6d5d967 Fixes creation of entangled singularities. 2020-07-17 15:27:03 +02:00
Sebastian Hartte 5c290789e0 Fixes #4467: Private methods also need to be annotated with @OnlyIn(Dist.CLIENT)
if they use client-side classes.
2020-07-17 12:45:17 +02:00
yueh 38f6bf16f2 Updated dependencies (#4466)
Changed forge to 31.2.31 and also marked it as required version.
Changed JEI to 6.0.2.12 for dev usage.
2020-07-15 23:25:35 +02:00
Sebastian Hartte 4953509255 P2P Fluid Tunnel Fix 2020-07-13 17:45:40 +02:00
Sebastian Hartte 188f105730 Fix the alive check for the matter cannon. 2020-07-12 17:20:42 +02:00
654 changed files with 4108 additions and 3786 deletions
+5 -3
View File
@@ -21,13 +21,15 @@ jobs:
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
- name: Clean gradle
run: ./gradlew clean --no-daemon --max-workers 1
- name: Validate no assets
run: test ! -d ./src/generated
- name: Generate assets
uses: GabrielBB/xvfb-action@v1.2
with:
run: ./gradlew runData --no-daemon
run: ./gradlew runData --no-daemon --max-workers 1
- name: Validate assets
run: test -d ./src/generated
run: test -d ./src/generated -a -f ./src/generated/resources/.cache/cache
- name: Build with Gradle
run: ./gradlew build --no-daemon
run: ./gradlew build --no-daemon --max-workers 1
+5 -3
View File
@@ -21,13 +21,15 @@ jobs:
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
- name: Clean gradle
run: ./gradlew clean --no-daemon --max-workers 1
- name: Validate no assets
run: test ! -d ./src/generated
- name: Generate assets
uses: GabrielBB/xvfb-action@v1.2
with:
run: ./gradlew runData --no-daemon
run: ./gradlew runData --no-daemon --max-workers 1
- name: Validate assets
run: test -d ./src/generated
run: test -d ./src/generated -a -f ./src/generated/resources/.cache/cache
- name: Build with Gradle
run: ./gradlew build --no-daemon
run: ./gradlew build --no-daemon --max-workers 1
+5 -3
View File
@@ -21,18 +21,20 @@ jobs:
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
- name: Clean gradle
run: ./gradlew clean --no-daemon --max-workers 1
- name: Validate no assets
run: test ! -d ./src/generated
- name: Generate assets
uses: GabrielBB/xvfb-action@v1.2
with:
run: ./gradlew runData --no-daemon
run: ./gradlew runData --no-daemon --max-workers 1
- name: Validate assets
run: test -d ./src/generated
run: test -d ./src/generated -a -f ./src/generated/resources/.cache/cache
- name: Build with Gradle
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
run: ./gradlew build --no-daemon
run: ./gradlew build --no-daemon --max-workers 1
- uses: actions/upload-artifact@v2
with:
name: dist
+5 -5
View File
@@ -33,16 +33,16 @@ jobs:
- name: Generate assets
uses: GabrielBB/xvfb-action@v1.2
with:
run: ./gradlew runData --no-daemon
run: ./gradlew runData --no-daemon --max-workers 1
- name: Validate assets
run: test -d ./src/generated
run: test -d ./src/generated -a -f ./src/generated/resources/.cache/cache
- name: Build with Gradle
env:
KEY_STORE_PASS: ${{ secrets.KEY_STORE_PASS }}
KEY_STORE_ALIAS: ${{ secrets.KEY_STORE_ALIAS }}
KEY_STORE_KEY_PASS: ${{ secrets.KEY_STORE_KEY_PASS }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew build --no-daemon
run: ./gradlew build --no-daemon --max-workers 1
- name: Upload to curseforge
env:
KEY_STORE_PASS: ${{ secrets.KEY_STORE_PASS }}
@@ -50,14 +50,14 @@ jobs:
KEY_STORE_KEY_PASS: ${{ secrets.KEY_STORE_KEY_PASS }}
CHANGELOG: ${{ github.event.release.body }}
CURSEFORGE: ${{ secrets.CURSEFORGE }}
run: ./gradlew curseforge --no-daemon
run: ./gradlew curseforge --no-daemon --max-workers 1
- name: Publish to github packages
env:
KEY_STORE_PASS: ${{ secrets.KEY_STORE_PASS }}
KEY_STORE_ALIAS: ${{ secrets.KEY_STORE_ALIAS }}
KEY_STORE_KEY_PASS: ${{ secrets.KEY_STORE_KEY_PASS }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew publish --no-daemon
run: ./gradlew publish --no-daemon --max-workers 1
- name: Prepare artifact metadata
id: prepare_artifact_metadata
run: |
+9 -8
View File
@@ -45,7 +45,7 @@ A Mod about Matter, Energy and using them to conquer the world..
## Downloads
Downloads can be found on [CurseForge](http://www.curse.com/mc-mods/minecraft/223794-applied-energistics-2) or on the [official website](http://ae-mod.info/Downloads/).
Downloads can be found on [CurseForge](https://www.curseforge.com/minecraft/mc-mods/applied-energistics-2) or on the [official website](http://ae-mod.info/Downloads/).
## Installation
@@ -103,7 +103,7 @@ However the dependency might need to be wrapped in `fg.deobf()` like `runtimeOnl
1. Clone this repository via
- SSH `git clone git@github.com:AppliedEnergistics/Applied-Energistics-2.git` or
- HTTPS `git clone https://github.com/AppliedEnergistics/Applied-Energistics-2.git`
2. Build using the gradle `build` task. Jar will be in `build/libs`
2. Build using the `gradlew runData build` command. Jar will be in `build/libs`
3. For core developer: Setup IDE
- IntelliJ: Import as gradle project
- Eclipse: Import as gradle project or execute gradle task `eclipse` and potentially `genEclipseRuns`
@@ -132,12 +132,13 @@ Here are a few things to keep in mind that will help get your PR approved.
* SSH `git clone git@github.com:<your username>/Applied-Energistics-2.git` or
* HTTPS `git clone https://github.com/<your username>/Applied-Energistics-2.git`
3. Change code base
4. Add changes to git `git add -A`
5. Commit changes to your clone `git commit -m "<summary of made changes>"`
6. Push to your fork `git push`
7. Create a Pull-Request on GitHub
8. Wait for review
9. Squash commits for cleaner history
4. Run `gradlew spotlessApply` to apply automatic code formatting
5. Add changes to git `git add -A`
6. Commit changes to your clone `git commit -m "<summary of made changes>"`
7. Push to your fork `git push`
8. Create a Pull-Request on GitHub
9. Wait for review
10. Squash commits for cleaner history
If you are only doing single file pull requests, GitHub supports using a quick way without the need of cloning your fork. Also read up about [synching](https://help.github.com/articles/syncing-a-fork) if you plan to contribute on regular basis.
+3 -3
View File
@@ -10,13 +10,13 @@ artifact_basename=appliedenergistics2
#########################################################
minecraft_release=1.15
minecraft_version=1.15.2
mcp_mappings=20200701-1.15.1
forge_version=31.2.20
mcp_mappings=20200715-1.15.1
forge_version=31.2.31
#########################################################
# Provided APIs #
#########################################################
jei_version=6.0.0.4
jei_version=6.0.2.12
top_version=2.0.4-5
hwyla_version=1.10.8-B72_1.15.2
ctm_version=MC1.15.2-1.1.0.9
-45
View File
@@ -23,51 +23,6 @@ repositories {
name 'modmaven'
url "https://modmaven.k-4u.nl/"
}
maven {
name "Mobius"
url "http://mobiusstrip.eu/maven"
}
maven {
name = "JEI repo"
url "http://dvs1.progwml6.com/files/maven"
}
maven {
name = "Tesla repo"
url "http://maven.mcmoddev.com"
}
maven {
name = "IC2 repo"
url = "http://maven.ic2.player.to"
}
maven {
name = "CoFH Maven"
url = "http://maven.covers1624.net"
}
maven { // TheOneProbe
name 'tterrag maven'
url "http://maven.tterrag.com/"
}
maven {
name 'mcjty'
url "http://maven.k-4u.nl/"
}
maven { // CraftTweaker
name 'jared maven'
url "http://maven.blamejared.com/"
}
maven {
name = "CurseForge"
url = "https://minecraft.curseforge.com/api/maven/"
}
}
dependencies {
Binary file not shown.
+1 -1
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
@@ -23,6 +23,8 @@
package appeng.api.networking.crafting;
import java.util.List;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
@@ -60,24 +62,65 @@ public interface ICraftingPatternDetails {
boolean isCraftable();
/**
* Equal itemstacks will be aggregated into one, respectively 3*64 will be
* returned as one stack of 192, up to 576 of a single type.
* <p>
* This should be the preferred way to deal with the list of inputs.
* <p>
* The list will be sorted in descending order by stack size. However there is
* no guarantee about maintaining the placement order of the inputs in case of
* equal values.
*
* @return an immutable list of inputs without nulls
*/
List<IAEItemStack> getInputs();
/**
* Equal itemstacks will be aggregated into one, respectively 2*32 will be
* returned as one stack of 64, up to 192 of a single type.
* <p>
* This should be the preferred way to deal with the list of outputs.
* <p>
*
* The list will be sorted in descending order by stack size. However there is
* no guarantee about maintaining the placement order of the outputs in case of
* equal values.
*
* @return an immutable list of outputs without nulls
*/
List<IAEItemStack> getOutputs();
/**
* A sparse list representing the placement order of a crafting grid, left to
* right, then top to bottom.
* <p>
* Only use when absolutely necessary, always prefer
* {@link ICraftingPatternDetails#getInputs()}
* <p>
* This will contain exactly 9 entries.
* <p>
* This can return a copy from the internal structure, so there are no
* guarantees about modifications.
*
* @return a list of the inputs, will include nulls.
*/
IAEItemStack[] getInputs();
/**
* @return a list of the inputs, will be clean
*/
IAEItemStack[] getCondensedInputs();
/**
* @return a list of the outputs, will be clean
*/
IAEItemStack[] getCondensedOutputs();
IAEItemStack[] getSparseInputs();
/**
* A sparse list representing the placement order of the respective output
* slots.
* <p>
* Only use when absolutely necessary, always prefer
* {@link ICraftingPatternDetails#getOutputs()}
* <p>
* This will either contain 1 entry for crafting patterns or 3 for processing.
* <p>
* This can return a copy from the internal structure, so there are no
* guarantees about modifications.
*
* @return a list of the outputs, will include nulls.
*/
IAEItemStack[] getOutputs();
IAEItemStack[] getSparseOutputs();
/**
* @return if this pattern is enabled to support substitutions.
@@ -27,6 +27,7 @@ import javax.annotation.Nonnull;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable;
import appeng.api.networking.IGrid;
/**
* Used to access information about AE's various power accepting blocks for
@@ -71,4 +72,22 @@ public interface IAEPowerStorage extends IEnergySource {
*/
@Nonnull
AccessRestriction getPowerFlow();
}
/**
* The priority to use this energy storage.
*
* A higher value means it is more likely to be extracted from first, and less
* likely to be inserted into first.
*
* The value needs to be constant once added to a {@link IGrid}. Should it ever
* need to be changed, it has to be removed from the grid, then update the
* value, and finally added back to the grid.
*
* This should never use {@link Integer#MIN_VALUE} or {@link Integer#MAX_VALUE}.
*
* @return the priority for this storage
*/
default int getPriority() {
return 0;
}
}
+5 -2
View File
@@ -50,6 +50,7 @@ import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.model.data.EmptyModelData;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityProvider;
import net.minecraftforge.common.util.LazyOptional;
import appeng.api.networking.IGridNode;
@@ -346,10 +347,12 @@ public interface IPart extends ICustomCableConnection {
* capabilities on the cable bus will be forwarded to parts on the appropriate
* side.
*
* @see TileEntity#getCapability(Capability, net.minecraft.util.Direction)
* @see CapabilityProvider#getCapability(Capability,
* net.minecraft.util.Direction)
*
* @return The capability or null.
* @return The capability
*/
@Nonnull
default <T> LazyOptional<T> getCapability(Capability<T> capabilityClass) {
return LazyOptional.empty();
}
@@ -23,10 +23,13 @@ import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
@@ -54,12 +57,22 @@ public abstract class AbstractCraftingUnitBlock<T extends CraftingTileEntity> ex
builder.add(FORMED);
}
@Override
public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn,
BlockPos currentPos, BlockPos facingPos) {
TileEntity te = worldIn.getTileEntity(currentPos);
if (te != null) {
te.requestModelDataUpdate();
}
return super.updatePostPlacement(stateIn, facing, facingState, worldIn, currentPos, facingPos);
}
@Override
public void neighborChanged(final BlockState state, final World worldIn, final BlockPos pos, final Block blockIn,
final BlockPos fromPos, boolean isMoving) {
final CraftingTileEntity cp = this.getTileEntity(worldIn, pos);
if (cp != null) {
cp.updateMultiBlock();
cp.updateMultiBlock(fromPos);
}
}
@@ -41,9 +41,9 @@ class QnbFormedBakedModel implements IDynamicBakedModel {
private static final Material TEXTURE_RING_LIGHT_CORNER = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
new ResourceLocation(AppEng.MOD_ID, "block/quantum_ring_light_corner"));
private static final Material TEXTURE_CABLE_GLASS = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
new ResourceLocation(AppEng.MOD_ID, "parts/cable/glass/transparent"));
new ResourceLocation(AppEng.MOD_ID, "part/cable/glass/transparent"));
private static final Material TEXTURE_COVERED_CABLE = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
new ResourceLocation(AppEng.MOD_ID, "parts/cable/covered/transparent"));
new ResourceLocation(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;
@@ -70,7 +70,7 @@ public abstract class QuantumBaseBlock extends AEBaseTileBlock<QuantumBridgeTile
boolean isMoving) {
final QuantumBridgeTileEntity bridge = this.getTileEntity(world, pos);
if (bridge != null) {
bridge.neighborUpdate();
bridge.neighborUpdate(fromPos);
}
}
@@ -39,7 +39,7 @@ public class SpatialPylonBlock extends AEBaseTileBlock<SpatialPylonTileEntity> {
boolean isMoving) {
final SpatialPylonTileEntity tsp = this.getTileEntity(world, pos);
if (tsp != null) {
tsp.neighborChanged();
tsp.neighborChanged(fromPos);
}
}
@@ -25,7 +25,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.material.Material;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.state.EnumProperty;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand;
@@ -42,18 +42,17 @@ import appeng.tile.storage.ChestTileEntity;
public class ChestBlock extends AEBaseTileBlock<ChestTileEntity> {
private final static EnumProperty<DriveSlotState> SLOT_STATE = EnumProperty.create("slot_state",
DriveSlotState.class);
private final static BooleanProperty LIGHTS_ON = BooleanProperty.create("lights_on");
public ChestBlock() {
super(defaultProps(Material.IRON));
this.setDefaultState(this.getDefaultState().with(SLOT_STATE, DriveSlotState.EMPTY));
this.setDefaultState(this.getDefaultState().with(LIGHTS_ON, false));
}
@Override
protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder) {
super.fillStateContainer(builder);
builder.add(SLOT_STATE);
builder.add(LIGHTS_ON);
}
@Override
@@ -68,7 +67,7 @@ public class ChestBlock extends AEBaseTileBlock<ChestTileEntity> {
slotState = DriveSlotState.OFFLINE;
}
return currentState.with(SLOT_STATE, slotState);
return currentState.with(LIGHTS_ON, slotState != DriveSlotState.EMPTY && slotState != DriveSlotState.OFFLINE);
}
@Override
@@ -35,6 +35,7 @@ import org.lwjgl.opengl.GL11;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.gui.IGuiEventListener;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.client.gui.widget.Widget;
import net.minecraft.client.renderer.BufferBuilder;
@@ -60,6 +61,7 @@ import net.minecraftforge.fml.client.gui.GuiUtils;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IAEItemStack;
import appeng.client.gui.widgets.CustomSlotWidget;
import appeng.client.gui.widgets.ITickingWidget;
import appeng.client.gui.widgets.ITooltip;
import appeng.client.gui.widgets.Scrollbar;
import appeng.client.me.InternalSlotME;
@@ -88,6 +90,9 @@ import appeng.fluids.container.slots.IMEFluidSlot;
import appeng.helpers.InventoryAction;
public abstract class AEBaseScreen<T extends AEBaseContainer> extends ContainerScreen<T> {
public static final int COLOR_DARK_GRAY = 4210752;
private final List<InternalSlotME> meSlots = new ArrayList<>();
// drag y
private final Set<Slot> drag_click = new HashSet<>();
@@ -149,14 +154,14 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends ContainerS
protected void drawGuiSlot(CustomSlotWidget slot, int mouseX, int mouseY, float partialTicks) {
if (slot.isSlotEnabled()) {
final int left = slot.xPos();
final int top = slot.yPos();
final int right = left + slot.getWidth();
final int bottom = top + slot.getHeight();
final int left = slot.getTooltipAreaX();
final int top = slot.getTooltipAreaY();
final int right = left + slot.getTooltipAreaWidth();
final int bottom = top + slot.getTooltipAreaHeight();
slot.drawContent(getMinecraft(), mouseX, mouseY, partialTicks);
if (this.isPointInRegion(left, top, slot.getWidth(), slot.getHeight(), mouseX, mouseY)
if (this.isPointInRegion(left, top, slot.getTooltipAreaWidth(), slot.getTooltipAreaHeight(), mouseX, mouseY)
&& slot.canClick(getPlayer())) {
RenderSystem.colorMask(true, true, true, false);
this.fillGradient(left, top, right, bottom, -2130706433, -2130706433);
@@ -166,17 +171,17 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends ContainerS
}
private void drawTooltip(ITooltip tooltip, int mouseX, int mouseY) {
final int x = tooltip.xPos(); // ((GuiImgButton) c).x;
int y = tooltip.yPos(); // ((GuiImgButton) c).y;
final int x = tooltip.getTooltipAreaX();
int y = tooltip.getTooltipAreaY();
if (x < mouseX && x + tooltip.getWidth() > mouseX && tooltip.isVisible()) {
if (y < mouseY && y + tooltip.getHeight() > mouseY) {
if (x < mouseX && x + tooltip.getTooltipAreaWidth() > mouseX && tooltip.isTooltipAreaVisible()) {
if (y < mouseY && y + tooltip.getTooltipAreaHeight() > mouseY) {
if (y < 15) {
y = 15;
}
final String msg = tooltip.getMessage();
if (msg != null) {
final String msg = tooltip.getTooltipMessage();
if (msg != null && !msg.isEmpty()) {
this.drawTooltip(x + 11, y + 4, msg);
}
}
@@ -270,8 +275,8 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends ContainerS
}
for (CustomSlotWidget slot : this.guiSlots) {
if (this.isPointInRegion(slot.xPos(), slot.yPos(), slot.getWidth(), slot.getHeight(), xCoord, yCoord)
&& slot.canClick(getPlayer())) {
if (this.isPointInRegion(slot.getTooltipAreaX(), slot.getTooltipAreaY(), slot.getTooltipAreaWidth(),
slot.getTooltipAreaHeight(), xCoord, yCoord) && slot.canClick(getPlayer())) {
slot.slotClicked(getPlayer().inventory.getItemStack(), btn);
}
}
@@ -781,4 +786,14 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends ContainerS
protected List<InternalSlotME> getMeSlots() {
return this.meSlots;
}
public void tick() {
super.tick();
for (IGuiEventListener child : children) {
if (child instanceof ITickingWidget) {
((ITickingWidget) child).tick();
}
}
}
}
@@ -0,0 +1,16 @@
package appeng.client.gui;
public enum NumberEntryType {
CRAFT_ITEM_COUNT(Long.class), PRIORITY(Long.class), LEVEL_ITEM_COUNT(Long.class), LEVEL_FLUID_VOLUME(Long.class);
private final Class<? extends Number> inputType;
NumberEntryType(Class<? extends Number> inputType) {
this.inputType = inputType;
}
public Class<? extends Number> getInputType() {
return inputType;
}
}
@@ -19,15 +19,13 @@
package appeng.client.gui.implementations;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.client.util.InputMappings;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.fml.client.gui.GuiUtils;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.widgets.NumberBox;
import appeng.client.gui.NumberEntryType;
import appeng.container.implementations.CraftAmountContainer;
import appeng.core.AEConfig;
import appeng.core.localization.GuiText;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.CraftRequestPacket;
@@ -35,7 +33,7 @@ import appeng.core.sync.packets.CraftRequestPacket;
public class CraftAmountScreen extends AEBaseScreen<CraftAmountContainer> {
private final AESubScreen subGui;
private NumberBox amountToCraft;
private NumberEntryWidget amountToCraft;
private Button next;
@@ -48,39 +46,22 @@ public class CraftAmountScreen extends AEBaseScreen<CraftAmountContainer> {
public void init() {
super.init();
final int a = AEConfig.instance().craftItemsByStackAmounts(0);
final int b = AEConfig.instance().craftItemsByStackAmounts(1);
final int c = AEConfig.instance().craftItemsByStackAmounts(2);
final int d = AEConfig.instance().craftItemsByStackAmounts(3);
this.addButton(new Button(this.guiLeft + 20, this.guiTop + 26, 22, 20, "+" + a, btn -> addQty(a)));
this.addButton(new Button(this.guiLeft + 48, this.guiTop + 26, 28, 20, "+" + b, btn -> addQty(b)));
this.addButton(new Button(this.guiLeft + 82, this.guiTop + 26, 32, 20, "+" + c, btn -> addQty(c)));
this.addButton(new Button(this.guiLeft + 120, this.guiTop + 26, 38, 20, "+" + d, btn -> addQty(d)));
this.addButton(new Button(this.guiLeft + 20, this.guiTop + 75, 22, 20, "-" + a, btn -> addQty(-a)));
this.addButton(new Button(this.guiLeft + 48, this.guiTop + 75, 28, 20, "-" + b, btn -> addQty(-b)));
this.addButton(new Button(this.guiLeft + 82, this.guiTop + 75, 32, 20, "-" + c, btn -> addQty(-c)));
this.addButton(new Button(this.guiLeft + 120, this.guiTop + 75, 38, 20, "-" + d, btn -> addQty(-d)));
this.amountToCraft = new NumberEntryWidget(this, 20, 30, 138, 62, NumberEntryType.CRAFT_ITEM_COUNT, value -> {
});
this.amountToCraft.setValue(1);
this.amountToCraft.setTextFieldBounds(62, 57, 50);
this.amountToCraft.setMinValue(1);
this.amountToCraft.addButtons(children::add, this::addButton);
this.next = this.addButton(
new Button(this.guiLeft + 128, this.guiTop + 51, 38, 20, GuiText.Next.getLocal(), this::confirm));
subGui.addBackButton(this::addButton, 154, 0);
this.amountToCraft = new NumberBox(this.font, this.guiLeft + 62, this.guiTop + 57, 59, this.font.FONT_HEIGHT,
Integer.class);
this.amountToCraft.setEnableBackgroundDrawing(false);
this.amountToCraft.setMaxStringLength(16);
this.amountToCraft.setTextColor(0xFFFFFF);
this.amountToCraft.setVisible(true);
this.amountToCraft.setFocused2(true);
this.amountToCraft.setText("1");
}
private void confirm(Button button) {
NetworkHandler.instance()
.sendToServer(new CraftRequestPacket(Integer.parseInt(this.amountToCraft.getText()), hasShiftDown()));
.sendToServer(new CraftRequestPacket((int) this.amountToCraft.getValue(), hasShiftDown()));
}
@Override
@@ -95,99 +76,23 @@ public class CraftAmountScreen extends AEBaseScreen<CraftAmountContainer> {
this.bindTexture("guis/craft_amt.png");
GuiUtils.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize, getBlitOffset());
try {
Long.parseLong(this.amountToCraft.getText());
this.next.active = !this.amountToCraft.getText().isEmpty();
} catch (final NumberFormatException e) {
this.next.active = false;
}
this.next.active = this.amountToCraft.getValue() > 0;
this.amountToCraft.render(offsetX, offsetY, partialTicks);
}
@Override
public boolean charTyped(char ch, int p_charTyped_2_) {
// Forward entered text to the craft amount text-field
return this.amountToCraft.charTyped(ch, p_charTyped_2_);
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int p_keyPressed_3_) {
if (!this.checkHotbarKeys(InputMappings.getInputByCode(keyCode, scanCode))) {
if (keyCode == 28) {
this.next.onPress();
}
if ((keyCode == 211 || keyCode == 205 || keyCode == 203 || keyCode == 14)
&& this.amountToCraft.keyPressed(keyCode, scanCode, p_keyPressed_3_)) {
try {
String out = this.amountToCraft.getText();
boolean fixed = false;
while (out.startsWith("0") && out.length() > 1) {
out = out.substring(1);
fixed = true;
}
if (fixed) {
this.amountToCraft.setText(out);
}
if (out.isEmpty()) {
out = "0";
}
final long result = Long.parseLong(out);
if (result < 0) {
this.amountToCraft.setText("1");
}
} catch (final NumberFormatException e) {
// :P
}
return true;
}
}
return super.keyPressed(keyCode, scanCode, p_keyPressed_3_);
}
private void addQty(final int i) {
try {
String out = this.amountToCraft.getText();
boolean fixed = false;
while (out.startsWith("0") && out.length() > 1) {
out = out.substring(1);
fixed = true;
}
if (fixed) {
this.amountToCraft.setText(out);
}
if (out.isEmpty()) {
out = "0";
}
long result = Integer.parseInt(out);
if (result == 1 && i > 1) {
result = 0;
}
result += i;
if (result < 1) {
result = 1;
}
out = Long.toString(result);
Integer.parseInt(out);
this.amountToCraft.setText(out);
} catch (final NumberFormatException e) {
// :P
if (keyCode == 28) {
this.next.onPress();
return true;
} else {
return super.keyPressed(keyCode, scanCode, p_keyPressed_3_);
}
}
protected String getBackground() {
return "guis/craftAmt.png";
}
}
@@ -18,39 +18,27 @@
package appeng.client.gui.implementations;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.client.util.InputMappings;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.text.ITextComponent;
import appeng.api.config.FuzzyMode;
import appeng.api.config.LevelType;
import appeng.api.config.PowerUnits;
import appeng.api.config.RedstoneMode;
import appeng.api.config.Settings;
import appeng.api.config.Upgrades;
import appeng.api.config.YesNo;
import appeng.client.gui.widgets.NumberBox;
import appeng.client.gui.NumberEntryType;
import appeng.client.gui.widgets.ServerSettingToggleButton;
import appeng.client.gui.widgets.SettingToggleButton;
import appeng.container.implementations.LevelEmitterContainer;
import appeng.core.AEConfig;
import appeng.core.localization.GuiText;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ConfigValuePacket;
public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer> {
private NumberBox level;
private Button plus1;
private Button plus10;
private Button plus100;
private Button plus1000;
private Button minus1;
private Button minus10;
private Button minus100;
private Button minus1000;
private NumberEntryWidget level;
private SettingToggleButton<LevelType> levelMode;
private SettingToggleButton<YesNo> craftingMode;
@@ -62,16 +50,17 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
public void init() {
super.init();
this.level = new NumberBox(this.font, this.guiLeft + 24, this.guiTop + 43, 79, this.font.FONT_HEIGHT,
Long.class);
this.level.setEnableBackgroundDrawing(false);
this.level.setMaxStringLength(16);
this.level.setTextColor(0xFFFFFF);
this.level.setVisible(true);
this.level.setFocused2(true);
this.level = new NumberEntryWidget(this, 20, 17, 138, 62, NumberEntryType.LEVEL_ITEM_COUNT,
this::onLevelChange);
this.level.setTextFieldBounds(25, 44, 75);
this.level.addButtons(children::add, this::addButton);
container.setTextField(this.level);
}
private void onLevelChange(long level) {
NetworkHandler.instance().sendToServer(new ConfigValuePacket("LevelEmitter.Value", String.valueOf(level)));
}
@Override
protected void addButtons() {
this.levelMode = new ServerSettingToggleButton<>(this.guiLeft - 18, this.guiTop + 8, Settings.LEVEL_TYPE,
@@ -82,29 +71,6 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
FuzzyMode.IGNORE_ALL);
this.craftingMode = new ServerSettingToggleButton<>(this.guiLeft - 18, this.guiTop + 48,
Settings.CRAFT_VIA_REDSTONE, YesNo.NO);
final int a = AEConfig.instance().levelByStackAmounts(0);
final int b = AEConfig.instance().levelByStackAmounts(1);
final int c = AEConfig.instance().levelByStackAmounts(2);
final int d = AEConfig.instance().levelByStackAmounts(3);
this.addButton(this.plus1 = new Button(this.guiLeft + 20, this.guiTop + 17, 22, 20, "+" + a, btn -> addQty(a)));
this.addButton(
this.plus10 = new Button(this.guiLeft + 48, this.guiTop + 17, 28, 20, "+" + b, btn -> addQty(b)));
this.addButton(
this.plus100 = new Button(this.guiLeft + 82, this.guiTop + 17, 32, 20, "+" + c, btn -> addQty(c)));
this.addButton(
this.plus1000 = new Button(this.guiLeft + 120, this.guiTop + 17, 38, 20, "+" + d, btn -> addQty(d)));
this.addButton(
this.minus1 = new Button(this.guiLeft + 20, this.guiTop + 59, 22, 20, "-" + a, btn -> addQty(-a)));
this.addButton(
this.minus10 = new Button(this.guiLeft + 48, this.guiTop + 59, 28, 20, "-" + b, btn -> addQty(-b)));
this.addButton(
this.minus100 = new Button(this.guiLeft + 82, this.guiTop + 59, 32, 20, "-" + c, btn -> addQty(-c)));
this.addButton(
this.minus1000 = new Button(this.guiLeft + 120, this.guiTop + 59, 38, 20, "-" + d, btn -> addQty(-d)));
this.addButton(this.levelMode);
this.addButton(this.redstoneMode);
this.addButton(this.craftingMode);
@@ -115,15 +81,7 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
final boolean notCraftingMode = this.bc.getInstalledUpgrades(Upgrades.CRAFTING) == 0;
// configure enabled status...
this.level.setEnabled(notCraftingMode);
this.plus1.active = notCraftingMode;
this.plus10.active = notCraftingMode;
this.plus100.active = notCraftingMode;
this.plus1000.active = notCraftingMode;
this.minus1.active = notCraftingMode;
this.minus10.active = notCraftingMode;
this.minus100.active = notCraftingMode;
this.minus1000.active = notCraftingMode;
this.level.setActive(notCraftingMode);
this.levelMode.active = notCraftingMode;
this.redstoneMode.active = notCraftingMode;
@@ -134,7 +92,14 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
}
if (this.levelMode != null) {
this.levelMode.set(((LevelEmitterContainer) this.cvb).getLevelMode());
LevelType currentLevelMode = ((LevelEmitterContainer) this.cvb).getLevelMode();
this.levelMode.set(currentLevelMode);
if (notCraftingMode) {
if (currentLevelMode == LevelType.ENERGY_LEVEL) {
this.font.drawString(PowerUnits.AE.textComponent().getString(), 110, 44, COLOR_DARK_GRAY);
}
}
}
}
@@ -160,70 +125,4 @@ public class LevelEmitterScreen extends UpgradeableScreen<LevelEmitterContainer>
return GuiText.LevelEmitter;
}
private void addQty(final long i) {
try {
String Out = this.level.getText();
boolean Fixed = false;
while (Out.startsWith("0") && Out.length() > 1) {
Out = Out.substring(1);
Fixed = true;
}
if (Fixed) {
this.level.setText(Out);
}
if (Out.isEmpty()) {
Out = "0";
}
long result = Long.parseLong(Out);
result += i;
if (result < 0) {
result = 0;
}
this.level.setText(Out = Long.toString(result));
NetworkHandler.instance().sendToServer(new ConfigValuePacket("LevelEmitter.Value", Out));
} catch (final NumberFormatException e) {
// nope..
this.level.setText("0");
}
}
@Override
public boolean charTyped(char character, int key) {
// Forward entered characters to the number-text-field
return level.charTyped(character, key);
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int p_keyPressed_3_) {
if (!this.checkHotbarKeys(InputMappings.getInputByCode(keyCode, scanCode))) {
if (keyCode == 211 || keyCode == 205 || keyCode == 203 || keyCode == 14) {
String Out = this.level.getText();
boolean Fixed = false;
while (Out.startsWith("0") && Out.length() > 1) {
Out = Out.substring(1);
Fixed = true;
}
if (Fixed) {
this.level.setText(Out);
}
if (Out.isEmpty()) {
Out = "0";
}
NetworkHandler.instance().sendToServer(new ConfigValuePacket("LevelEmitter.Value", Out));
return true;
}
}
return super.keyPressed(keyCode, scanCode, p_keyPressed_3_);
}
}
@@ -295,12 +295,15 @@ public class MEMonitorableScreen<T extends MEMonitorableContainer> extends AEBas
@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.repo.setSearchString("");
this.repo.updateView();
this.setScrollBar();
}
return true;
}
// Right-clicking on the search field should clear it
if (this.searchField.isMouseOver(xCoord, yCoord) && btn == 1) {
this.searchField.setText("");
this.repo.setSearchString("");
this.repo.updateView();
this.setScrollBar();
return true;
}
@@ -0,0 +1,130 @@
package appeng.client.gui.implementations;
import java.util.function.Consumer;
import java.util.function.LongConsumer;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.IGuiEventListener;
import net.minecraft.client.gui.widget.button.Button;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.NumberEntryType;
import appeng.client.gui.widgets.ITickingWidget;
import appeng.client.gui.widgets.NumberBox;
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 {
private final AEBaseScreen<?> parent;
private final int x;
private final int y;
private final NumberBox level;
private final NumberEntryType type;
private Button plus1;
private Button plus10;
private Button plus100;
private Button plus1000;
private Button minus1;
private Button minus10;
private Button minus100;
private Button minus1000;
public NumberEntryWidget(AEBaseScreen<?> parent, int x, int y, int width, int height, NumberEntryType type,
LongConsumer changeListener) {
this.parent = parent;
this.x = x;
this.y = y;
this.type = type;
FontRenderer font = parent.getMinecraft().fontRenderer;
int inputX = parent.getGuiLeft() + x;
int inputY = parent.getGuiTop() + y;
this.level = new NumberBox(font, inputX, inputY, width, font.FONT_HEIGHT, type.getInputType(), changeListener);
this.level.setEnableBackgroundDrawing(false);
this.level.setMaxStringLength(16);
this.level.setTextColor(0xFFFFFF);
this.level.setVisible(true);
this.level.setFocused2(true);
parent.setFocusedDefault(this.level);
}
public void setActive(boolean active) {
this.level.setEnabled(active);
this.plus1.active = active;
this.plus10.active = active;
this.plus100.active = active;
this.plus1000.active = active;
this.minus1.active = active;
this.minus10.active = active;
this.minus100.active = active;
this.minus1000.active = active;
}
public void setTextFieldBounds(int x, int y, int width) {
this.level.x = parent.getGuiLeft() + x;
this.level.y = parent.getGuiTop() + y;
this.level.setWidth(width);
}
public void setMinValue(long minValue) {
this.level.setMinValue(minValue);
}
public void addButtons(Consumer<IGuiEventListener> addChildren, Consumer<Button> addButton) {
final int[] steps = AEConfig.instance().getNumberEntrySteps(type);
int a = steps[0];
int b = steps[1];
int c = steps[2];
int d = steps[3];
int left = parent.getGuiLeft() + x;
int top = parent.getGuiTop() + y;
addButton.accept(this.plus1 = new Button(left, top, 22, 20, "+" + a, btn -> addQty(a)));
addButton.accept(this.plus10 = new Button(left + 28, top, 28, 20, "+" + b, btn -> addQty(b)));
addButton.accept(this.plus100 = new Button(left + 62, top, 32, 20, "+" + c, btn -> addQty(c)));
addButton.accept(this.plus1000 = new Button(left + 100, top, 38, 20, "+" + d, btn -> addQty(d)));
// Placing this here will give a sensible tab order
addChildren.accept(this.level);
addButton.accept(this.minus1 = new Button(left, top + 42, 22, 20, "-" + a, btn -> addQty(-a)));
addButton.accept(this.minus10 = new Button(left + 28, top + 42, 28, 20, "-" + b, btn -> addQty(-b)));
addButton.accept(this.minus100 = new Button(left + 62, top + 42, 32, 20, "-" + c, btn -> addQty(-c)));
addButton.accept(this.minus1000 = new Button(left + 100, top + 42, 38, 20, "-" + d, btn -> addQty(-d)));
}
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)));
}
public void render(int mouseX, int mouseY, float partialTicks) {
this.level.render(mouseX, mouseY, partialTicks);
}
public void setValue(long value, boolean skipNotify) {
this.level.setValue(value, skipNotify);
}
public void setValue(long value) {
setValue(value, false);
}
public long getValue() {
return level.getValue();
}
@Override
public void tick() {
this.level.tick();
}
}
@@ -18,15 +18,12 @@
package appeng.client.gui.implementations;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.client.util.InputMappings;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.text.ITextComponent;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.widgets.NumberBox;
import appeng.client.gui.NumberEntryType;
import appeng.container.implementations.PriorityContainer;
import appeng.core.AEConfig;
import appeng.core.localization.GuiText;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ConfigValuePacket;
@@ -35,7 +32,7 @@ public class PriorityScreen extends AEBaseScreen<PriorityContainer> {
private final AESubScreen subGui;
private NumberBox priority;
private NumberEntryWidget priority;
public PriorityScreen(PriorityContainer container, PlayerInventory playerInventory, ITextComponent title) {
super(container, playerInventory, title);
@@ -46,31 +43,18 @@ public class PriorityScreen extends AEBaseScreen<PriorityContainer> {
public void init() {
super.init();
final int a = AEConfig.instance().priorityByStacksAmounts(0);
final int b = AEConfig.instance().priorityByStacksAmounts(1);
final int c = AEConfig.instance().priorityByStacksAmounts(2);
final int d = AEConfig.instance().priorityByStacksAmounts(3);
this.addButton(new Button(this.guiLeft + 20, this.guiTop + 32, 22, 20, "+" + a, btn -> addQty(a)));
this.addButton(new Button(this.guiLeft + 48, this.guiTop + 32, 28, 20, "+" + b, btn -> addQty(b)));
this.addButton(new Button(this.guiLeft + 82, this.guiTop + 32, 32, 20, "+" + c, btn -> addQty(c)));
this.addButton(new Button(this.guiLeft + 120, this.guiTop + 32, 38, 20, "+" + d, btn -> addQty(d)));
this.addButton(new Button(this.guiLeft + 20, this.guiTop + 69, 22, 20, "-" + a, btn -> addQty(-a)));
this.addButton(new Button(this.guiLeft + 48, this.guiTop + 69, 28, 20, "-" + b, btn -> addQty(-b)));
this.addButton(new Button(this.guiLeft + 82, this.guiTop + 69, 32, 20, "-" + c, btn -> addQty(-c)));
this.addButton(new Button(this.guiLeft + 120, this.guiTop + 69, 38, 20, "-" + d, btn -> addQty(-d)));
this.priority = new NumberEntryWidget(this, 20, 30, 138, 62, NumberEntryType.PRIORITY, this::onPriorityChange);
this.priority.setTextFieldBounds(62, 57, 50);
this.priority.setMinValue(Integer.MIN_VALUE);
container.setTextField(this.priority);
this.priority.addButtons(children::add, this::addButton);
this.subGui.addBackButton(this::addButton, 154, 0);
}
this.priority = new NumberBox(this.font, this.guiLeft + 62, this.guiTop + 57, 59, this.font.FONT_HEIGHT,
Long.class);
this.priority.setEnableBackgroundDrawing(false);
this.priority.setMaxStringLength(16);
this.priority.setTextColor(0xFFFFFF);
this.priority.setVisible(true);
this.priority.setFocused2(true);
container.setTextField(this.priority);
private void onPriorityChange(long priority) {
NetworkHandler.instance()
.sendToServer(new ConfigValuePacket("PriorityHost.Priority", String.valueOf(priority)));
}
@Override
@@ -86,90 +70,6 @@ public class PriorityScreen extends AEBaseScreen<PriorityContainer> {
this.priority.render(mouseX, mouseY, partialTicks);
}
private void addQty(final int i) {
try {
String out = this.priority.getText();
boolean fixed = false;
while (out.startsWith("0") && out.length() > 1) {
out = out.substring(1);
fixed = true;
}
if (fixed) {
this.priority.setText(out);
}
if (out.isEmpty()) {
out = "0";
}
long result = Long.parseLong(out);
result += i;
this.priority.setText(out = Long.toString(result));
NetworkHandler.instance().sendToServer(new ConfigValuePacket("PriorityHost.Priority", out));
} catch (final NumberFormatException e) {
// nope..
this.priority.setText("0");
}
}
@Override
public boolean charTyped(char character, int key) {
if (priority.charTyped(character, key)) {
String out = this.priority.getText();
boolean fixed = false;
while (out.startsWith("0") && out.length() > 1) {
out = out.substring(1);
fixed = true;
}
if (fixed) {
this.priority.setText(out);
}
if (out.isEmpty()) {
out = "0";
}
NetworkHandler.instance().sendToServer(new ConfigValuePacket("PriorityHost.Priority", out));
return true;
}
return false;
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int p_keyPressed_3_) {
if (!this.checkHotbarKeys(InputMappings.getInputByCode(keyCode, scanCode))) {
if ((keyCode == 211 || keyCode == 205 || keyCode == 203 || keyCode == 14)
&& this.priority.keyPressed(keyCode, scanCode, p_keyPressed_3_)) {
String out = this.priority.getText();
boolean fixed = false;
while (out.startsWith("0") && out.length() > 1) {
out = out.substring(1);
fixed = true;
}
if (fixed) {
this.priority.setText(out);
}
if (out.isEmpty()) {
out = "0";
}
NetworkHandler.instance().sendToServer(new ConfigValuePacket("PriorityHost.Priority", out));
return true;
}
}
return super.keyPressed(keyCode, scanCode, p_keyPressed_3_);
}
protected String getBackground() {
return "guis/priority.png";
}
@@ -58,20 +58,6 @@ public class AETextField extends TextFieldWidget {
this._fontPad = (int) fontRenderer.getCharWidth('_');
}
@Override
public boolean mouseClicked(final double xPos, final double yPos, final int button) {
if (!super.mouseClicked(xPos, yPos, button)) {
return false;
}
final boolean requiresFocus = this.isMouseOver(xPos, yPos);
if (!this.isFocused()) {
this.setFocused2(requiresFocus);
}
return true;
}
public void selectAll() {
this.setCursorPosition(0);
this.setSelectionPos(this.getMaxStringLength());
@@ -24,7 +24,7 @@ import java.util.regex.Pattern;
import appeng.api.config.ActionItems;
import appeng.core.localization.ButtonToolTips;
public class ActionButton extends IconButton implements ITooltip {
public class ActionButton extends IconButton {
private static final Pattern PATTERN_NEW_LINE = Pattern.compile("\\n", Pattern.LITERAL);
private final int iconIndex;
@@ -34,32 +34,32 @@ public abstract class CustomSlotWidget extends AbstractGui implements ITooltip {
}
@Override
public String getMessage() {
public String getTooltipMessage() {
return null;
}
@Override
public int xPos() {
public int getTooltipAreaX() {
return this.x;
}
@Override
public int yPos() {
public int getTooltipAreaY() {
return this.y;
}
@Override
public int getWidth() {
public int getTooltipAreaWidth() {
return 16;
}
@Override
public int getHeight() {
public int getTooltipAreaHeight() {
return 16;
}
@Override
public boolean isVisible() {
public boolean isTooltipAreaVisible() {
return false;
}
@@ -0,0 +1,13 @@
package appeng.client.gui.widgets;
import net.minecraft.client.gui.screen.Screen;
/**
* Indicates that a widget (anything that is in the {@link Screen#children()}
* list) should receive callbacks every tick.
*/
public interface ITickingWidget {
void tick();
}
@@ -28,38 +28,38 @@ public interface ITooltip {
*
* @return tooltip message
*/
String getMessage();
String getTooltipMessage();
/**
* x Location for the object that triggers the tooltip.
*
* @return xPosition
*/
int xPos();
int getTooltipAreaX();
/**
* y Location for the object that triggers the tooltip.
*
* @return yPosition
*/
int yPos();
int getTooltipAreaY();
/**
* Width of the object that triggers the tooltip.
*
* @return width
*/
int getWidth();
int getTooltipAreaWidth();
/**
* Height for the object that triggers the tooltip.
*
* @return height
*/
int getHeight();
int getTooltipAreaHeight();
/**
* @return true if button being drawn
*/
boolean isVisible();
boolean isTooltipAreaVisible();
}
@@ -95,27 +95,32 @@ public abstract class IconButton extends Button implements ITooltip {
protected abstract int getIconIndex();
@Override
public int xPos() {
public String getTooltipMessage() {
return getMessage();
}
@Override
public int getTooltipAreaX() {
return this.x;
}
@Override
public int yPos() {
public int getTooltipAreaY() {
return this.y;
}
@Override
public int getWidth() {
public int getTooltipAreaWidth() {
return this.halfSize ? 8 : 16;
}
@Override
public int getHeight() {
public int getTooltipAreaHeight() {
return this.halfSize ? 8 : 16;
}
@Override
public boolean isVisible() {
public boolean isTooltipAreaVisible() {
return this.visible;
}
@@ -18,35 +18,135 @@
package appeng.client.gui.widgets;
import java.util.function.LongConsumer;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.widget.TextFieldWidget;
// FIXME: Fix this piece of crap (i.e. onChange listener)
public class NumberBox extends TextFieldWidget {
private final Class type;
private final LongConsumer changeListener;
private long lastValue;
private long minValue = 0;
private long maxValue;
public NumberBox(final FontRenderer fontRenderer, final int x, final int y, final int width, final int height,
final Class type) {
final Class<?> type, LongConsumer changeListener) {
super(fontRenderer, x, y, width, height, "0");
this.type = type;
this.setText("0");
setResponder(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 void writeText(final String selectedText) {
final String original = this.getText();
super.writeText(selectedText);
try {
if (this.type == int.class || this.type == Integer.class) {
Integer.parseInt(this.getText());
} else if (this.type == long.class || this.type == Long.class) {
Long.parseLong(this.getText());
} else if (this.type == double.class || this.type == Double.class) {
Double.parseDouble(this.getText());
}
} catch (final NumberFormatException e) {
this.setText(original);
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;
}
}
@@ -76,7 +76,7 @@ public class ProgressBar extends Widget implements ITooltip {
}
@Override
public String getMessage() {
public String getTooltipMessage() {
if (this.fullMsg != null) {
return this.fullMsg;
}
@@ -86,27 +86,27 @@ public class ProgressBar extends Widget implements ITooltip {
}
@Override
public int xPos() {
public int getTooltipAreaX() {
return this.x - 2;
}
@Override
public int yPos() {
public int getTooltipAreaY() {
return this.y - 2;
}
@Override
public int getWidth() {
public int getTooltipAreaWidth() {
return this.width + 4;
}
@Override
public int getHeight() {
public int getTooltipAreaHeight() {
return this.height + 4;
}
@Override
public boolean isVisible() {
public boolean isTooltipAreaVisible() {
return true;
}
@@ -278,7 +278,7 @@ public class SettingToggleButton<T extends Enum<T>> extends IconButton {
}
@Override
public String getMessage() {
public String getTooltipMessage() {
ITextComponent displayName = null;
ITextComponent displayValue = null;
@@ -314,7 +314,7 @@ public class SettingToggleButton<T extends Enum<T>> extends IconButton {
return name + '\n' + sb;
}
return null;
return "";
}
public String getFillVar() {
@@ -97,27 +97,32 @@ public class TabButton extends Button implements ITooltip {
}
@Override
public int xPos() {
public String getTooltipMessage() {
return getMessage();
}
@Override
public int getTooltipAreaX() {
return this.x;
}
@Override
public int yPos() {
public int getTooltipAreaY() {
return this.y;
}
@Override
public int getWidth() {
public int getTooltipAreaWidth() {
return 22;
}
@Override
public int getHeight() {
public int getTooltipAreaHeight() {
return 22;
}
@Override
public boolean isVisible() {
public boolean isTooltipAreaVisible() {
return this.visible;
}
@@ -74,7 +74,7 @@ public class ToggleButton extends Button implements ITooltip {
}
@Override
public String getMessage() {
public String getTooltipMessage() {
if (this.displayName != null) {
String name = I18n.format(this.displayName);
String value = I18n.format(this.displayHint);
@@ -99,31 +99,31 @@ public class ToggleButton extends Button implements ITooltip {
return name + '\n' + sb;
}
return null;
return "";
}
@Override
public int xPos() {
public int getTooltipAreaX() {
return this.x;
}
@Override
public int yPos() {
public int getTooltipAreaY() {
return this.y;
}
@Override
public int getWidth() {
public int getTooltipAreaWidth() {
return 16;
}
@Override
public int getHeight() {
public int getTooltipAreaHeight() {
return 16;
}
@Override
public boolean isVisible() {
public boolean isTooltipAreaVisible() {
return this.visible;
}
}
@@ -81,19 +81,19 @@ class CableBuilder {
String textureFolder;
switch (cableType) {
case GLASS:
textureFolder = "parts/cable/glass/";
textureFolder = "part/cable/glass/";
break;
case COVERED:
textureFolder = "parts/cable/covered/";
textureFolder = "part/cable/covered/";
break;
case SMART:
textureFolder = "parts/cable/smart/";
textureFolder = "part/cable/smart/";
break;
case DENSE_COVERED:
textureFolder = "parts/cable/dense_covered/";
textureFolder = "part/cable/dense_covered/";
break;
case DENSE_SMART:
textureFolder = "parts/cable/dense_smart/";
textureFolder = "part/cable/dense_smart/";
break;
default:
throw new IllegalStateException("Cable type " + cableType + " does not support connections.");
@@ -37,7 +37,7 @@ import appeng.core.AppEng;
* Covered (also used by the Smart Cable) - Dense
*/
public enum CableCoreType {
GLASS("parts/cable/core/glass"), COVERED("parts/cable/core/covered"), DENSE("parts/cable/core/dense_smart");
GLASS("part/cable/core/glass"), COVERED("part/cable/core/covered"), DENSE("part/cable/core/dense_smart");
private static final Map<AECableType, CableCoreType> cableMapping = generateCableMapping();
@@ -23,7 +23,7 @@ import appeng.core.AppEng;
public class P2PTunnelFrequencyModel implements IModelGeometry<P2PTunnelFrequencyModel> {
private static final Material TEXTURE = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
new ResourceLocation(AppEng.MOD_ID, "parts/p2p_tunnel_frequency"));
new ResourceLocation(AppEng.MOD_ID, "part/p2p_tunnel_frequency"));
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
@@ -34,16 +34,16 @@ import appeng.core.AppEng;
public class SmartCableTextures {
public static final Material[] SMART_CHANNELS_TEXTURES = Arrays
.stream(new ResourceLocation[] { new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_00"), //
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_01"), //
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_02"), //
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_03"), //
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_04"), //
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_10"), //
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_11"), //
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_12"), //
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_13"), //
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_14")//
.stream(new ResourceLocation[] { new ResourceLocation(AppEng.MOD_ID, "part/cable/smart/channels_00"), //
new ResourceLocation(AppEng.MOD_ID, "part/cable/smart/channels_01"), //
new ResourceLocation(AppEng.MOD_ID, "part/cable/smart/channels_02"), //
new ResourceLocation(AppEng.MOD_ID, "part/cable/smart/channels_03"), //
new ResourceLocation(AppEng.MOD_ID, "part/cable/smart/channels_04"), //
new ResourceLocation(AppEng.MOD_ID, "part/cable/smart/channels_10"), //
new ResourceLocation(AppEng.MOD_ID, "part/cable/smart/channels_11"), //
new ResourceLocation(AppEng.MOD_ID, "part/cable/smart/channels_12"), //
new ResourceLocation(AppEng.MOD_ID, "part/cable/smart/channels_13"), //
new ResourceLocation(AppEng.MOD_ID, "part/cable/smart/channels_14")//
}).map(e -> new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE, e)).toArray(Material[]::new);
// Textures used to display channels on smart cables. There's two sets of 5
@@ -28,6 +28,7 @@ import javax.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.Vector3f;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.item.Item;
@@ -49,6 +50,19 @@ public class DriveBakedModel extends DelegateBakedModel {
this.defaultCell = defaultCell;
}
/**
* Calculates the origin of a drive slot for positioning a cell model into it.
*/
public static void getSlotOrigin(int row, int col, Vector3f translation) {
// Position this drive model copy at the correct slot. The transform is based on
// the cell-model being in slot 0,0,0 while the upper left slot's origin is at
// 9,13,1
float xOffset = (9 - col * 8) / 16.0f;
float yOffset = (13 - row * 3) / 16.0f;
float zOffset = 1 / 16.0f;
translation.set(xOffset, yOffset, zOffset);
}
@Nonnull
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand,
@@ -63,17 +77,14 @@ public class DriveBakedModel extends DelegateBakedModel {
DriveSlotsState slotsState = driveModelData.getSlotsState();
Vector3f slotTranslation = new Vector3f();
if (slotsState != null) {
for (int row = 0; row < 5; row++) {
for (int col = 0; col < 2; col++) {
Matrix4f transform = new Matrix4f();
// Position this drive model copy at the correct slot. The transform is based on
// the
// cell-model being in slot 0,0 at the top left of the drive.
float xOffset = -col * 8 / 16.0f;
float yOffset = -row * 3 / 16.0f;
transform.setTranslation(xOffset, yOffset, 0);
getSlotOrigin(row, col, slotTranslation);
transform.setTranslation(slotTranslation.getX(), slotTranslation.getY(), slotTranslation.getZ());
int slot = row * 2 + col;
@@ -184,7 +184,7 @@ class SpatialPylonBakedModel implements IDynamicBakedModel {
@Override
public boolean isAmbientOcclusion() {
return true;
return false;
}
@Override
@@ -0,0 +1,106 @@
package appeng.client.render.tesr;
import java.util.EnumMap;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.Vector3f;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import appeng.api.implementations.tiles.IChestOrDrive;
import appeng.block.storage.DriveSlotState;
/**
* Utility class to render LEDs for storage cells from a Tile Entity Renderer.
*/
class CellLedRenderer {
private static final EnumMap<DriveSlotState, Vector3f> STATE_COLORS;
// Color used for the cell indicator for blinking during recent activity
private static final Vector3f BLINK_COLOR = new Vector3f(1, 0.5f, 0.5f);
static {
STATE_COLORS = new EnumMap<>(DriveSlotState.class);
STATE_COLORS.put(DriveSlotState.OFFLINE, new Vector3f(0, 0, 0));
STATE_COLORS.put(DriveSlotState.ONLINE, new Vector3f(0, 1, 0));
STATE_COLORS.put(DriveSlotState.NOT_EMPTY, new Vector3f(0f, 0.667f, 1));
STATE_COLORS.put(DriveSlotState.TYPES_FULL, new Vector3f(1, 0.667f, 0));
STATE_COLORS.put(DriveSlotState.FULL, new Vector3f(1, 0, 0));
}
// The positions are based on the upper left slot in a drive
private static final float L = 5 / 16.f; // left (x-axis)
private static final float R = 4 / 16.f; // right (x-axis)
private static final float T = 1 / 16.f; // top (y-axis)
private static final float B = -0.001f / 16.f; // bottom (y-axis)
private static final float FR = -0.001f / 16.f; // front (z-axis)
private static final float BA = 0.499f / 16.f; // back (z-axis)
// Vertex data for the LED cuboid (has no back)
// Directions are when looking from the front onto the LED
private static final float[] LED_QUADS = {
// Front Face
R, T, FR, L, T, FR, L, B, FR, R, B, FR,
// Left Face
L, T, FR, L, T, BA, L, B, BA, L, B, FR,
// Right Face
R, T, BA, R, T, FR, R, B, FR, R, B, BA,
// Top Face
R, T, BA, L, T, BA, L, T, FR, R, T, FR,
// Bottom Face
R, B, FR, L, B, FR, L, B, BA, R, B, BA, };
public static final RenderType RENDER_LAYER = RenderType.makeType("ae_drive_leds",
DefaultVertexFormats.POSITION_COLOR, 7, 32565, false, true, RenderType.State.getBuilder().build(false));
public static void renderLed(IChestOrDrive drive, int slot, IVertexBuilder buffer, MatrixStack ms,
float partialTicks) {
Vector3f color = getColorForSlot(drive, slot, partialTicks);
if (color == null) {
return;
}
for (int i = 0; i < LED_QUADS.length; i += 3) {
float x = LED_QUADS[i];
float y = LED_QUADS[i + 1];
float z = LED_QUADS[i + 2];
buffer.pos(ms.getLast().getMatrix(), x, y, z).color(color.getX(), color.getY(), color.getZ(), 1.f)
.endVertex();
}
}
private static Vector3f getColorForSlot(IChestOrDrive drive, int slot, float partialTicks) {
DriveSlotState state = DriveSlotState.fromCellStatus(drive.getCellStatus(slot));
if (state == DriveSlotState.EMPTY) {
return null;
}
if (!drive.isPowered()) {
return STATE_COLORS.get(DriveSlotState.OFFLINE);
}
Vector3f col = STATE_COLORS.get(state);
if (drive.isCellBlinking(slot)) {
// 200 ms interval (100ms to get to red, then 100ms back)
long t = System.currentTimeMillis() % 200;
float f = (t - 100) / 200.0f + 0.5f;
f = easeInOutCubic(f);
col = col.copy();
col.lerp(BLINK_COLOR, f);
}
return col;
}
private static float easeInOutCubic(float x) {
return x < 0.5f ? 4 * x * x * x : 1 - (float) Math.pow(-2 * x + 2, 3) / 2;
}
private CellLedRenderer() {
}
}
@@ -0,0 +1,154 @@
/*
* 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.render.tesr;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ModelManager;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.client.model.data.EmptyModelData;
import net.minecraftforge.client.model.data.IModelData;
import appeng.api.client.ICellModelRegistry;
import appeng.block.storage.DriveSlotsState;
import appeng.client.render.DelegateBakedModel;
import appeng.client.render.FacingToRotation;
import appeng.core.Api;
import appeng.tile.storage.ChestTileEntity;
/**
* The tile entity renderer for ME chests takes care of rendering the right
* model for the inserted cell, as well as the LED.
*/
public class ChestTileEntityRenderer extends TileEntityRenderer<ChestTileEntity> {
private final ICellModelRegistry cellModelRegistry = Api.instance().client().cells();
private final ModelManager modelManager;
private final BlockModelRenderer blockRenderer;
public ChestTileEntityRenderer(TileEntityRendererDispatcher rendererDispatcherIn) {
super(rendererDispatcherIn);
Minecraft client = Minecraft.getInstance();
modelManager = client.getModelManager();
blockRenderer = client.getBlockRendererDispatcher().getBlockModelRenderer();
}
@Override
public void render(ChestTileEntity chest, float partialTicks, MatrixStack matrices, IRenderTypeBuffer buffers,
int combinedLight, int combinedOverlay) {
World world = chest.getWorld();
if (world == null) {
return;
}
DriveSlotsState driveSlotState = DriveSlotsState.fromChestOrDrive(chest);
Item cellItem = driveSlotState.getCell(0);
if (cellItem == null || cellItem == Items.AIR) {
return; // No cell inserted into chest
}
ResourceLocation cellModelLocation = cellModelRegistry.model(cellItem);
if (cellModelLocation == null) {
cellModelLocation = cellModelRegistry.getDefaultModel();
}
IBakedModel model = modelManager.getModel(cellModelLocation);
matrices.push();
matrices.translate(0.5, 0.5, 0.5);
FacingToRotation rotation = FacingToRotation.get(chest.getForward(), chest.getUp());
rotation.push(matrices);
matrices.translate(-0.5, -0.5, -0.5);
// The models are created for the top-left slot of the drive model,
// we need to move them into place for the slot on the ME chest
matrices.translate(5 / 16.0, 4 / 16.0, 0);
// Render the cell model as-if it was a block model
IVertexBuilder buffer = buffers.getBuffer(RenderType.getCutout());
// We "fake" the position here to make it use the light-value in front of the
// drive
FaceRotatingModel rotatedModel = new FaceRotatingModel(model, rotation);
blockRenderer.renderModel(world, rotatedModel, chest.getBlockState(), chest.getPos(), matrices, buffer, false,
new Random(), 0L, combinedOverlay, EmptyModelData.INSTANCE);
IVertexBuilder ledBuffer = buffers.getBuffer(CellLedRenderer.RENDER_LAYER);
CellLedRenderer.renderLed(chest, 0, ledBuffer, matrices, partialTicks);
matrices.pop();
}
/**
* The actual vertex data will be transformed using the matrix stack, but the
* faces will not be correctly rotated so the incorrect lighting data would be
* used to apply diffuse lighting and the lightmap texture.
*/
private static class FaceRotatingModel extends DelegateBakedModel {
private final FacingToRotation r;
protected FaceRotatingModel(IBakedModel base, FacingToRotation r) {
super(base);
this.r = r;
}
@Nonnull
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand,
@Nonnull IModelData extraData) {
if (side != null) {
side = r.rotate(side); // This fixes the incorrect lightmap position
}
List<BakedQuad> quads = new ArrayList<>(super.getQuads(state, side, rand, extraData));
for (int i = 0; i < quads.size(); i++) {
BakedQuad quad = quads.get(i);
quads.set(i, new BakedQuad(quad.getVertexData(), quad.getTintIndex(), r.rotate(quad.getFace()),
quad.func_187508_a(), quad.shouldApplyDiffuseLighting()));
}
return quads;
}
}
}
@@ -1,21 +1,17 @@
package appeng.client.render.tesr;
import java.util.EnumMap;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.Vector3f;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import appeng.block.storage.DriveSlotState;
import appeng.client.render.FacingToRotation;
import appeng.client.render.model.DriveBakedModel;
import appeng.tile.storage.DriveTileEntity;
/**
@@ -24,44 +20,6 @@ import appeng.tile.storage.DriveTileEntity;
@OnlyIn(Dist.CLIENT)
public class DriveLedTileEntityRenderer extends TileEntityRenderer<DriveTileEntity> {
private static final EnumMap<DriveSlotState, Vector3f> STATE_COLORS;
// Color used for the cell indicator for blinking during recent activity
private static final Vector3f BLINK_COLOR = new Vector3f(1, 0.5f, 0.5f);
static {
STATE_COLORS = new EnumMap<>(DriveSlotState.class);
STATE_COLORS.put(DriveSlotState.OFFLINE, new Vector3f(0, 0, 0));
STATE_COLORS.put(DriveSlotState.ONLINE, new Vector3f(0, 1, 0));
STATE_COLORS.put(DriveSlotState.NOT_EMPTY, new Vector3f(0f, 0.667f, 1));
STATE_COLORS.put(DriveSlotState.TYPES_FULL, new Vector3f(1, 0.667f, 0));
STATE_COLORS.put(DriveSlotState.FULL, new Vector3f(1, 0, 0));
}
private static final float L = 14 / 16.f; // left (x-axis)
private static final float R = 13 / 16.f; // right (x-axis)
private static final float T = 14 / 16.f; // top (x-axis)
private static final float B = 12.999f / 16.f; // bottom (x-axis)
private static final float FR = 0.999f / 16.f; // front (z-axis)
private static final float BA = 1.499f / 16.f; // back (z-axis)
// Vertex data for the LED cuboid (has no back)
// Directions are when looking from the front onto the LED
private static final float[] LED_QUADS = {
// Front Face
R, T, FR, L, T, FR, L, B, FR, R, B, FR,
// Left Face
L, T, FR, L, T, BA, L, B, BA, L, B, FR,
// Right Face
R, T, BA, R, T, FR, R, B, FR, R, B, BA,
// Top Face
R, T, BA, L, T, BA, L, T, FR, R, T, FR,
// Bottom Face
R, B, FR, L, B, FR, L, B, BA, R, B, BA, };
private static final RenderType STATE = RenderType.makeType("ae_drive_leds", DefaultVertexFormats.POSITION_COLOR, 7,
32565, false, true, RenderType.State.getBuilder().build(false));
public DriveLedTileEntityRenderer(TileEntityRendererDispatcher rendererDispatcherIn) {
super(rendererDispatcherIn);
}
@@ -79,32 +37,18 @@ public class DriveLedTileEntityRenderer extends TileEntityRenderer<DriveTileEnti
FacingToRotation.get(drive.getForward(), drive.getUp()).push(ms);
ms.translate(-0.5, -0.5, -0.5);
IVertexBuilder buffer = buffers.getBuffer(STATE);
IVertexBuilder buffer = buffers.getBuffer(CellLedRenderer.RENDER_LAYER);
Vector3f slotTranslation = new Vector3f();
for (int row = 0; row < 5; row++) {
for (int col = 0; col < 2; col++) {
int slot = row * 2 + col;
Vector3f color = getColorForSlot(drive, slot, partialTicks);
if (color == null) {
continue;
}
ms.push();
// Position this drive model copy at the correct slot. The transform is based on
// the
// cell-model being in slot 0,0 at the top left of the drive.
float xOffset = -col * 8 / 16.0f;
float yOffset = -row * 3 / 16.0f;
ms.translate(xOffset, yOffset, 0);
DriveBakedModel.getSlotOrigin(row, col, slotTranslation);
ms.translate(slotTranslation.getX(), slotTranslation.getY(), slotTranslation.getZ());
for (int i = 0; i < LED_QUADS.length; i += 3) {
float x = LED_QUADS[i];
float y = LED_QUADS[i + 1];
float z = LED_QUADS[i + 2];
buffer.pos(ms.getLast().getMatrix(), x, y, z).color(color.getX(), color.getY(), color.getZ(), 1.f)
.endVertex();
}
int slot = row * 2 + col;
CellLedRenderer.renderLed(drive, slot, buffer, ms, partialTicks);
ms.pop();
}
@@ -113,31 +57,4 @@ public class DriveLedTileEntityRenderer extends TileEntityRenderer<DriveTileEnti
ms.pop();
}
private Vector3f getColorForSlot(DriveTileEntity drive, int slot, float partialTicks) {
DriveSlotState state = DriveSlotState.fromCellStatus(drive.getCellStatus(slot));
if (state == DriveSlotState.EMPTY) {
return null;
}
if (!drive.isPowered()) {
return STATE_COLORS.get(DriveSlotState.OFFLINE);
}
Vector3f col = STATE_COLORS.get(state);
if (drive.isCellBlinking(slot)) {
// 200 ms interval (100ms to get to red, then 100ms back)
long t = System.currentTimeMillis() % 200;
float f = (t - 100) / 200.0f + 0.5f;
f = easeInOutCubic(f);
col = col.copy();
col.lerp(BLINK_COLOR, f);
}
return col;
}
private static float easeInOutCubic(float x) {
return x < 0.5f ? 4 * x * x * x : 1 - (float) Math.pow(-2 * x + 2, 3) / 2;
}
}
@@ -47,7 +47,6 @@ 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.IAEMultiBlock;
import appeng.me.cluster.implementations.CraftingCPUCluster;
import appeng.tile.crafting.CraftingTileEntity;
import appeng.util.Platform;
@@ -82,7 +81,7 @@ public class CraftingCPUContainer extends AEBaseContainer
}
if (te instanceof CraftingTileEntity) {
this.setCPU((ICraftingCPU) ((IAEMultiBlock) te).getCluster());
this.setCPU(((CraftingTileEntity) te).getCluster());
}
if (this.getNetwork() == null && Platform.isServer()) {
@@ -52,7 +52,7 @@ public class FormationPlaneContainer extends UpgradeableContainer {
return helper.open(player, locator);
}
@GuiSync(6)
@GuiSync(7)
public YesNo placeMode;
public FormationPlaneContainer(int id, final PlayerInventory ip, final FormationPlanePart te) {
@@ -18,7 +18,6 @@
package appeng.container.implementations;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.ContainerType;
@@ -33,6 +32,7 @@ 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;
@@ -58,7 +58,7 @@ public class LevelEmitterContainer extends UpgradeableContainer {
private final LevelEmitterPart lvlEmitter;
@OnlyIn(Dist.CLIENT)
private TextFieldWidget textField;
private NumberEntryWidget textField;
@GuiSync(2)
public LevelType lvType;
@GuiSync(3)
@@ -72,9 +72,9 @@ public class LevelEmitterContainer extends UpgradeableContainer {
}
@OnlyIn(Dist.CLIENT)
public void setTextField(final TextFieldWidget level) {
public void setTextField(final NumberEntryWidget level) {
this.textField = level;
this.textField.setText(String.valueOf(this.EmitterValue));
this.textField.setValue(this.EmitterValue);
}
public void setLevel(final long l, final PlayerEntity player) {
@@ -104,7 +104,7 @@ public class LevelEmitterContainer extends UpgradeableContainer {
final IItemHandler inv = this.getUpgradeable().getInventoryByName("config");
final int y = 40;
final int x = 80 + 44;
final int x = 80 + 57;
this.addSlot(new FakeTypeOnlySlot(inv, 0, x, y));
}
@@ -140,7 +140,7 @@ public class LevelEmitterContainer extends UpgradeableContainer {
public void onUpdate(final String field, final Object oldValue, final Object newValue) {
if (field.equals("EmitterValue")) {
if (this.textField != null) {
this.textField.setText(String.valueOf(this.EmitterValue));
this.textField.setValue(this.EmitterValue);
}
}
}
@@ -18,9 +18,6 @@
package appeng.container.implementations;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.player.ServerPlayerEntity;
@@ -264,21 +261,13 @@ public class PatternTermContainer extends MEMonitorableContainer
return new ItemStack[] { out };
}
} else {
final List<ItemStack> list = new ArrayList<>(3);
boolean hasValue = false;
final ItemStack[] list = new ItemStack[3];
for (final OptionalFakeSlot outputSlot : this.outputSlots) {
final ItemStack out = outputSlot.getStack();
if (!out.isEmpty() && out.getCount() > 0) {
list.add(out);
hasValue = true;
}
}
if (hasValue) {
return list.toArray(new ItemStack[list.size()]);
for (int i = 0; i < this.outputSlots.length; i++) {
final ItemStack out = this.outputSlots[i].getStack();
list[i] = out;
}
return list;
}
return null;
@@ -18,7 +18,6 @@
package appeng.container.implementations;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.ContainerType;
@@ -29,6 +28,7 @@ import net.minecraftforge.api.distmarker.OnlyIn;
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;
@@ -53,7 +53,8 @@ public class PriorityContainer extends AEBaseContainer {
private final IPriorityHost priHost;
@OnlyIn(Dist.CLIENT)
private TextFieldWidget textField;
private NumberEntryWidget textField;
@GuiSync(2)
public long PriorityValue = -1;
@@ -64,9 +65,9 @@ public class PriorityContainer extends AEBaseContainer {
}
@OnlyIn(Dist.CLIENT)
public void setTextField(final TextFieldWidget level) {
public void setTextField(final NumberEntryWidget level) {
this.textField = level;
this.textField.setText(String.valueOf(this.PriorityValue));
this.textField.setValue(this.PriorityValue, true);
}
public void setPriority(final int newValue, final PlayerEntity player) {
@@ -88,7 +89,7 @@ public class PriorityContainer extends AEBaseContainer {
public void onUpdate(final String field, final Object oldValue, final Object newValue) {
if (field.equals("PriorityValue")) {
if (this.textField != null) {
this.textField.setText(String.valueOf(this.PriorityValue));
this.textField.setValue(this.PriorityValue, true);
}
}
+19 -15
View File
@@ -53,6 +53,7 @@ import appeng.api.config.Settings;
import appeng.api.config.TerminalStyle;
import appeng.api.config.YesNo;
import appeng.api.features.AEFeature;
import appeng.client.gui.NumberEntryType;
import appeng.core.settings.TickRates;
import appeng.util.EnumCycler;
@@ -95,7 +96,7 @@ public final class AEConfig {
private boolean useColoredCraftingStatus;
private boolean disableColoredCableRecipesInJEI;
private int craftingCalculationTimePerTick;
private PowerUnits selectedPowerUnit;
private PowerUnits selectedPowerUnit = PowerUnits.AE;
// GUI Buttons
private final int[] craftByStacks = new int[4];
@@ -273,20 +274,23 @@ public final class AEConfig {
}
}
public int craftItemsByStackAmounts(final int i) {
return this.craftByStacks[i];
}
public int priorityByStacksAmounts(final int i) {
return this.priorityByStacks[i];
}
public int levelByStackAmounts(final int i) {
return this.levelByStacks[i];
}
public int levelByMillyBuckets(final int i) {
return this.levelByMillibuckets[i];
/**
* Returns an array with the quantity-steps for the +/- buttons in number entry
* dialogs of the given type. Guaranteed to have 4 entries.
*/
public int[] getNumberEntrySteps(NumberEntryType type) {
switch (type) {
case CRAFT_ITEM_COUNT:
return craftByStacks;
case PRIORITY:
return priorityByStacks;
case LEVEL_ITEM_COUNT:
return levelByStacks;
case LEVEL_FLUID_VOLUME:
return levelByMillibuckets;
default:
throw new IllegalArgumentException("Unknown number entry: " + type);
}
}
public PowerUnits getSelectedPowerUnit() {
@@ -1,18 +0,0 @@
package appeng.core;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.util.ResourceLocation;
public class AERecipeType<T extends IRecipe<?>> implements IRecipeType<T> {
private final String id;
public AERecipeType(ResourceLocation registryName) {
this.id = registryName.toString();
}
@Override
public String toString() {
return id;
}
}
+4 -10
View File
@@ -44,7 +44,6 @@ import net.minecraftforge.client.model.geometry.IModelGeometry;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.ModDimension;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.CrashReportExtender;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.client.registry.RenderingRegistry;
@@ -79,7 +78,6 @@ import appeng.client.render.model.MemoryCardModel;
import appeng.client.render.model.SkyCompassModel;
import appeng.client.render.model.UVLModelLoader;
import appeng.client.render.spatial.SpatialPylonModel;
import appeng.core.crash.ModCrashEnhancement;
import appeng.core.features.registries.PartModels;
import appeng.core.stats.AdvancementTriggers;
import appeng.core.sync.network.NetworkHandler;
@@ -115,9 +113,7 @@ public final class AppEng {
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, AEConfig.CLIENT_SPEC);
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, AEConfig.COMMON_SPEC);
proxy = DistExecutor.runForDist(() -> ClientHelper::new, () -> ServerHelper::new);
CrashReportExtender.registerCrashCallable(new ModCrashEnhancement());
proxy = DistExecutor.safeRunForDist(() -> ClientHelper::new, () -> ServerHelper::new);
CreativeTab.init();
new FacadeItemGroup(); // This call has a side-effect (adding it to the creative screen)
@@ -136,15 +132,14 @@ public final class AppEng {
modEventBus.addGenericListener(ModDimension.class, registration::registerModDimension);
modEventBus.addListener(Integrations::enqueueIMC);
modEventBus.addListener(this::commonSetup);
// Register client-only events
DistExecutor.runWhenOn(Dist.CLIENT, () -> registration::registerClientEvents);
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> modEventBus.addListener(this::clientSetup));
MinecraftForge.EVENT_BUS.addListener(TickHandler.INSTANCE::unloadWorld);
MinecraftForge.EVENT_BUS.addListener(TickHandler.INSTANCE::onTick);
TickHandler.setup(MinecraftForge.EVENT_BUS);
MinecraftForge.EVENT_BUS.addListener(this::onServerAboutToStart);
MinecraftForge.EVENT_BUS.addListener(this::serverStopped);
MinecraftForge.EVENT_BUS.addListener(this::serverStopping);
@@ -154,7 +149,6 @@ public final class AppEng {
}
private void commonSetup(FMLCommonSetupEvent event) {
ApiDefinitions definitions = Api.INSTANCE.definitions();
definitions.getRegistry().getBootstrapComponents(IInitComponent.class)
.forEachRemaining(IInitComponent::initialize);
@@ -300,7 +294,7 @@ public final class AppEng {
private void serverStopped(final FMLServerStoppedEvent event) {
WorldData.instance().onServerStoppped();
TickHandler.INSTANCE.shutdown();
TickHandler.instance().shutdown();
}
}
@@ -428,9 +428,6 @@ final class Registration {
public void registerRecipeSerializers(RegistryEvent.Register<IRecipeSerializer<?>> event) {
IForgeRegistry<IRecipeSerializer<?>> r = event.getRegistry();
GrinderRecipe.TYPE = new AERecipeType<>(GrinderRecipeSerializer.INSTANCE.getRegistryName());
InscriberRecipe.TYPE = new AERecipeType<>(InscriberRecipeSerializer.INSTANCE.getRegistryName());
FacadeItem facadeItem = (FacadeItem) Api.INSTANCE.definitions().items().facade().item();
r.registerAll(DisassembleRecipe.SERIALIZER, GrinderRecipeSerializer.INSTANCE,
InscriberRecipeSerializer.INSTANCE, FacadeRecipe.getSerializer(facadeItem));
@@ -97,6 +97,7 @@ import appeng.client.render.crafting.CraftingMonitorTESR;
import appeng.client.render.crafting.MonitorBakedModel;
import appeng.client.render.model.AutoRotatingBakedModel;
import appeng.client.render.spatial.SpatialPylonRendering;
import appeng.client.render.tesr.ChestTileEntityRenderer;
import appeng.client.render.tesr.CrankTESR;
import appeng.client.render.tesr.DriveLedTileEntityRenderer;
import appeng.client.render.tesr.SkyChestTESR;
@@ -426,7 +427,14 @@ public final class ApiBlocks implements IBlocks {
}).build())
.rendering(new DriveRendering()).build();
this.chest = registry.block("chest", ChestBlock::new).features(AEFeature.STORAGE_CELLS, AEFeature.ME_CHEST)
.tileEntity(registry.tileEntity("chest", ChestTileEntity.class, ChestTileEntity::new).build())
.tileEntity(registry.tileEntity("chest", ChestTileEntity.class, ChestTileEntity::new)
.rendering(new TileEntityRenderingCustomizer<ChestTileEntity>() {
@Override
@OnlyIn(Dist.CLIENT)
public void customize(TileEntityRendering<ChestTileEntity> rendering) {
rendering.tileEntityRenderer(ChestTileEntityRenderer::new);
}
}).build())
.rendering(new ChestRendering()).build();
this.iface = registry.block("interface", InterfaceBlock::new).features(AEFeature.INTERFACE)
.tileEntity(
@@ -1,38 +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>.
*/
package appeng.core.crash;
import net.minecraftforge.fml.common.ICrashCallable;
import net.minecraftforge.versions.forge.ForgeVersion;
import appeng.core.AEConfig;
public class ModCrashEnhancement implements ICrashCallable {
@Override
public String getLabel() {
return "AE2 Version";
}
@Override
public String call() throws Exception {
return AEConfig.CHANNEL + ' ' + AEConfig.VERSION + " for Forge " + ForgeVersion.getVersion();
}
}
@@ -27,7 +27,7 @@ public enum GuiText {
Chest, StoredEnergy, Of, Condenser, Drive, GrindStone, SkyChest,
VibrationChamber, SpatialIOPort, LevelEmitter, FluidLevelEmitter, Terminal,
VibrationChamber, SpatialIOPort, LevelEmitter, FluidLevelEmitter, FluidLevelEmitterUnit, Terminal,
Interface, FluidInterface, Config, StoredItems, StoredFluids, Patterns, ImportBus, ImportBusFluids, ExportBus,
ExportBusFluids,
@@ -32,6 +32,15 @@ import appeng.core.sync.network.INetworkInfo;
import appeng.core.sync.network.NetworkHandler;
public abstract class BasePacket {
/**
* Sadly {@link PacketBuffer#readString()} gets inlined by Proguard which means
* it's not available on the Server. This field has the default string length
* that is used for writeString, which then also should be used for readString
* when it has no special length requirements.
*/
public static final int MAX_STRING_LENGTH = 32767;
private PacketBuffer p;
public void serverPacketData(final INetworkInfo manager, final PlayerEntity player) {
@@ -103,6 +103,7 @@ public class BlockTransitionEffectPacket extends BasePacket {
playBreakOrPickupSound();
}
@OnlyIn(Dist.CLIENT)
private void spawnParticles() {
EnergyParticleData data = new EnergyParticleData(false, direction);
@@ -121,6 +122,7 @@ public class BlockTransitionEffectPacket extends BasePacket {
}
}
@OnlyIn(Dist.CLIENT)
private void playBreakOrPickupSound() {
SoundEvent soundEvent;
@@ -57,8 +57,8 @@ public class ConfigValuePacket extends BasePacket {
private final String Value;
public ConfigValuePacket(final PacketBuffer stream) {
this.Name = stream.readString();
this.Value = stream.readString();
this.Name = stream.readString(MAX_STRING_LENGTH);
this.Value = stream.readString(MAX_STRING_LENGTH);
}
// api
@@ -57,6 +57,6 @@ public class PaintedEntityPacket extends BasePacket {
@Override
public void clientPacketData(final INetworkInfo network, final PlayerEntity player) {
final PlayerColor pc = new PlayerColor(this.entityId, this.myColor, this.ticks);
TickHandler.INSTANCE.getPlayerColors().put(this.entityId, pc);
TickHandler.instance().getPlayerColors().put(this.entityId, pc);
}
}
@@ -125,7 +125,7 @@ public class CraftingJob implements Runnable, ICraftingJob {
public void run() {
try {
try {
TickHandler.INSTANCE.registerCraftingSimulation(this.world, this);
TickHandler.instance().registerCraftingSimulation(this.world, this);
this.handlePausing();
final Stopwatch timer = Stopwatch.createStarted();
@@ -85,7 +85,7 @@ public class CraftingTreeNode {
}
boolean notRecursive(final ICraftingPatternDetails details) {
IAEItemStack[] o = details.getCondensedOutputs();
Collection<IAEItemStack> o = details.getOutputs();
for (final IAEItemStack i : o) {
if (i.equals(this.what)) {
@@ -93,7 +93,7 @@ public class CraftingTreeNode {
}
}
o = details.getCondensedInputs();
o = details.getInputs();
for (final IAEItemStack i : o) {
if (i.equals(this.what)) {
@@ -64,10 +64,10 @@ public class CraftingTreeProcess {
final World world = job.getWorld();
if (details.isCraftable()) {
final IAEItemStack[] list = details.getInputs();
final IAEItemStack[] list = details.getSparseInputs();
final CraftingInventory ic = new CraftingInventory(new ContainerNull(), 3, 3);
final IAEItemStack[] is = details.getInputs();
final IAEItemStack[] is = details.getSparseInputs();
for (int x = 0; x < ic.getSizeInventory(); x++) {
ic.setInventorySlotContents(x, is[x] == null ? ItemStack.EMPTY : is[x].createItemStack());
}
@@ -82,11 +82,11 @@ public class CraftingTreeProcess {
}
}
for (final IAEItemStack part : details.getCondensedInputs()) {
for (final IAEItemStack part : details.getInputs()) {
final ItemStack g = part.createItemStack();
boolean isAnInput = false;
for (final IAEItemStack a : details.getCondensedOutputs()) {
for (final IAEItemStack a : details.getOutputs()) {
if (!g.isEmpty() && a != null && a.equals(g)) {
isAnInput = true;
}
@@ -114,7 +114,7 @@ public class CraftingTreeProcess {
} else {
// this is minor different then below, this slot uses the pattern, but kinda
// fudges it.
for (final IAEItemStack part : details.getCondensedInputs()) {
for (final IAEItemStack part : details.getInputs()) {
for (int x = 0; x < list.length; x++) {
final IAEItemStack comparePart = list[x];
if (part != null && part.equals(comparePart)) {
@@ -127,11 +127,11 @@ public class CraftingTreeProcess {
}
}
} else {
for (final IAEItemStack part : details.getCondensedInputs()) {
for (final IAEItemStack part : details.getInputs()) {
final ItemStack g = part.createItemStack();
boolean isAnInput = false;
for (final IAEItemStack a : details.getCondensedOutputs()) {
for (final IAEItemStack a : details.getOutputs()) {
if (!g.isEmpty() && a != null && a.equals(g)) {
isAnInput = true;
}
@@ -142,7 +142,7 @@ public class CraftingTreeProcess {
}
}
for (final IAEItemStack part : details.getCondensedInputs()) {
for (final IAEItemStack part : details.getInputs()) {
this.nodes.put(new CraftingTreeNode(cc, job, part.copy(), this, -1, depth + 1), part.getStackSize());
}
}
@@ -208,7 +208,7 @@ public class CraftingTreeProcess {
// assume its possible.
// add crafting results..
for (final IAEItemStack out : this.details.getCondensedOutputs()) {
for (final IAEItemStack out : this.details.getOutputs()) {
final IAEItemStack o = out.copy();
o.setStackSize(o.getStackSize() * i);
inv.injectItems(o, Actionable.MODULATE, src);
@@ -227,7 +227,7 @@ public class CraftingTreeProcess {
}
IAEItemStack getAmountCrafted(IAEItemStack what2) {
for (final IAEItemStack is : this.details.getCondensedOutputs()) {
for (final IAEItemStack is : this.details.getOutputs()) {
if (is.equals(what2)) {
what2 = what2.copy();
what2.setStackSize(is.getStackSize());
@@ -236,7 +236,7 @@ public class CraftingTreeProcess {
}
// more fuzzy!
for (final IAEItemStack is : this.details.getCondensedOutputs()) {
for (final IAEItemStack is : this.details.getOutputs()) {
if (is.getItem() == what2.getItem()
&& (is.getItem().isDamageable() || is.getItemDamage() == what2.getItemDamage())) {
what2 = is.copy();
@@ -1,4 +1,4 @@
package appeng.forge.data;
package appeng.datagen;
import net.minecraft.data.DataGenerator;
import net.minecraftforge.eventbus.api.SubscribeEvent;
@@ -6,8 +6,8 @@ import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
import appeng.core.AppEng;
import appeng.forge.data.providers.loot.BlockDropProvider;
import appeng.forge.data.providers.recipes.SlabStairRecipes;
import appeng.datagen.providers.loot.BlockDropProvider;
import appeng.datagen.providers.recipes.SlabStairRecipes;
@Mod.EventBusSubscriber(modid = AppEng.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class AE2DataGenerators {
@@ -1,4 +1,4 @@
package appeng.forge.data.providers;
package appeng.datagen.providers;
import net.minecraft.data.IDataProvider;
@@ -1,4 +1,4 @@
package appeng.forge.data.providers.loot;
package appeng.datagen.providers.loot;
import java.io.IOException;
import java.nio.file.Path;
@@ -33,7 +33,7 @@ import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
import net.minecraftforge.registries.ForgeRegistries;
import appeng.core.AppEng;
import appeng.forge.data.providers.IAE2DataProvider;
import appeng.datagen.providers.IAE2DataProvider;
public class BlockDropProvider extends BlockLootTables implements IAE2DataProvider {
private Map<Block, Function<Block, LootTable.Builder>> overrides = ImmutableMap.<Block, Function<Block, LootTable.Builder>>builder()
@@ -1,4 +1,4 @@
package appeng.forge.data.providers.recipes;
package appeng.datagen.providers.recipes;
import java.util.function.Consumer;
@@ -15,7 +15,7 @@ import net.minecraft.util.ResourceLocation;
import appeng.api.definitions.IBlockDefinition;
import appeng.core.AppEng;
import appeng.forge.data.providers.IAE2DataProvider;
import appeng.datagen.providers.IAE2DataProvider;
public class SlabStairRecipes extends RecipeProvider implements IAE2DataProvider {
@@ -46,6 +46,8 @@ public class ChunkLoaderTileEntity extends AEBaseTileEntity implements ITickable
@Override
public void remove() {
super.remove();
World world = getWorld();
if (world instanceof ServerWorld) {
ChunkPos chunkPos = new ChunkPos(getPos());
@@ -76,7 +76,7 @@ public class DebugCardItem extends AEBaseItem {
int grids = 0;
int totalNodes = 0;
for (final Grid g : TickHandler.INSTANCE.getGridList()) {
for (final Grid g : TickHandler.instance().getGridList()) {
grids++;
totalNodes += g.getNodes().size();
}
@@ -27,6 +27,7 @@ import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.world.World;
@@ -38,6 +39,8 @@ import appeng.util.Platform;
public final class SingularityEntity extends AEBaseItemEntity {
private static final ResourceLocation TAG_ENDER_PEARL = new ResourceLocation("forge:ender_pearls");
public static EntityType<SingularityEntity> TYPE;
private static int randTickSeed = 0;
@@ -84,6 +87,17 @@ public final class SingularityEntity extends AEBaseItemEntity {
if (!other.isEmpty()) {
boolean matches = false;
if (materials.enderDust().isSameAs(other)) {
matches = true;
}
// check... other name.
if (!matches) {
if (other.getItem().getTags().contains(TAG_ENDER_PEARL)) {
matches = true;
}
}
if (matches) {
while (item.getCount() > 0 && other.getCount() > 0) {
other.grow(-1);
+1 -1
View File
@@ -49,7 +49,7 @@ public class FacadePart implements IFacadePart {
@Override
public void getBoxes(final IPartCollisionHelper ch, boolean livingEntity) {
if (livingEntity) {
if (livingEntity || !ch.isBBCollision()) {
// prevent weird snag behavior
ch.addBox(0.0, 0.0, 14, 16.0, 16.0, 16.0);
} else {
@@ -1,17 +1,15 @@
package appeng.fluids.client.gui;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.client.util.InputMappings;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.text.ITextComponent;
import appeng.api.config.RedstoneMode;
import appeng.api.config.Settings;
import appeng.client.gui.NumberEntryType;
import appeng.client.gui.implementations.NumberEntryWidget;
import appeng.client.gui.implementations.UpgradeableScreen;
import appeng.client.gui.widgets.NumberBox;
import appeng.client.gui.widgets.ServerSettingToggleButton;
import appeng.core.AEConfig;
import appeng.core.localization.GuiText;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ConfigValuePacket;
@@ -19,7 +17,8 @@ import appeng.fluids.client.gui.widgets.FluidSlotWidget;
import appeng.fluids.container.FluidLevelEmitterContainer;
public class FluidLevelEmitterScreen extends UpgradeableScreen<FluidLevelEmitterContainer> {
private NumberBox level;
private NumberEntryWidget level;
public FluidLevelEmitterScreen(FluidLevelEmitterContainer container, PlayerInventory playerInventory,
ITextComponent title) {
@@ -30,17 +29,14 @@ public class FluidLevelEmitterScreen extends UpgradeableScreen<FluidLevelEmitter
public void init() {
super.init();
this.level = new NumberBox(this.font, this.guiLeft + 24, this.guiTop + 43, 79, this.font.FONT_HEIGHT,
Long.class);
this.level.setEnableBackgroundDrawing(false);
this.level.setMaxStringLength(16);
this.level.setTextColor(0xFFFFFF);
this.level.setVisible(true);
this.level.changeFocus(true);
this.level = new NumberEntryWidget(this, 20, 17, 138, 62, NumberEntryType.LEVEL_FLUID_VOLUME,
this::onLevelChange);
this.level.setTextFieldBounds(25, 44, 75);
container.setTextField(this.level);
this.level.addButtons(children::add, this::addButton);
final int y = 40;
final int x = 80 + 44;
final int x = 80 + 57;
this.guiSlots.add(new FluidSlotWidget(this.container.getFluidConfigInventory(), 0, 0, x, y));
}
@@ -48,22 +44,6 @@ public class FluidLevelEmitterScreen extends UpgradeableScreen<FluidLevelEmitter
protected void addButtons() {
this.redstoneMode = new ServerSettingToggleButton<>(this.guiLeft - 18, this.guiTop + 28,
Settings.REDSTONE_EMITTER, RedstoneMode.LOW_SIGNAL);
final int a = AEConfig.instance().levelByMillyBuckets(0);
final int b = AEConfig.instance().levelByMillyBuckets(1);
final int c = AEConfig.instance().levelByMillyBuckets(2);
final int d = AEConfig.instance().levelByMillyBuckets(3);
this.addButton(new Button(this.guiLeft + 20, this.guiTop + 17, 22, 20, "+" + a, btn -> addQty(a)));
this.addButton(new Button(this.guiLeft + 48, this.guiTop + 17, 28, 20, "+" + b, btn -> addQty(b)));
this.addButton(new Button(this.guiLeft + 82, this.guiTop + 17, 32, 20, "+" + c, btn -> addQty(c)));
this.addButton(new Button(this.guiLeft + 120, this.guiTop + 17, 38, 20, "+" + d, btn -> addQty(d)));
this.addButton(new Button(this.guiLeft + 20, this.guiTop + 59, 22, 20, "-" + a, btn -> addQty(-a)));
this.addButton(new Button(this.guiLeft + 48, this.guiTop + 59, 28, 20, "-" + b, btn -> addQty(-b)));
this.addButton(new Button(this.guiLeft + 82, this.guiTop + 59, 32, 20, "-" + c, btn -> addQty(-c)));
this.addButton(new Button(this.guiLeft + 120, this.guiTop + 59, 38, 20, "-" + d, btn -> addQty(-d)));
this.addButton(this.redstoneMode);
}
@@ -73,6 +53,13 @@ public class FluidLevelEmitterScreen extends UpgradeableScreen<FluidLevelEmitter
this.level.render(mouseX, mouseY, partialTicks);
}
@Override
public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) {
super.drawFG(offsetX, offsetY, mouseX, mouseY);
this.font.drawString(GuiText.FluidLevelEmitterUnit.getLocal(), 110, 44, COLOR_DARK_GRAY);
}
@Override
protected boolean drawUpgrades() {
return false;
@@ -92,89 +79,8 @@ public class FluidLevelEmitterScreen extends UpgradeableScreen<FluidLevelEmitter
protected void handleButtonVisibility() {
}
private void addQty(final long i) {
try {
String Out = this.level.getText();
boolean Fixed = false;
while (Out.startsWith("0") && Out.length() > 1) {
Out = Out.substring(1);
Fixed = true;
}
if (Fixed) {
this.level.setText(Out);
}
if (Out.isEmpty()) {
Out = "0";
}
long result = Long.parseLong(Out);
result += i;
if (result < 0) {
result = 0;
}
this.level.setText(Out = Long.toString(result));
NetworkHandler.instance().sendToServer(new ConfigValuePacket("FluidLevelEmitter.Value", Out));
} catch (final NumberFormatException e) {
// nope..
this.level.setText("0");
}
private void onLevelChange(long level) {
NetworkHandler.instance().sendToServer(new ConfigValuePacket("FluidLevelEmitter.Value", String.valueOf(level)));
}
@Override
public boolean charTyped(char character, int keyCode) {
if (level.charTyped(character, keyCode)) {
String Out = this.level.getText();
boolean Fixed = false;
while (Out.startsWith("0") && Out.length() > 1) {
Out = Out.substring(1);
Fixed = true;
}
if (Fixed) {
this.level.setText(Out);
}
if (Out.isEmpty()) {
Out = "0";
}
NetworkHandler.instance().sendToServer(new ConfigValuePacket("FluidLevelEmitter.Value", Out));
return true;
}
return super.charTyped(character, keyCode);
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int p_keyPressed_3_) {
if (!this.checkHotbarKeys(InputMappings.getInputByCode(keyCode, scanCode))) {
if ((keyCode == 211 || keyCode == 205 || keyCode == 203 || keyCode == 14)
&& this.level.keyPressed(keyCode, scanCode, p_keyPressed_3_)) {
String Out = this.level.getText();
boolean Fixed = false;
while (Out.startsWith("0") && Out.length() > 1) {
Out = Out.substring(1);
Fixed = true;
}
if (Fixed) {
this.level.setText(Out);
}
if (Out.isEmpty()) {
Out = "0";
}
NetworkHandler.instance().sendToServer(new ConfigValuePacket("FluidLevelEmitter.Value", Out));
return true;
}
}
return super.keyPressed(keyCode, scanCode, p_keyPressed_3_);
}
}
@@ -266,12 +266,15 @@ public class FluidTerminalScreen extends AEBaseMEScreen<FluidTerminalContainer>
@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.repo.setSearchString("");
this.repo.updateView();
this.setScrollBar();
}
return true;
}
// Right-clicking on the search field should clear it
if (this.searchField.isMouseOver(xCoord, yCoord) && btn == 1) {
this.searchField.setText("");
this.repo.setSearchString("");
this.repo.updateView();
this.setScrollBar();
return true;
}
@@ -332,4 +335,5 @@ public class FluidTerminalScreen extends AEBaseMEScreen<FluidTerminalContainer>
protected String getBackground() {
return "guis/terminal.png";
}
}
@@ -52,7 +52,8 @@ public class FluidSlotWidget extends CustomSlotWidget {
final float blue = (attributes.getColor() & 255) / 255.0F;
RenderSystem.color3f(red, green, blue);
blit(xPos(), yPos(), this.getBlitOffset(), getWidth(), getHeight(), sprite);
blit(getTooltipAreaX(), getTooltipAreaY(), this.getBlitOffset(), getTooltipAreaWidth(),
getTooltipAreaHeight(), sprite);
}
}
@@ -76,7 +77,7 @@ public class FluidSlotWidget extends CustomSlotWidget {
}
@Override
public String getMessage() {
public String getTooltipMessage() {
final IAEFluidStack fluid = this.getFluidStack();
if (fluid != null) {
return I18n.format(fluid.getFluidStack().getTranslationKey());
@@ -85,7 +86,7 @@ public class FluidSlotWidget extends CustomSlotWidget {
}
@Override
public boolean isVisible() {
public boolean isTooltipAreaVisible() {
return true;
}
@@ -85,7 +85,7 @@ public class FluidTankWidget extends Widget implements ITooltip {
}
@Override
public String getMessage() {
public String getTooltipMessage() {
final IAEFluidStack fluid = this.tank.getFluidInSlot(this.slot);
if (fluid != null && fluid.getStackSize() > 0) {
String desc = fluid.getFluid().getAttributes().getDisplayName(fluid.getFluidStack()).getFormattedText();
@@ -93,31 +93,31 @@ public class FluidTankWidget extends Widget implements ITooltip {
return desc + "\n" + amountToText;
}
return null;
return "";
}
@Override
public int xPos() {
public int getTooltipAreaX() {
return this.x - 2;
}
@Override
public int yPos() {
public int getTooltipAreaY() {
return this.y - 2;
}
@Override
public int getWidth() {
public int getTooltipAreaWidth() {
return this.width + 4;
}
@Override
public int getHeight() {
public int getTooltipAreaHeight() {
return this.height + 4;
}
@Override
public boolean isVisible() {
public boolean isTooltipAreaVisible() {
return true;
}
@@ -48,7 +48,8 @@ public class OptionalFluidSlotWidget extends FluidSlotWidget {
} else {
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 0.4F);
}
GuiUtils.drawTexturedModalRect(guileft + this.xPos() - 1, guitop + this.yPos() - 1, this.srcX - 1,
this.srcY - 1, this.getWidth() + 2, this.getHeight() + 2, currentZIndex);
GuiUtils.drawTexturedModalRect(guileft + this.getTooltipAreaX() - 1, guitop + this.getTooltipAreaY() - 1,
this.srcX - 1, this.srcY - 1, this.getTooltipAreaWidth() + 2, this.getTooltipAreaHeight() + 2,
currentZIndex);
}
}
@@ -1,6 +1,5 @@
package appeng.fluids.container;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.ContainerType;
@@ -11,6 +10,7 @@ import net.minecraftforge.api.distmarker.OnlyIn;
import appeng.api.config.RedstoneMode;
import appeng.api.config.SecurityPermissions;
import appeng.api.config.Settings;
import appeng.client.gui.implementations.NumberEntryWidget;
import appeng.container.ContainerLocator;
import appeng.container.guisync.GuiSync;
import appeng.container.implementations.ContainerHelper;
@@ -35,7 +35,7 @@ public class FluidLevelEmitterContainer extends FluidConfigurableContainer {
private final FluidLevelEmitterPart lvlEmitter;
@OnlyIn(Dist.CLIENT)
private TextFieldWidget textField;
private NumberEntryWidget textField;
@GuiSync(3)
public long EmitterValue = -1;
@@ -45,9 +45,9 @@ public class FluidLevelEmitterContainer extends FluidConfigurableContainer {
}
@OnlyIn(Dist.CLIENT)
public void setTextField(final TextFieldWidget level) {
public void setTextField(final NumberEntryWidget level) {
this.textField = level;
this.textField.setText(String.valueOf(this.EmitterValue));
this.textField.setValue(this.EmitterValue);
}
public void setLevel(final long l, final PlayerEntity player) {
@@ -87,7 +87,7 @@ public class FluidLevelEmitterContainer extends FluidConfigurableContainer {
public void onUpdate(final String field, final Object oldValue, final Object newValue) {
if (field.equals("EmitterValue")) {
if (this.textField != null) {
this.textField.setText(String.valueOf(this.EmitterValue));
this.textField.setValue(this.EmitterValue);
}
}
}
@@ -210,7 +210,7 @@ public class DualityFluidInterface
} else if (capabilityClass == Capabilities.STORAGE_MONITORABLE_ACCESSOR) {
return (LazyOptional<T>) LazyOptional.of(() -> this.accessor);
}
return null;
return LazyOptional.empty();
}
private boolean hasConfig() {
@@ -14,7 +14,6 @@ import net.minecraft.item.ItemStack;
import net.minecraft.tags.FluidTags;
import net.minecraft.tags.Tag;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
@@ -35,15 +34,12 @@ import appeng.api.networking.storage.IStorageGrid;
import appeng.api.networking.ticking.IGridTickable;
import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.networking.ticking.TickingRequest;
import appeng.api.parts.IPart;
import appeng.api.parts.IPartCollisionHelper;
import appeng.api.parts.IPartHost;
import appeng.api.parts.IPartModel;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.channels.IFluidStorageChannel;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation;
import appeng.core.Api;
import appeng.core.AppEng;
import appeng.core.settings.TickRates;
@@ -53,6 +49,7 @@ import appeng.items.parts.PartModels;
import appeng.me.GridAccessException;
import appeng.me.helpers.MachineSource;
import appeng.parts.BasicStatePart;
import appeng.parts.automation.PlaneConnectionHelper;
import appeng.parts.automation.PlaneConnections;
import appeng.parts.automation.PlaneModelData;
import appeng.parts.automation.PlaneModels;
@@ -73,115 +70,27 @@ public class FluidAnnihilationPlanePart extends BasicStatePart implements IGridT
private final IActionSource mySrc = new MachineSource(this);
private final PlaneConnectionHelper connectionHelper = new PlaneConnectionHelper(this);
public FluidAnnihilationPlanePart(final ItemStack is) {
super(is);
}
@Override
public void getBoxes(final IPartCollisionHelper bch) {
int minX = 1;
int minY = 1;
int maxX = 15;
int maxY = 15;
final IPartHost host = this.getHost();
if (host != null) {
final TileEntity te = host.getTile();
final BlockPos pos = te.getPos();
final Direction e = bch.getWorldX();
final Direction u = bch.getWorldY();
if (this.isAnnihilationPlane(te.getWorld().getTileEntity(pos.offset(e.getOpposite())), this.getSide())) {
minX = 0;
}
if (this.isAnnihilationPlane(te.getWorld().getTileEntity(pos.offset(e)), this.getSide())) {
maxX = 16;
}
if (this.isAnnihilationPlane(te.getWorld().getTileEntity(pos.offset(u.getOpposite())), this.getSide())) {
minY = 0;
}
if (this.isAnnihilationPlane(te.getWorld().getTileEntity(pos.offset(e)), this.getSide())) {
maxY = 16;
}
}
bch.addBox(5, 5, 14, 11, 11, 15);
bch.addBox(minX, minY, 15, maxX, maxY, 16);
connectionHelper.getBoxes(bch);
}
public PlaneConnections getConnections() {
final Direction facingRight, facingUp;
AEPartLocation location = this.getSide();
switch (location) {
case UP:
facingRight = Direction.EAST;
facingUp = Direction.NORTH;
break;
case DOWN:
facingRight = Direction.WEST;
facingUp = Direction.NORTH;
break;
case NORTH:
facingRight = Direction.WEST;
facingUp = Direction.UP;
break;
case SOUTH:
facingRight = Direction.EAST;
facingUp = Direction.UP;
break;
case WEST:
facingRight = Direction.SOUTH;
facingUp = Direction.UP;
break;
case EAST:
facingRight = Direction.NORTH;
facingUp = Direction.UP;
break;
default:
case INTERNAL:
return PlaneConnections.of(false, false, false, false);
}
boolean left = false, right = false, down = false, up = false;
final IPartHost host = this.getHost();
if (host != null) {
final TileEntity te = host.getTile();
final BlockPos pos = te.getPos();
if (this.isAnnihilationPlane(te.getWorld().getTileEntity(pos.offset(facingRight.getOpposite())),
this.getSide())) {
left = true;
}
if (this.isAnnihilationPlane(te.getWorld().getTileEntity(pos.offset(facingRight)), this.getSide())) {
right = true;
}
if (this.isAnnihilationPlane(te.getWorld().getTileEntity(pos.offset(facingUp.getOpposite())),
this.getSide())) {
down = true;
}
if (this.isAnnihilationPlane(te.getWorld().getTileEntity(pos.offset(facingUp)), this.getSide())) {
up = true;
}
}
return PlaneConnections.of(up, right, down, left);
return connectionHelper.getConnections();
}
@Override
public void onNeighborChanged(IBlockReader w, BlockPos pos, BlockPos neighbor) {
if (pos.offset(this.getSide().getFacing()).equals(neighbor)) {
this.refresh();
} else {
connectionHelper.updateConnections();
}
}
@@ -190,14 +99,6 @@ public class FluidAnnihilationPlanePart extends BasicStatePart implements IGridT
return 1;
}
private boolean isAnnihilationPlane(final TileEntity blockTileEntity, final AEPartLocation side) {
if (blockTileEntity instanceof IPartHost) {
final IPart p = ((IPartHost) blockTileEntity).getPart(side);
return p != null && p.getClass() == this.getClass();
}
return false;
}
private void refresh() {
try {
this.getProxy().getTick().alertDevice(this.getProxy().getNode());
@@ -19,13 +19,17 @@
package appeng.helpers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.Item;
@@ -46,14 +50,21 @@ import appeng.util.Platform;
public class CraftingPatternDetails implements ICraftingPatternDetails, Comparable<CraftingPatternDetails> {
private static final int ALL_INPUT_LIMIT = 9;
private static final int CRAFTING_OUTPUT_LIMIT = 1;
private static final int PROCESSING_OUTPUT_LIMIT = 3;
private static final Comparator<IAEItemStack> COMPARE_BY_STACKSIZE = (left, right) -> Long
.compare(right.getStackSize(), left.getStackSize());
private final CraftingInventory crafting = new CraftingInventory(new ContainerNull(), 3, 3);
private final CraftingInventory testFrame = new CraftingInventory(new ContainerNull(), 3, 3);
private final ItemStack correctOutput;
private final ICraftingRecipe standardRecipe;
private final IAEItemStack[] condensedInputs;
private final IAEItemStack[] condensedOutputs;
private final IAEItemStack[] inputs;
private final IAEItemStack[] outputs;
private final List<IAEItemStack> inputs;
private final List<IAEItemStack> outputs;
private final IAEItemStack[] sparseInputs;
private final IAEItemStack[] sparseOutputs;
private final boolean isCraftable;
private final boolean canSubstitute;
private final Set<TestLookup> failCache = new HashSet<>();
@@ -79,7 +90,7 @@ public class CraftingPatternDetails implements ICraftingPatternDetails, Comparab
final List<IAEItemStack> in = new ArrayList<>();
final List<IAEItemStack> out = new ArrayList<>();
for (int x = 0; x < 9; x++) {
for (int x = 0; x < ALL_INPUT_LIMIT; x++) {
final IAEItemStack ais = ingredients.get(x);
final ItemStack gs = ais != null ? ais.createItemStack() : ItemStack.EMPTY;
@@ -109,70 +120,19 @@ public class CraftingPatternDetails implements ICraftingPatternDetails, Comparab
this.standardRecipe = null;
this.correctOutput = ItemStack.EMPTY;
for (int x = 0; x < 3; x++) {
for (int x = 0; x < PROCESSING_OUTPUT_LIMIT; x++) {
final IAEItemStack ais = products.get(x);
final ItemStack gs = ais.createItemStack();
if (!gs.isEmpty()) {
out.add(ais.copy());
}
out.add(ais != null ? ais.copy() : null);
}
}
this.inputs = in.toArray(new IAEItemStack[0]);
this.outputs = out.toArray(new IAEItemStack[0]);
final int outputLength = this.isCraftable ? CRAFTING_OUTPUT_LIMIT : PROCESSING_OUTPUT_LIMIT;
this.sparseInputs = in.toArray(new IAEItemStack[ALL_INPUT_LIMIT]);
this.sparseOutputs = out.toArray(new IAEItemStack[outputLength]);
final Map<IAEItemStack, IAEItemStack> tmpOutputs = new HashMap<>();
for (final IAEItemStack io : this.outputs) {
if (io == null) {
continue;
}
final IAEItemStack g = tmpOutputs.get(io);
if (g == null) {
tmpOutputs.put(io, io.copy());
} else {
g.add(io);
}
}
final Map<IAEItemStack, IAEItemStack> tmpInputs = new HashMap<>();
for (final IAEItemStack io : this.inputs) {
if (io == null) {
continue;
}
final IAEItemStack g = tmpInputs.get(io);
if (g == null) {
tmpInputs.put(io, io.copy());
} else {
g.add(io);
}
}
if (tmpOutputs.isEmpty() || tmpInputs.isEmpty()) {
throw new IllegalStateException("No pattern here!");
}
this.condensedInputs = new IAEItemStack[tmpInputs.size()];
int offset = 0;
for (final IAEItemStack io : tmpInputs.values()) {
this.condensedInputs[offset] = io;
offset++;
}
offset = 0;
this.condensedOutputs = new IAEItemStack[tmpOutputs.size()];
for (final IAEItemStack io : tmpOutputs.values()) {
this.condensedOutputs[offset] = io;
offset++;
}
this.inputs = this.condenseStacks(in);
this.outputs = this.condenseStacks(out);
}
private void markItemAs(final int slotIndex, final ItemStack i, final TestStatus b) {
@@ -213,8 +173,8 @@ public class CraftingPatternDetails implements ICraftingPatternDetails, Comparab
this.testFrame.setInventorySlotContents(slotIndex, i);
// If we cannot substitute, the items must match exactly
if (!canSubstitute && slotIndex < inputs.length) {
if (!inputs[slotIndex].isSameType(i)) {
if (!canSubstitute && slotIndex < sparseInputs.length) {
if (!sparseInputs[slotIndex].isSameType(i)) {
this.markItemAs(slotIndex, i, TestStatus.DECLINE);
return false;
}
@@ -240,25 +200,25 @@ public class CraftingPatternDetails implements ICraftingPatternDetails, Comparab
}
@Override
public IAEItemStack[] getInputs() {
public IAEItemStack[] getSparseInputs() {
return this.sparseInputs;
}
@Override
public List<IAEItemStack> getInputs() {
return this.inputs;
}
@Override
public IAEItemStack[] getCondensedInputs() {
return this.condensedInputs;
}
@Override
public IAEItemStack[] getCondensedOutputs() {
return this.condensedOutputs;
}
@Override
public IAEItemStack[] getOutputs() {
public List<IAEItemStack> getOutputs() {
return this.outputs;
}
@Override
public IAEItemStack[] getSparseOutputs() {
return this.sparseOutputs;
}
@Override
public boolean canSubstitute() {
return this.canSubstitute;
@@ -276,8 +236,8 @@ public class CraftingPatternDetails implements ICraftingPatternDetails, Comparab
}
}
if (this.outputs != null && this.outputs.length > 0) {
return this.outputs[0].createItemStack();
if (this.sparseOutputs != null && this.sparseOutputs.length > 0) {
return this.sparseOutputs[0].createItemStack();
}
return ItemStack.EMPTY;
@@ -344,6 +304,29 @@ public class CraftingPatternDetails implements ICraftingPatternDetails, Comparab
return false;
}
/**
* Merges all equal entries into a single one while adding their total stack
* sizes.
*
* @throws IllegalStateException if the result would be empty.
*
* @param collection the collection to condense
*
* @return a non empty list of condensed stacks.
*/
private List<IAEItemStack> condenseStacks(Collection<IAEItemStack> collection) {
final List<IAEItemStack> merged = collection.stream().filter(Objects::nonNull)
.collect(Collectors.toMap(Function.identity(), IAEItemStack::copy,
(left, right) -> left.setStackSize(left.getStackSize() + right.getStackSize())))
.values().stream().sorted(COMPARE_BY_STACKSIZE).collect(ImmutableList.toImmutableList());
if (merged.isEmpty()) {
throw new IllegalStateException("No pattern here!");
}
return merged;
}
private enum TestStatus {
ACCEPT, DECLINE, TEST
}
+72 -42
View File
@@ -25,6 +25,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.WeakHashMap;
@@ -36,11 +37,15 @@ import com.google.common.collect.Multimap;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.event.TickEvent.ClientTickEvent;
import net.minecraftforge.event.TickEvent.Phase;
import net.minecraftforge.event.TickEvent.Type;
import net.minecraftforge.event.TickEvent.ServerTickEvent;
import net.minecraftforge.event.TickEvent.WorldTickEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.DistExecutor.SafeRunnable;
import appeng.api.networking.IGridNode;
import appeng.api.parts.CableRenderMode;
@@ -58,17 +63,39 @@ import appeng.util.Platform;
public class TickHandler {
public static final TickHandler INSTANCE = new TickHandler();
private static final TickHandler INSTANCE = new TickHandler();
private final Queue<IWorldCallable<?>> serverQueue = new ArrayDeque<>();
private final Multimap<World, CraftingJob> craftingJobs = LinkedListMultimap.create();
private final WeakHashMap<IWorld, Queue<IWorldCallable<?>>> callQueue = new WeakHashMap<>();
private final Map<IWorld, Queue<IWorldCallable<?>>> callQueue = new WeakHashMap<>();
private final HandlerRep server = new HandlerRep();
private final HandlerRep client = new HandlerRep();
private final HashMap<Integer, PlayerColor> cliPlayerColors = new HashMap<>();
private final HashMap<Integer, PlayerColor> srvPlayerColors = new HashMap<>();
private final Map<Integer, PlayerColor> cliPlayerColors = new HashMap<>();
private final Map<Integer, PlayerColor> srvPlayerColors = new HashMap<>();
private CableRenderMode crm = CableRenderMode.STANDARD;
public HashMap<Integer, PlayerColor> getPlayerColors() {
public static TickHandler instance() {
return INSTANCE;
}
public static void setup(IEventBus eventBus) {
eventBus.addListener(INSTANCE::onServerTick);
eventBus.addListener(INSTANCE::onWorldTick);
eventBus.addListener(INSTANCE::onUnloadWorld);
// DistExecutor does not like functional interfaces
DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> new SafeRunnable() {
private static final long serialVersionUID = 5221919736953944125L;
@Override
public void run() {
eventBus.addListener(INSTANCE::onClientTick);
}
});
}
public Map<Integer, PlayerColor> getPlayerColors() {
if (Platform.isServer()) {
return this.srvPlayerColors;
}
@@ -91,8 +118,8 @@ public class TickHandler {
}
public void addInit(final AEBaseTileEntity tile) {
if (Platform.isServer()) // for no there is no reason to care about this on the client...
{
// for no there is no reason to care about this on the client...
if (Platform.isServer()) {
this.getRepo().tiles.add(tile);
}
}
@@ -105,15 +132,15 @@ public class TickHandler {
}
public void addNetwork(final Grid grid) {
if (Platform.isServer()) // for no there is no reason to care about this on the client...
{
// for no there is no reason to care about this on the client...
if (Platform.isServer()) {
this.getRepo().addNetwork(grid);
}
}
public void removeNetwork(final Grid grid) {
if (Platform.isServer()) // for no there is no reason to care about this on the client...
{
// for no there is no reason to care about this on the client...
if (Platform.isServer()) {
this.getRepo().removeNetwork(grid);
}
}
@@ -126,9 +153,9 @@ public class TickHandler {
this.getRepo().clear();
}
public void unloadWorld(final WorldEvent.Unload ev) {
if (Platform.isServer()) // for no there is no reason to care about this on the client...
{
public void onUnloadWorld(final WorldEvent.Unload ev) {
// for no there is no reason to care about this on the client...
if (Platform.isServer()) {
final List<IGridNode> toDestroy = new ArrayList<>();
this.getRepo().updateNetworks();
@@ -146,25 +173,36 @@ public class TickHandler {
}
}
public void onTick(final TickEvent ev) {
if (ev.type == Type.CLIENT && ev.phase == Phase.START) {
public void onClientTick(final ClientTickEvent ev) {
if (ev.phase == Phase.START) {
this.tickColors(this.cliPlayerColors);
final CableRenderMode currentMode = Api.instance().partHelper().getCableRenderMode();
if (currentMode != this.crm) {
this.crm = currentMode;
AppEng.proxy.triggerUpdates();
}
}
}
if (ev.type == Type.WORLD && ev.phase == Phase.END) {
final WorldTickEvent wte = (WorldTickEvent) ev;
public void onWorldTick(final WorldTickEvent ev) {
if (ev.phase == Phase.START) {
final World world = ev.world;
final Queue<IWorldCallable<?>> queue = this.callQueue.get(world);
this.processQueue(queue, world);
}
if (ev.phase == Phase.END) {
synchronized (this.craftingJobs) {
final Collection<CraftingJob> jobSet = this.craftingJobs.get(wte.world);
final Collection<CraftingJob> jobSet = this.craftingJobs.get(ev.world);
if (!jobSet.isEmpty()) {
final int simTime = Math.max(1,
AEConfig.instance().getCraftingCalculationTimePerTick() / jobSet.size());
final int jobSize = jobSet.size();
final int microSecondsPerTick = AEConfig.instance().getCraftingCalculationTimePerTick() * 1000;
final int simTime = Math.max(1, microSecondsPerTick / jobSize);
final Iterator<CraftingJob> i = jobSet.iterator();
while (i.hasNext()) {
final CraftingJob cj = i.next();
if (!cj.simulateFor(simTime)) {
@@ -174,10 +212,12 @@ public class TickHandler {
}
}
}
}
// for no there is no reason to care about this on the client...
else if (ev.type == Type.SERVER && ev.phase == Phase.END) {
public void onServerTick(final ServerTickEvent ev) {
if (ev.phase == Phase.END) {
this.tickColors(this.srvPlayerColors);
// ready tiles.
final HandlerRep repo = this.getRepo();
while (!repo.tiles.isEmpty()) {
@@ -196,17 +236,17 @@ public class TickHandler {
// cross world queue.
this.processQueue(this.serverQueue, null);
}
}
// world synced queue(s)
if (ev.type == Type.WORLD && ev.phase == Phase.START) {
final World world = ((WorldTickEvent) ev).world;
final Queue<IWorldCallable<?>> queue = this.callQueue.get(world);
this.processQueue(queue, world);
public void registerCraftingSimulation(final World world, final CraftingJob craftingJob) {
synchronized (this.craftingJobs) {
this.craftingJobs.put(world, craftingJob);
}
}
private void tickColors(final HashMap<Integer, PlayerColor> playerSet) {
private void tickColors(final Map<Integer, PlayerColor> playerSet) {
final Iterator<PlayerColor> i = playerSet.values().iterator();
while (i.hasNext()) {
final PlayerColor pc = i.next();
if (pc.ticksLeft <= 0) {
@@ -235,16 +275,6 @@ public class TickHandler {
AELog.debug(e);
}
}
// long time = sw.elapsed( TimeUnit.MILLISECONDS );
// if ( time > 0 )
// AELog.info( "processQueue Time: " + time + "ms" );
}
public void registerCraftingSimulation(final World world, final CraftingJob craftingJob) {
synchronized (this.craftingJobs) {
this.craftingJobs.put(world, craftingJob);
}
}
private static class HandlerRep {
@@ -19,6 +19,7 @@
package appeng.items.misc;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
@@ -155,8 +156,8 @@ public class EncodedPatternItem extends AEBaseItem {
final boolean isCrafting = details.isCraftable();
final boolean substitute = details.canSubstitute();
final IAEItemStack[] in = details.getCondensedInputs();
final IAEItemStack[] out = details.getCondensedOutputs();
final Collection<IAEItemStack> in = details.getInputs();
final Collection<IAEItemStack> out = details.getOutputs();
final ITextComponent label = (isCrafting ? GuiText.Crafts.textComponent() : GuiText.Creates.textComponent())
.appendText(": ");
@@ -208,7 +209,7 @@ public class EncodedPatternItem extends AEBaseItem {
final ICraftingPatternDetails details = Api.instance().crafting().decodePattern(item, w);
out = details != null ? details.getOutputs()[0].createItemStack() : ItemStack.EMPTY;
out = details != null ? details.getOutputs().get(0).createItemStack() : ItemStack.EMPTY;
SIMPLE_CACHE.put(item, out);
return out;
@@ -226,7 +227,9 @@ public class EncodedPatternItem extends AEBaseItem {
final CompoundNBT tag = itemStack.getTag();
Preconditions.checkArgument(tag != null, "itemStack missing a NBT tag");
return new ResourceLocation(tag.getString(NBT_RECIPE_ID));
return tag.contains(NBT_RECIPE_ID, Constants.NBT.TAG_STRING)
? new ResourceLocation(tag.getString(NBT_RECIPE_ID))
: null;
}
public List<IAEItemStack> getIngredients(ItemStack itemStack) {
@@ -279,7 +282,7 @@ public class EncodedPatternItem extends AEBaseItem {
Preconditions.checkArgument(tag != null, "itemStack missing a NBT tag");
return getCraftingRecipeId(itemStack) == null && tag.getBoolean(NBT_SUBSITUTE);
return getCraftingRecipeId(itemStack) != null && tag.getBoolean(NBT_SUBSITUTE);
}
/**
@@ -118,6 +118,9 @@ public abstract class AbstractStorageCell<T extends IAEStack<T>> extends AEBaseI
@Override
public FuzzyMode getFuzzyMode(final ItemStack is) {
final String fz = is.getOrCreateTag().getString("FuzzyMode");
if (fz.isEmpty()) {
return FuzzyMode.IGNORE_ALL;
}
try {
return FuzzyMode.valueOf(fz);
} catch (final Throwable t) {
@@ -188,26 +188,24 @@ public class MatterCannonItem extends AEBasePoweredItem implements IStorageCell<
for (int l = 0; l < list.size(); ++l) {
final Entity entity1 = (Entity) list.get(l);
if (!entity1.isAlive() && entity1 != p && !(entity1 instanceof ItemEntity)) {
if (entity1.isAlive()) {
// prevent killing / flying of mounts.
if (entity1.isRidingOrBeingRiddenBy(p)) {
continue;
}
if (entity1.isAlive() && entity1 != p && !(entity1 instanceof ItemEntity)) {
// prevent killing / flying of mounts.
if (entity1.isRidingOrBeingRiddenBy(p)) {
continue;
}
final float f1 = 0.3F;
final float f1 = 0.3F;
final AxisAlignedBB boundingBox = entity1.getBoundingBox().grow(f1, f1, f1);
final Vec3d intersection = boundingBox.rayTrace(Vec3d, Vec3d1).orElse(null);
final AxisAlignedBB boundingBox = entity1.getBoundingBox().grow(f1, f1, f1);
final Vec3d intersection = boundingBox.rayTrace(Vec3d, Vec3d1).orElse(null);
if (intersection != null) {
final double nd = Vec3d.squareDistanceTo(intersection);
if (intersection != null) {
final double nd = Vec3d.squareDistanceTo(intersection);
if (nd < closest) {
entity = entity1;
entityIntersection = intersection;
closest = nd;
}
if (nd < closest) {
entity = entity1;
entityIntersection = intersection;
closest = nd;
}
}
}
@@ -246,7 +244,7 @@ public class MatterCannonItem extends AEBasePoweredItem implements IStorageCell<
final int id = entityHit.getEntityId();
final PlayerColor marker = new PlayerColor(id, col, 20 * 30);
TickHandler.INSTANCE.getPlayerColors().put(id, marker);
TickHandler.instance().getPlayerColors().put(id, marker);
if (entityHit instanceof SheepEntity) {
final SheepEntity sh = (SheepEntity) entityHit;
@@ -72,10 +72,12 @@ public class QuartzCuttingKnifeItem extends AEBaseItem implements IGuiItem {
@Override
public ItemStack getContainerItem(final ItemStack itemStack) {
ItemStack copy = itemStack.copy();
copy.setDamage(itemStack.getDamage() + 1);
return copy;
ItemStack damagedStack = itemStack.copy();
if (damagedStack.attemptDamageItem(1, random, null)) {
return ItemStack.EMPTY;
} else {
return damagedStack;
}
}
@Override
+2 -2
View File
@@ -64,7 +64,7 @@ public class Grid implements IGrid {
this.postEvent(new MENetworkPostCacheConstruction());
TickHandler.INSTANCE.addNetwork(this);
TickHandler.instance().addNetwork(this);
center.setGrid(this);
}
@@ -112,7 +112,7 @@ public class Grid implements IGrid {
this.pivot = (GridNode) n.next();
} else {
this.pivot = null;
TickHandler.INSTANCE.removeNetwork(this);
TickHandler.instance().removeNetwork(this);
this.myStorage.remove();
}
}
+2 -2
View File
@@ -384,7 +384,7 @@ public class GridNode implements IGridNode, IPathItem {
GridConnection.create(node, this, f.getOpposite());
} catch (SecurityConnectionException e) {
AELog.debug(e);
TickHandler.INSTANCE.addCallable(node.getWorld(), new MachineSecurityBreak(this));
TickHandler.instance().addCallable(node.getWorld(), new MachineSecurityBreak(this));
return;
} catch (final FailedConnectionException e) {
@@ -411,7 +411,7 @@ public class GridNode implements IGridNode, IPathItem {
} catch (SecurityConnectionException e) {
AELog.debug(e);
TickHandler.INSTANCE.addCallable(node.getWorld(), new MachineSecurityBreak(this));
TickHandler.instance().addCallable(node.getWorld(), new MachineSecurityBreak(this));
return;
} catch (final FailedConnectionException e) {
+87 -21
View File
@@ -23,16 +23,19 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.NavigableSet;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import java.util.SortedSet;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable;
import appeng.api.config.PowerMultiplier;
@@ -72,10 +75,33 @@ public class EnergyGridCache implements IEnergyGrid {
return Double.compare(percent1, percent2);
};
private static final Comparator<IAEPowerStorage> COMPARATOR_HIGHEST_PRIORITY_FIRST = (o1, o2) -> {
final int cmp = Integer.compare(o2.getPriority(), o1.getPriority());
return cmp != 0 ? cmp : Integer.compare(System.identityHashCode(o2), System.identityHashCode(o1));
};
private static final Comparator<IAEPowerStorage> COMPARATOR_LOWEST_PRIORITY_FIRST = (o1,
o2) -> -COMPARATOR_HIGHEST_PRIORITY_FIRST.compare(o1, o2);
private final NavigableSet<EnergyThreshold> interests = Sets.newTreeSet();
private final double averageLength = 40.0;
private final Set<IAEPowerStorage> providers = new LinkedHashSet<>();
private final Set<IAEPowerStorage> requesters = new LinkedHashSet<>();
// Should only be modified from the add/remove methods below to guard against
// concurrent modifications
private final SortedSet<IAEPowerStorage> providers = new ObjectRBTreeSet<>(COMPARATOR_HIGHEST_PRIORITY_FIRST);
// Used to track whether an extraction is currently in progress, to fail fast
// when something externally
// modifies the energy grid.
private boolean ongoingExtractOperation = false;
// Should only be modified from the add/remove methods below to guard against
// concurrent modifications
private final SortedSet<IAEPowerStorage> requesters = new ObjectRBTreeSet<>(COMPARATOR_LOWEST_PRIORITY_FIRST);
// Used to track whether an injection is currently in progress, to fail fast
// when something externally
// modifies the energy grid.
private boolean ongoingInjectOperation = false;
private final Multiset<IEnergyGridProvider> energyGridProviders = HashMultiset.create();
private final IGrid myGrid;
private final HashMap<IGridNode, IEnergyWatcher> watchers = new HashMap<>();
@@ -138,12 +164,12 @@ public class EnergyGridCache implements IEnergyGrid {
switch (ev.type) {
case PROVIDE_POWER:
if (ev.storage.getPowerFlow() != AccessRestriction.WRITE) {
this.providers.add(ev.storage);
addProvider(ev.storage);
}
break;
case REQUEST_POWER:
if (ev.storage.getPowerFlow() != AccessRestriction.READ) {
this.requesters.add(ev.storage);
addRequester(ev.storage);
}
break;
}
@@ -271,16 +297,21 @@ public class EnergyGridCache implements IEnergyGrid {
final Iterator<IAEPowerStorage> it = this.providers.iterator();
while (extractedPower < amt && it.hasNext()) {
final IAEPowerStorage node = it.next();
ongoingExtractOperation = true;
try {
while (extractedPower < amt && it.hasNext()) {
final IAEPowerStorage node = it.next();
final double req = amt - extractedPower;
final double newPower = node.extractAEPower(req, mode, PowerMultiplier.ONE);
extractedPower += newPower;
final double req = amt - extractedPower;
final double newPower = node.extractAEPower(req, mode, PowerMultiplier.ONE);
extractedPower += newPower;
if (newPower < req && mode == Actionable.MODULATE) {
it.remove();
if (newPower < req && mode == Actionable.MODULATE) {
it.remove();
}
}
} finally {
ongoingExtractOperation = false;
}
final double result = Math.min(extractedPower, amt);
@@ -303,13 +334,18 @@ public class EnergyGridCache implements IEnergyGrid {
final Iterator<IAEPowerStorage> it = this.requesters.iterator();
while (amt > 0 && it.hasNext()) {
final IAEPowerStorage node = it.next();
amt = node.injectAEPower(amt, mode);
ongoingInjectOperation = true;
try {
while (amt > 0 && it.hasNext()) {
final IAEPowerStorage node = it.next();
amt = node.injectAEPower(amt, mode);
if (amt > 0 && mode == Actionable.MODULATE) {
it.remove();
if (amt > 0 && mode == Actionable.MODULATE) {
it.remove();
}
}
} finally {
ongoingInjectOperation = false;
}
final double overflow = Math.max(0.0, amt);
@@ -442,8 +478,8 @@ public class EnergyGridCache implements IEnergyGrid {
this.globalAvailablePower -= ps.getAECurrentPower();
}
this.providers.remove(ps);
this.requesters.remove(ps);
removeProvider(ps);
removeRequester(ps);
}
}
@@ -457,6 +493,30 @@ public class EnergyGridCache implements IEnergyGrid {
}
}
private void addRequester(IAEPowerStorage requester) {
Preconditions.checkState(!ongoingInjectOperation,
"Cannot modify energy requesters while energy is being injected.");
this.requesters.add(requester);
}
private void removeRequester(IAEPowerStorage requester) {
Preconditions.checkState(!ongoingInjectOperation,
"Cannot modify energy requesters while energy is being injected.");
this.requesters.add(requester);
}
private void addProvider(IAEPowerStorage provider) {
Preconditions.checkState(!ongoingExtractOperation,
"Cannot modify energy providers while energy is being extracted.");
this.providers.add(provider);
}
private void removeProvider(IAEPowerStorage provider) {
Preconditions.checkState(!ongoingExtractOperation,
"Cannot modify energy providers while energy is being extracted.");
this.providers.remove(provider);
}
@Override
public void addNode(final IGridNode node, final IGridHost machine) {
if (machine instanceof IEnergyGridProvider) {
@@ -482,11 +542,11 @@ public class EnergyGridCache implements IEnergyGrid {
if (current > 0 && ps.getPowerFlow() != AccessRestriction.WRITE) {
this.globalAvailablePower += current;
this.providers.add(ps);
addProvider(ps);
}
if (current < max && ps.getPowerFlow() != AccessRestriction.READ) {
this.requesters.add(ps);
addRequester(ps);
}
}
}
@@ -572,6 +632,12 @@ public class EnergyGridCache implements IEnergyGrid {
return this.stored;
}
@Override
public int getPriority() {
// MIN_VALUE to push it to the back
return Integer.MIN_VALUE;
}
private void addCurrentAEPower(double amount) {
this.stored += amount;
+32 -20
View File
@@ -82,21 +82,21 @@ public class SpatialPylonCache implements ISpatialCache {
int pylonBlocks = 0;
for (final SpatialPylonCluster cl : this.clusters.values()) {
if (this.captureMax == null) {
this.captureMax = cl.getMax().copy();
this.captureMax = new DimensionalCoord(cl.getWorld(), cl.getBoundsMax());
}
if (this.captureMin == null) {
this.captureMin = cl.getMin().copy();
this.captureMin = new DimensionalCoord(cl.getWorld(), cl.getBoundsMin());
}
pylonBlocks += cl.tileCount();
this.captureMin.x = Math.min(this.captureMin.x, cl.getMin().x);
this.captureMin.y = Math.min(this.captureMin.y, cl.getMin().y);
this.captureMin.z = Math.min(this.captureMin.z, cl.getMin().z);
this.captureMin.x = Math.min(this.captureMin.x, cl.getBoundsMin().getX());
this.captureMin.y = Math.min(this.captureMin.y, cl.getBoundsMin().getY());
this.captureMin.z = Math.min(this.captureMin.z, cl.getBoundsMin().getZ());
this.captureMax.x = Math.max(this.captureMax.x, cl.getMax().x);
this.captureMax.y = Math.max(this.captureMax.y, cl.getMax().y);
this.captureMax.z = Math.max(this.captureMax.z, cl.getMax().z);
this.captureMax.x = Math.max(this.captureMax.x, cl.getBoundsMax().getX());
this.captureMax.y = Math.max(this.captureMax.y, cl.getBoundsMax().getY());
this.captureMax.z = Math.max(this.captureMax.z, cl.getBoundsMax().getZ());
}
double maxPower = 0;
@@ -110,28 +110,40 @@ public class SpatialPylonCache implements ISpatialCache {
case X:
this.isValid = this.isValid
&& ((this.captureMax.y == cl.getMin().y || this.captureMin.y == cl.getMax().y)
|| (this.captureMax.z == cl.getMin().z || this.captureMin.z == cl.getMax().z))
&& ((this.captureMax.y == cl.getMax().y || this.captureMin.y == cl.getMin().y)
|| (this.captureMax.z == cl.getMax().z || this.captureMin.z == cl.getMin().z));
&& ((this.captureMax.y == cl.getBoundsMin().getY()
|| this.captureMin.y == cl.getBoundsMax().getY())
|| (this.captureMax.z == cl.getBoundsMin().getZ()
|| this.captureMin.z == cl.getBoundsMax().getZ()))
&& ((this.captureMax.y == cl.getBoundsMax().getY()
|| this.captureMin.y == cl.getBoundsMin().getY())
|| (this.captureMax.z == cl.getBoundsMax().getZ()
|| this.captureMin.z == cl.getBoundsMin().getZ()));
break;
case Y:
this.isValid = this.isValid
&& ((this.captureMax.x == cl.getMin().x || this.captureMin.x == cl.getMax().x)
|| (this.captureMax.z == cl.getMin().z || this.captureMin.z == cl.getMax().z))
&& ((this.captureMax.x == cl.getMax().x || this.captureMin.x == cl.getMin().x)
|| (this.captureMax.z == cl.getMax().z || this.captureMin.z == cl.getMin().z));
&& ((this.captureMax.x == cl.getBoundsMin().getX()
|| this.captureMin.x == cl.getBoundsMax().getX())
|| (this.captureMax.z == cl.getBoundsMin().getZ()
|| this.captureMin.z == cl.getBoundsMax().getZ()))
&& ((this.captureMax.x == cl.getBoundsMax().getX()
|| this.captureMin.x == cl.getBoundsMin().getX())
|| (this.captureMax.z == cl.getBoundsMax().getZ()
|| this.captureMin.z == cl.getBoundsMin().getZ()));
break;
case Z:
this.isValid = this.isValid
&& ((this.captureMax.y == cl.getMin().y || this.captureMin.y == cl.getMax().y)
|| (this.captureMax.x == cl.getMin().x || this.captureMin.x == cl.getMax().x))
&& ((this.captureMax.y == cl.getMax().y || this.captureMin.y == cl.getMin().y)
|| (this.captureMax.x == cl.getMax().x || this.captureMin.x == cl.getMin().x));
&& ((this.captureMax.y == cl.getBoundsMin().getY()
|| this.captureMin.y == cl.getBoundsMax().getY())
|| (this.captureMax.x == cl.getBoundsMin().getX()
|| this.captureMin.x == cl.getBoundsMax().getX()))
&& ((this.captureMax.y == cl.getBoundsMax().getY()
|| this.captureMin.y == cl.getBoundsMin().getY())
|| (this.captureMax.x == cl.getBoundsMax().getX()
|| this.captureMin.x == cl.getBoundsMin().getX()));
break;
case UNFORMED:
@@ -20,13 +20,32 @@ package appeng.me.cluster;
import java.util.Iterator;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import appeng.api.networking.IGridHost;
public interface IAECluster {
/**
* The minimum x,y,z position still within the bounds of the cluster.
*/
BlockPos getBoundsMin();
/**
* The maximum x,y,z position still within the bounds of the cluster.
*/
BlockPos getBoundsMax();
void updateStatus(boolean updateGrid);
void destroy();
Iterator<IGridHost> getTiles();
/**
* @return True if the cluster has been destroyed, but not yet removed from a
* tile entity. Usually true during destruction.
*/
boolean isDestroyed();
Iterator<? extends IGridHost> getTiles();
}
@@ -18,11 +18,11 @@
package appeng.me.cluster;
public interface IAEMultiBlock {
public interface IAEMultiBlock<Cluster extends IAECluster> {
void disconnect(boolean b);
IAECluster getCluster();
Cluster getCluster();
boolean isValid();
}
+106 -42
View File
@@ -18,56 +18,108 @@
package appeng.me.cluster;
import java.lang.ref.WeakReference;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import appeng.api.util.AEPartLocation;
import appeng.api.util.WorldCoord;
import appeng.core.AELog;
import appeng.util.Platform;
public abstract class MBCalculator {
public abstract class MBCalculator<TTile extends IAEMultiBlock<TCluster>, TCluster extends IAECluster> {
private final IAEMultiBlock target;
/**
* To avoid recursive cluster rebuilds, we use a global field to prevent this
* from happening. This is set to the cluster that is currently causing a
* Multiblock modification.
*/
private static WeakReference<IAECluster> modificationInProgress = new WeakReference<>(null);
public MBCalculator(final IAEMultiBlock t) {
protected final TTile target;
public MBCalculator(final TTile t) {
this.target = t;
}
public void calculateMultiblock(final World world, final WorldCoord loc) {
if (Platform.isClient()) {
public static void setModificationInProgress(IAECluster cluster) {
IAECluster inProgress = modificationInProgress.get();
if (inProgress == cluster) {
return;
}
if (inProgress != null && cluster != null) {
throw new IllegalStateException("A modification is already in-progress for: " + inProgress);
}
modificationInProgress = new WeakReference<>(cluster);
}
public static boolean isModificationInProgress() {
return modificationInProgress.get() != null;
}
public void updateMultiblockAfterNeighborUpdate(final World world, final BlockPos loc, BlockPos changedPos) {
boolean recheck;
TCluster cluster = target.getCluster();
if (cluster != null) {
if (isWithinBounds(changedPos, cluster.getBoundsMin(), cluster.getBoundsMax())) {
// If the location is part of the current multiblock, always re-check
recheck = true;
} else {
// If the location is outside, only re-check if it would now be considered part
// of it
recheck = isValidTileAt(world, changedPos.getX(), changedPos.getY(), changedPos.getZ());
}
} else {
// Always recheck if the tile is not part of a cluster, because the adjacent
// block could have previously been a valid tile, but in a wrong placement,
// or the other way around.
recheck = true;
}
if (recheck) {
calculateMultiblock(world, loc);
}
}
public void calculateMultiblock(final World world, final BlockPos loc) {
if (Platform.isClient() || isModificationInProgress()) {
return;
}
IAECluster currentCluster = target.getCluster();
if (currentCluster != null && currentCluster.isDestroyed()) {
return; // If we're still part of a cluster that is in the process of being destroyed,
// don't recalc.
}
try {
final WorldCoord min = loc.copy();
final WorldCoord max = loc.copy();
final BlockPos.Mutable min = new BlockPos.Mutable(loc);
final BlockPos.Mutable max = new BlockPos.Mutable(loc);
// find size of MB structure...
while (this.isValidTileAt(world, min.x - 1, min.y, min.z)) {
min.x--;
while (this.isValidTileAt(world, min.getX() - 1, min.getY(), min.getZ())) {
min.setX(min.getX() - 1);
}
while (this.isValidTileAt(world, min.x, min.y - 1, min.z)) {
min.y--;
while (this.isValidTileAt(world, min.getX(), min.getY() - 1, min.getZ())) {
min.setY(min.getY() - 1);
}
while (this.isValidTileAt(world, min.x, min.y, min.z - 1)) {
min.z--;
while (this.isValidTileAt(world, min.getX(), min.getY(), min.getZ() - 1)) {
min.setZ(min.getZ() - 1);
}
while (this.isValidTileAt(world, max.x + 1, max.y, max.z)) {
max.x++;
while (this.isValidTileAt(world, max.getX() + 1, max.getY(), max.getZ())) {
max.setX(max.getX() + 1);
}
while (this.isValidTileAt(world, max.x, max.y + 1, max.z)) {
max.y++;
while (this.isValidTileAt(world, max.getX(), max.getY() + 1, max.getZ())) {
max.setY(max.getY() + 1);
}
while (this.isValidTileAt(world, max.x, max.y, max.z + 1)) {
max.z++;
while (this.isValidTileAt(world, max.getX(), max.getY(), max.getZ() + 1)) {
max.setZ(max.getZ() + 1);
}
if (this.checkMultiblockScale(min, max)) {
if (this.verifyUnownedRegion(world, min, max)) {
IAECluster c = this.createCluster(world, min, max);
try {
if (!this.verifyInternalStructure(world, min, max)) {
this.disconnect();
@@ -79,26 +131,39 @@ public abstract class MBCalculator {
}
boolean updateGrid = false;
final IAECluster cluster = this.target.getCluster();
if (cluster == null) {
this.updateTiles(c, world, min, max);
TCluster cluster = this.target.getCluster();
if (cluster == null || !cluster.getBoundsMin().equals(min) || !cluster.getBoundsMax().equals(max)) {
cluster = this.createCluster(world, min, max);
setModificationInProgress(cluster);
// NOTE: The following will break existing clusters within the bounds
this.updateTiles(cluster, world, min, max);
updateGrid = true;
} else {
c = cluster;
setModificationInProgress(cluster);
}
c.updateStatus(updateGrid);
cluster.updateStatus(updateGrid);
return;
}
}
} catch (final Throwable err) {
AELog.debug(err);
} finally {
setModificationInProgress(null);
}
this.disconnect();
}
private static boolean isWithinBounds(BlockPos pos, BlockPos boundsMin, BlockPos boundsMax) {
int x = pos.getX();
int y = pos.getY();
int z = pos.getZ();
return (x >= boundsMin.getX() && y >= boundsMin.getY() && z >= boundsMin.getZ() && x <= boundsMax.getX()
&& y <= boundsMax.getY() && z <= boundsMax.getZ());
}
private boolean isValidTileAt(final World w, final int x, final int y, final int z) {
return this.isValidTile(w.getTileEntity(new BlockPos(x, y, z)));
}
@@ -111,11 +176,12 @@ public abstract class MBCalculator {
*
* @return true if structure has correct dimensions or size
*/
public abstract boolean checkMultiblockScale(WorldCoord min, WorldCoord max);
public abstract boolean checkMultiblockScale(BlockPos min, BlockPos max);
private boolean verifyUnownedRegion(final World w, final WorldCoord min, final WorldCoord max) {
private boolean verifyUnownedRegion(final World w, final BlockPos min, final BlockPos max) {
for (final AEPartLocation side : AEPartLocation.SIDE_LOCATIONS) {
if (this.verifyUnownedRegionInner(w, min.x, min.y, min.z, max.x, max.y, max.z, side)) {
if (this.verifyUnownedRegionInner(w, min.getX(), min.getY(), min.getZ(), max.getX(), max.getY(), max.getZ(),
side)) {
return false;
}
}
@@ -132,14 +198,16 @@ public abstract class MBCalculator {
*
* @return created cluster
*/
public abstract IAECluster createCluster(World w, WorldCoord min, WorldCoord max);
public abstract TCluster createCluster(World w, BlockPos min, BlockPos max);
public abstract boolean verifyInternalStructure(World world, WorldCoord min, WorldCoord max);
public abstract boolean verifyInternalStructure(World world, BlockPos min, BlockPos max);
/**
* disassembles the multi-block.
*/
public abstract void disconnect();
public void disconnect() {
this.target.disconnect(true);
}
/**
* configure the multi-block tiles, most of the important stuff is in here.
@@ -149,7 +217,7 @@ public abstract class MBCalculator {
* @param min min world coord
* @param max max world coord
*/
public abstract void updateTiles(IAECluster c, World w, WorldCoord min, WorldCoord max);
public abstract void updateTiles(TCluster c, World w, BlockPos min, BlockPos max);
/**
* check if the tile entities are correct for the structure.
@@ -191,14 +259,10 @@ public abstract class MBCalculator {
return false;
}
for (int x = minX; x <= maxX; x++) {
for (int y = minY; y <= maxY; y++) {
for (int z = minZ; z <= maxZ; z++) {
final TileEntity te = w.getTileEntity(new BlockPos(x, y, z));
if (this.isValidTile(te)) {
return true;
}
}
for (BlockPos p : BlockPos.getAllInBoxMutable(minX, minY, minZ, maxX, maxY, maxZ)) {
final TileEntity te = w.getTileEntity(p);
if (this.isValidTile(te)) {
return true;
}
}
@@ -29,32 +29,27 @@ import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode;
import appeng.api.networking.events.MENetworkCraftingCpuChange;
import appeng.api.util.AEPartLocation;
import appeng.api.util.WorldCoord;
import appeng.me.cluster.IAECluster;
import appeng.me.cluster.IAEMultiBlock;
import appeng.me.cluster.MBCalculator;
import appeng.tile.crafting.CraftingTileEntity;
public class CraftingCPUCalculator extends MBCalculator {
public class CraftingCPUCalculator extends MBCalculator<CraftingTileEntity, CraftingCPUCluster> {
private final CraftingTileEntity tqb;
public CraftingCPUCalculator(final IAEMultiBlock t) {
public CraftingCPUCalculator(final CraftingTileEntity t) {
super(t);
this.tqb = (CraftingTileEntity) t;
}
@Override
public boolean checkMultiblockScale(final WorldCoord min, final WorldCoord max) {
if (max.x - min.x > 16) {
public boolean checkMultiblockScale(final BlockPos min, final BlockPos max) {
if (max.getX() - min.getX() > 16) {
return false;
}
if (max.y - min.y > 16) {
if (max.getY() - min.getY() > 16) {
return false;
}
if (max.z - min.z > 16) {
if (max.getZ() - min.getZ() > 16) {
return false;
}
@@ -62,27 +57,23 @@ public class CraftingCPUCalculator extends MBCalculator {
}
@Override
public IAECluster createCluster(final World w, final WorldCoord min, final WorldCoord max) {
public CraftingCPUCluster createCluster(final World w, final BlockPos min, final BlockPos max) {
return new CraftingCPUCluster(min, max);
}
@Override
public boolean verifyInternalStructure(final World w, final WorldCoord min, final WorldCoord max) {
public boolean verifyInternalStructure(final World w, final BlockPos min, final BlockPos max) {
boolean storage = false;
for (int x = min.x; x <= max.x; x++) {
for (int y = min.y; y <= max.y; y++) {
for (int z = min.z; z <= max.z; z++) {
final IAEMultiBlock te = (IAEMultiBlock) w.getTileEntity(new BlockPos(x, y, z));
for (BlockPos blockPos : BlockPos.getAllInBoxMutable(min, max)) {
final IAEMultiBlock<?> te = (IAEMultiBlock<?>) w.getTileEntity(blockPos);
if (!te.isValid()) {
return false;
}
if (te == null || !te.isValid()) {
return false;
}
if (!storage && te instanceof CraftingTileEntity) {
storage = ((CraftingTileEntity) te).getStorageBytes() > 0;
}
}
if (!storage && te instanceof CraftingTileEntity) {
storage = ((CraftingTileEntity) te).getStorageBytes() > 0;
}
}
@@ -90,27 +81,16 @@ public class CraftingCPUCalculator extends MBCalculator {
}
@Override
public void disconnect() {
this.tqb.disconnect(true);
}
@Override
public void updateTiles(final IAECluster cl, final World w, final WorldCoord min, final WorldCoord max) {
final CraftingCPUCluster c = (CraftingCPUCluster) cl;
for (int x = min.x; x <= max.x; x++) {
for (int y = min.y; y <= max.y; y++) {
for (int z = min.z; z <= max.z; z++) {
final CraftingTileEntity te = (CraftingTileEntity) w.getTileEntity(new BlockPos(x, y, z));
te.updateStatus(c);
c.addTile(te);
}
}
public void updateTiles(final CraftingCPUCluster c, final World w, final BlockPos min, final BlockPos max) {
for (BlockPos blockPos : BlockPos.getAllInBoxMutable(min, max)) {
final CraftingTileEntity te = (CraftingTileEntity) w.getTileEntity(blockPos);
te.updateStatus(c);
c.addTile(te);
}
c.done();
final Iterator<IGridHost> i = c.getTiles();
final Iterator<CraftingTileEntity> i = c.getTiles();
while (i.hasNext()) {
final IGridHost gh = i.next();
final IGridNode n = gh.getGridNode(AEPartLocation.INTERNAL);
@@ -18,12 +18,7 @@
package appeng.me.cluster.implementations;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import com.google.common.collect.ImmutableList;
@@ -32,6 +27,7 @@ import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
@@ -44,14 +40,7 @@ import appeng.api.crafting.ICraftingHelper;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.CraftingItemList;
import appeng.api.networking.crafting.ICraftingCPU;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.crafting.ICraftingJob;
import appeng.api.networking.crafting.ICraftingLink;
import appeng.api.networking.crafting.ICraftingMedium;
import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.networking.crafting.ICraftingRequester;
import appeng.api.networking.crafting.*;
import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.events.MENetworkCraftingCpuChange;
import appeng.api.networking.security.IActionSource;
@@ -61,17 +50,13 @@ import appeng.api.storage.IMEMonitorHandlerReceiver;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.api.util.WorldCoord;
import appeng.container.ContainerNull;
import appeng.core.AELog;
import appeng.core.Api;
import appeng.crafting.CraftBranchFailure;
import appeng.crafting.CraftingJob;
import appeng.crafting.CraftingLink;
import appeng.crafting.CraftingWatcher;
import appeng.crafting.MECraftingInventory;
import appeng.crafting.*;
import appeng.me.cache.CraftingGridCache;
import appeng.me.cluster.IAECluster;
import appeng.me.cluster.MBCalculator;
import appeng.me.helpers.MachineSource;
import appeng.tile.crafting.CraftingMonitorTileEntity;
import appeng.tile.crafting.CraftingTileEntity;
@@ -82,8 +67,8 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU {
private static final String LOG_MARK_AS_COMPLETE = "Completed job for %s.";
private final WorldCoord min;
private final WorldCoord max;
private final BlockPos boundsMin;
private final BlockPos boundsMax;
private final int[] usedOps = new int[3];
private final Map<ICraftingPatternDetails, TaskProgress> tasks = new HashMap<>();
// INSTANCE sate
@@ -114,11 +99,12 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU {
private long startItemCount;
private long remainingItemCount;
public CraftingCPUCluster(final WorldCoord min, final WorldCoord max) {
this.min = min;
this.max = max;
public CraftingCPUCluster(final BlockPos boundsMin, final BlockPos boundsMax) {
this.boundsMin = boundsMin.toImmutable();
this.boundsMax = boundsMax.toImmutable();
}
@Override
public boolean isDestroyed() {
return this.isDestroyed;
}
@@ -127,6 +113,16 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU {
return this.myLastLink;
}
@Override
public BlockPos getBoundsMin() {
return boundsMin;
}
@Override
public BlockPos getBoundsMax() {
return boundsMax;
}
/**
* add a new Listener to the monitor, be sure to properly remove yourself when
* your done.
@@ -162,25 +158,35 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU {
}
this.isDestroyed = true;
boolean posted = false;
boolean ownsModification = !MBCalculator.isModificationInProgress();
if (ownsModification) {
MBCalculator.setModificationInProgress(this);
}
try {
boolean posted = false;
for (final CraftingTileEntity r : this.tiles) {
final IGridNode n = r.getActionableNode();
if (n != null && !posted) {
final IGrid g = n.getGrid();
if (g != null) {
g.postEvent(new MENetworkCraftingCpuChange(n));
posted = true;
for (final CraftingTileEntity r : this.tiles) {
final IGridNode n = r.getActionableNode();
if (n != null && !posted) {
final IGrid g = n.getGrid();
if (g != null) {
g.postEvent(new MENetworkCraftingCpuChange(n));
posted = true;
}
}
}
r.updateStatus(null);
r.updateStatus(null);
}
} finally {
if (ownsModification) {
MBCalculator.setModificationInProgress(null);
}
}
}
@Override
public Iterator<IGridHost> getTiles() {
return (Iterator) this.tiles.iterator();
public Iterator<CraftingTileEntity> getTiles() {
return this.tiles.iterator();
}
void addTile(final CraftingTileEntity te) {
@@ -423,7 +429,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU {
return null;
}
private boolean canCraft(final ICraftingPatternDetails details, final IAEItemStack[] condensedInputs) {
private boolean canCraft(final ICraftingPatternDetails details, final Collection<IAEItemStack> condensedInputs) {
for (IAEItemStack g : condensedInputs) {
if (details.isCraftable()) {
@@ -551,7 +557,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU {
final ICraftingPatternDetails details = e.getKey();
if (this.canCraft(details, details.getCondensedInputs())) {
if (this.canCraft(details, details.getInputs())) {
CraftingInventory ic = null;
for (final ICraftingMedium m : cc.getMediums(e.getKey())) {
@@ -561,7 +567,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU {
if (!m.isBusy()) {
if (ic == null) {
final IAEItemStack[] input = details.getInputs();
final IAEItemStack[] input = details.getSparseInputs();
double sum = 0;
for (final IAEItemStack anInput : input) {
@@ -657,7 +663,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU {
this.somethingChanged = true;
this.remainingOperations--;
for (final IAEItemStack out : details.getCondensedOutputs()) {
for (final IAEItemStack out : details.getOutputs()) {
this.postChange(out, this.machineSrc);
this.waitingFor.add(out.copy());
this.postCraftingStatusChange(out.copy());
@@ -890,7 +896,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU {
break;
case PENDING:
for (final Entry<ICraftingPatternDetails, TaskProgress> t : this.tasks.entrySet()) {
for (IAEItemStack ais : t.getKey().getCondensedOutputs()) {
for (IAEItemStack ais : t.getKey().getOutputs()) {
ais = ais.copy();
ais.setStackSize(ais.getStackSize() * t.getValue().value);
list.add(ais);
@@ -909,7 +915,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU {
}
for (final Entry<ICraftingPatternDetails, TaskProgress> t : this.tasks.entrySet()) {
for (IAEItemStack ais : t.getKey().getCondensedOutputs()) {
for (IAEItemStack ais : t.getKey().getOutputs()) {
ais = ais.copy();
ais.setStackSize(ais.getStackSize() * t.getValue().value);
list.add(ais);
@@ -954,7 +960,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU {
is.setStackSize(0);
for (final Entry<ICraftingPatternDetails, TaskProgress> t : this.tasks.entrySet()) {
for (final IAEItemStack ais : t.getKey().getCondensedOutputs()) {
for (final IAEItemStack ais : t.getKey().getOutputs()) {
if (ais.equals(is)) {
is.setStackSize(is.getStackSize() + ais.getStackSize() * t.getValue().value);
}
@@ -25,31 +25,25 @@ import net.minecraft.world.World;
import appeng.api.definitions.IBlockDefinition;
import appeng.api.definitions.IBlocks;
import appeng.api.util.WorldCoord;
import appeng.core.Api;
import appeng.me.cluster.IAECluster;
import appeng.me.cluster.IAEMultiBlock;
import appeng.me.cluster.MBCalculator;
import appeng.tile.qnb.QuantumBridgeTileEntity;
public class QuantumCalculator extends MBCalculator {
public class QuantumCalculator extends MBCalculator<QuantumBridgeTileEntity, QuantumCluster> {
private final QuantumBridgeTileEntity tqb;
public QuantumCalculator(final IAEMultiBlock t) {
public QuantumCalculator(final QuantumBridgeTileEntity t) {
super(t);
this.tqb = (QuantumBridgeTileEntity) t;
}
@Override
public boolean checkMultiblockScale(final WorldCoord min, final WorldCoord max) {
public boolean checkMultiblockScale(final BlockPos min, final BlockPos max) {
if ((max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1) * (max.getZ() - min.getZ() + 1) == 9) {
final int ones = ((max.getX() - min.getX()) == 0 ? 1 : 0) + ((max.getY() - min.getY()) == 0 ? 1 : 0)
+ ((max.getZ() - min.getZ()) == 0 ? 1 : 0);
if ((max.x - min.x + 1) * (max.y - min.y + 1) * (max.z - min.z + 1) == 9) {
final int ones = ((max.x - min.x) == 0 ? 1 : 0) + ((max.y - min.y) == 0 ? 1 : 0)
+ ((max.z - min.z) == 0 ? 1 : 0);
final int threes = ((max.x - min.x) == 2 ? 1 : 0) + ((max.y - min.y) == 2 ? 1 : 0)
+ ((max.z - min.z) == 2 ? 1 : 0);
final int threes = ((max.getX() - min.getX()) == 2 ? 1 : 0) + ((max.getY() - min.getY()) == 2 ? 1 : 0)
+ ((max.getZ() - min.getZ()) == 2 ? 1 : 0);
return ones == 1 && threes == 2;
}
@@ -57,36 +51,31 @@ public class QuantumCalculator extends MBCalculator {
}
@Override
public IAECluster createCluster(final World w, final WorldCoord min, final WorldCoord max) {
public QuantumCluster createCluster(final World w, final BlockPos min, final BlockPos max) {
return new QuantumCluster(min, max);
}
@Override
public boolean verifyInternalStructure(final World w, final WorldCoord min, final WorldCoord max) {
public boolean verifyInternalStructure(final World w, final BlockPos min, final BlockPos max) {
byte num = 0;
for (int x = min.x; x <= max.x; x++) {
for (int y = min.y; y <= max.y; y++) {
for (int z = min.z; z <= max.z; z++) {
final BlockPos p = new BlockPos(x, y, z);
final IAEMultiBlock te = (IAEMultiBlock) w.getTileEntity(p);
for (BlockPos p : BlockPos.getAllInBoxMutable(min, max)) {
final IAEMultiBlock<?> te = (IAEMultiBlock<?>) w.getTileEntity(p);
if (!te.isValid()) {
return false;
}
if (te == null || !te.isValid()) {
return false;
}
num++;
final IBlocks blocks = Api.instance().definitions().blocks();
if (num == 5) {
if (!this.isBlockAtLocation(w, p, blocks.quantumLink())) {
return false;
}
} else {
if (!this.isBlockAtLocation(w, p, blocks.quantumRing())) {
return false;
}
}
num++;
final IBlocks blocks = Api.instance().definitions().blocks();
if (num == 5) {
if (!this.isBlockAtLocation(w, p, blocks.quantumLink())) {
return false;
}
} else {
if (!this.isBlockAtLocation(w, p, blocks.quantumRing())) {
return false;
}
}
}
@@ -94,39 +83,29 @@ public class QuantumCalculator extends MBCalculator {
}
@Override
public void disconnect() {
this.tqb.disconnect(true);
}
@Override
public void updateTiles(final IAECluster cl, final World w, final WorldCoord min, final WorldCoord max) {
public void updateTiles(final QuantumCluster c, final World w, final BlockPos min, final BlockPos max) {
byte num = 0;
byte ringNum = 0;
final QuantumCluster c = (QuantumCluster) cl;
for (int x = min.x; x <= max.x; x++) {
for (int y = min.y; y <= max.y; y++) {
for (int z = min.z; z <= max.z; z++) {
final QuantumBridgeTileEntity te = (QuantumBridgeTileEntity) w.getTileEntity(new BlockPos(x, y, z));
for (BlockPos p : BlockPos.getAllInBoxMutable(min, max)) {
final QuantumBridgeTileEntity te = (QuantumBridgeTileEntity) w.getTileEntity(p);
num++;
final byte flags;
if (num == 5) {
flags = num;
c.setCenter(te);
} else {
if (num == 1 || num == 3 || num == 7 || num == 9) {
flags = (byte) (this.tqb.getCorner() | num);
} else {
flags = num;
}
c.getRing()[ringNum] = te;
ringNum++;
}
te.updateStatus(c, flags, true);
num++;
final byte flags;
if (num == 5) {
flags = num;
c.setCenter(te);
} else {
if (num == 1 || num == 3 || num == 7 || num == 9) {
flags = (byte) (this.target.getCorner() | num);
} else {
flags = num;
}
c.getRing()[ringNum] = te;
ringNum++;
}
te.updateStatus(c, flags, true);
}
}
@@ -21,6 +21,7 @@ package appeng.me.cluster.implementations;
import java.util.Iterator;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.World;
import net.minecraft.world.dimension.DimensionType;
@@ -32,21 +33,20 @@ import appeng.api.events.LocatableEventAnnounce;
import appeng.api.events.LocatableEventAnnounce.LocatableEvent;
import appeng.api.exceptions.FailedConnectionException;
import appeng.api.features.ILocatable;
import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode;
import appeng.api.util.AEPartLocation;
import appeng.api.util.WorldCoord;
import appeng.core.AELog;
import appeng.core.Api;
import appeng.me.cache.helpers.ConnectionWrapper;
import appeng.me.cluster.IAECluster;
import appeng.me.cluster.MBCalculator;
import appeng.tile.qnb.QuantumBridgeTileEntity;
import appeng.util.iterators.ChainedIterator;
public class QuantumCluster implements ILocatable, IAECluster {
private final WorldCoord min;
private final WorldCoord max;
private final BlockPos boundsMin;
private final BlockPos boundsMax;
private boolean isDestroyed = false;
private boolean updateStatus = true;
private QuantumBridgeTileEntity[] Ring;
@@ -56,9 +56,9 @@ public class QuantumCluster implements ILocatable, IAECluster {
private long otherSide;
private QuantumBridgeTileEntity center;
public QuantumCluster(final WorldCoord min, final WorldCoord max) {
this.min = min;
this.max = max;
public QuantumCluster(final BlockPos min, final BlockPos max) {
this.boundsMin = min.toImmutable();
this.boundsMax = max.toImmutable();
this.setRing(new QuantumBridgeTileEntity[8]);
}
@@ -189,6 +189,21 @@ public class QuantumCluster implements ILocatable, IAECluster {
return this.thisSide != 0;
}
@Override
public BlockPos getBoundsMin() {
return boundsMin;
}
@Override
public BlockPos getBoundsMax() {
return boundsMax;
}
@Override
public boolean isDestroyed() {
return isDestroyed;
}
@Override
public void destroy() {
if (this.isDestroyed) {
@@ -196,28 +211,33 @@ public class QuantumCluster implements ILocatable, IAECluster {
}
this.isDestroyed = true;
if (this.registered) {
MinecraftForge.EVENT_BUS.unregister(this);
this.registered = false;
MBCalculator.setModificationInProgress(this);
try {
if (this.registered) {
MinecraftForge.EVENT_BUS.unregister(this);
this.registered = false;
}
if (this.thisSide != 0) {
this.updateStatus(true);
MinecraftForge.EVENT_BUS.post(new LocatableEventAnnounce(this, LocatableEvent.UNREGISTER));
}
this.center.updateStatus(null, (byte) -1, this.isUpdateStatus());
for (final QuantumBridgeTileEntity r : this.getRing()) {
r.updateStatus(null, (byte) -1, this.isUpdateStatus());
}
this.center = null;
this.setRing(new QuantumBridgeTileEntity[8]);
} finally {
MBCalculator.setModificationInProgress(null);
}
if (this.thisSide != 0) {
this.updateStatus(true);
MinecraftForge.EVENT_BUS.post(new LocatableEventAnnounce(this, LocatableEvent.UNREGISTER));
}
this.center.updateStatus(null, (byte) -1, this.isUpdateStatus());
for (final QuantumBridgeTileEntity r : this.getRing()) {
r.updateStatus(null, (byte) -1, this.isUpdateStatus());
}
this.center = null;
this.setRing(new QuantumBridgeTileEntity[8]);
}
@Override
public Iterator<IGridHost> getTiles() {
public Iterator<QuantumBridgeTileEntity> getTiles() {
return new ChainedIterator<>(this.getRing()[0], this.getRing()[1], this.getRing()[2], this.getRing()[3],
this.getRing()[4], this.getRing()[5], this.getRing()[6], this.getRing()[7], this.center);
}
@@ -22,47 +22,36 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import appeng.api.util.DimensionalCoord;
import appeng.api.util.WorldCoord;
import appeng.me.cluster.IAECluster;
import appeng.me.cluster.IAEMultiBlock;
import appeng.me.cluster.MBCalculator;
import appeng.tile.spatial.SpatialPylonTileEntity;
public class SpatialPylonCalculator extends MBCalculator {
public class SpatialPylonCalculator extends MBCalculator<SpatialPylonTileEntity, SpatialPylonCluster> {
private final SpatialPylonTileEntity tqb;
public SpatialPylonCalculator(final IAEMultiBlock t) {
public SpatialPylonCalculator(final SpatialPylonTileEntity t) {
super(t);
this.tqb = (SpatialPylonTileEntity) t;
}
@Override
public boolean checkMultiblockScale(final WorldCoord min, final WorldCoord max) {
return (min.x == max.x && min.y == max.y && min.z != max.z)
|| (min.x == max.x && min.y != max.y && min.z == max.z)
|| (min.x != max.x && min.y == max.y && min.z == max.z);
public boolean checkMultiblockScale(final BlockPos min, final BlockPos max) {
return (min.getX() == max.getX() && min.getY() == max.getY() && min.getZ() != max.getZ())
|| (min.getX() == max.getX() && min.getY() != max.getY() && min.getZ() == max.getZ())
|| (min.getX() != max.getX() && min.getY() == max.getY() && min.getZ() == max.getZ());
}
@Override
public IAECluster createCluster(final World w, final WorldCoord min, final WorldCoord max) {
return new SpatialPylonCluster(new DimensionalCoord(w, min.x, min.y, min.z),
new DimensionalCoord(w, max.x, max.y, max.z));
public SpatialPylonCluster createCluster(final World w, final BlockPos min, final BlockPos max) {
return new SpatialPylonCluster(w, min, max);
}
@Override
public boolean verifyInternalStructure(final World w, final WorldCoord min, final WorldCoord max) {
public boolean verifyInternalStructure(final World w, final BlockPos min, final BlockPos max) {
for (int x = min.x; x <= max.x; x++) {
for (int y = min.y; y <= max.y; y++) {
for (int z = min.z; z <= max.z; z++) {
final IAEMultiBlock te = (IAEMultiBlock) w.getTileEntity(new BlockPos(x, y, z));
for (BlockPos p : BlockPos.getAllInBoxMutable(min, max)) {
final IAEMultiBlock<?> te = (IAEMultiBlock<?>) w.getTileEntity(p);
if (!te.isValid()) {
return false;
}
}
if (te == null || !te.isValid()) {
return false;
}
}
@@ -70,22 +59,11 @@ public class SpatialPylonCalculator extends MBCalculator {
}
@Override
public void disconnect() {
this.tqb.disconnect(true);
}
@Override
public void updateTiles(final IAECluster cl, final World w, final WorldCoord min, final WorldCoord max) {
final SpatialPylonCluster c = (SpatialPylonCluster) cl;
for (int x = min.x; x <= max.x; x++) {
for (int y = min.y; y <= max.y; y++) {
for (int z = min.z; z <= max.z; z++) {
final SpatialPylonTileEntity te = (SpatialPylonTileEntity) w.getTileEntity(new BlockPos(x, y, z));
te.updateStatus(c);
c.getLine().add((te));
}
}
public void updateTiles(final SpatialPylonCluster c, final World w, final BlockPos min, final BlockPos max) {
for (BlockPos p : BlockPos.getAllInBoxMutable(min, max)) {
final SpatialPylonTileEntity te = (SpatialPylonTileEntity) w.getTileEntity(p);
te.updateStatus(c);
c.getLine().add(te);
}
}
@@ -22,30 +22,34 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import appeng.api.networking.IGridHost;
import appeng.api.util.DimensionalCoord;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import appeng.me.cluster.IAECluster;
import appeng.me.cluster.MBCalculator;
import appeng.tile.spatial.SpatialPylonTileEntity;
public class SpatialPylonCluster implements IAECluster {
private final DimensionalCoord min;
private final DimensionalCoord max;
private final World world;
private final BlockPos boundsMin;
private final BlockPos boundsMax;
private final List<SpatialPylonTileEntity> line = new ArrayList<>();
private boolean isDestroyed = false;
private Axis currentAxis = Axis.UNFORMED;
private boolean isValid;
public SpatialPylonCluster(final DimensionalCoord min, final DimensionalCoord max) {
this.min = min.copy();
this.max = max.copy();
public SpatialPylonCluster(final World world, final BlockPos boundsMin, final BlockPos boundsMax) {
this.world = world;
this.boundsMin = boundsMin.toImmutable();
this.boundsMax = boundsMax.toImmutable();
if (this.getMin().x != this.getMax().x) {
if (this.getBoundsMin().getX() != this.getBoundsMax().getX()) {
this.setCurrentAxis(Axis.X);
} else if (this.getMin().y != this.getMax().y) {
} else if (this.getBoundsMin().getY() != this.getBoundsMax().getY()) {
this.setCurrentAxis(Axis.Y);
} else if (this.getMin().z != this.getMax().z) {
} else if (this.getBoundsMin().getZ() != this.getBoundsMax().getZ()) {
this.setCurrentAxis(Axis.Z);
} else {
this.setCurrentAxis(Axis.UNFORMED);
@@ -59,6 +63,11 @@ public class SpatialPylonCluster implements IAECluster {
}
}
@Override
public boolean isDestroyed() {
return isDestroyed;
}
@Override
public void destroy() {
@@ -67,14 +76,19 @@ public class SpatialPylonCluster implements IAECluster {
}
this.isDestroyed = true;
for (final SpatialPylonTileEntity r : this.getLine()) {
r.updateStatus(null);
MBCalculator.setModificationInProgress(this);
try {
for (final SpatialPylonTileEntity r : this.getLine()) {
r.updateStatus(null);
}
} finally {
MBCalculator.setModificationInProgress(null);
}
}
@Override
public Iterator<IGridHost> getTiles() {
return (Iterator) this.getLine().iterator();
public Iterator<SpatialPylonTileEntity> getTiles() {
return this.getLine().iterator();
}
public int tileCount() {
@@ -97,12 +111,18 @@ public class SpatialPylonCluster implements IAECluster {
this.isValid = isValid;
}
public DimensionalCoord getMax() {
return this.max;
public World getWorld() {
return world;
}
public DimensionalCoord getMin() {
return this.min;
@Override
public BlockPos getBoundsMax() {
return this.boundsMax;
}
@Override
public BlockPos getBoundsMin() {
return this.boundsMin;
}
List<SpatialPylonTileEntity> getLine() {
@@ -96,7 +96,7 @@ public class AENetworkProxy implements IGridBlock {
public void validate() {
if (this.gp instanceof AEBaseTileEntity) {
TickHandler.INSTANCE.addInit((AEBaseTileEntity) this.gp);
TickHandler.instance().addInit((AEBaseTileEntity) this.gp);
}
}
@@ -41,11 +41,10 @@ public class AENetworkProxyMultiblock extends AENetworkProxy implements IGridMul
if (this.getCluster() == null) {
return new ChainedIterator<>();
}
return new ProxyNodeIterator(this.getCluster().getTiles());
}
private IAECluster getCluster() {
return ((IAEMultiBlock) this.getMachine()).getCluster();
return ((IAEMultiBlock<?>) this.getMachine()).getCluster();
}
}

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