Compare commits

...

52 Commits

Author SHA1 Message Date
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
628 changed files with 3379 additions and 2990 deletions
+3 -1
View File
@@ -21,6 +21,8 @@ jobs:
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
- name: Clean gradle
run: ./gradlew clean --no-daemon
- name: Validate no assets
run: test ! -d ./src/generated
- name: Generate assets
@@ -28,6 +30,6 @@ jobs:
with:
run: ./gradlew runData --no-daemon
- 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
+3 -1
View File
@@ -21,6 +21,8 @@ jobs:
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
- name: Clean gradle
run: ./gradlew clean --no-daemon
- name: Validate no assets
run: test ! -d ./src/generated
- name: Generate assets
@@ -28,6 +30,6 @@ jobs:
with:
run: ./gradlew runData --no-daemon
- 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
+3 -1
View File
@@ -21,6 +21,8 @@ jobs:
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
- name: Clean gradle
run: ./gradlew clean --no-daemon
- name: Validate no assets
run: test ! -d ./src/generated
- name: Generate assets
@@ -28,7 +30,7 @@ jobs:
with:
run: ./gradlew runData --no-daemon
- 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 }}
+1 -1
View File
@@ -35,7 +35,7 @@ jobs:
with:
run: ./gradlew runData --no-daemon
- 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 }}
+1 -1
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
+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
@@ -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;
}
}
@@ -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<>();
@@ -176,7 +181,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends ContainerS
}
final String msg = tooltip.getMessage();
if (msg != null) {
if (msg != null && !msg.isEmpty()) {
this.drawTooltip(x + 11, y + 4, msg);
}
}
@@ -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());
@@ -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();
}
@@ -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;
}
}
@@ -314,7 +314,7 @@ public class SettingToggleButton<T extends Enum<T>> extends IconButton {
return name + '\n' + sb;
}
return null;
return "";
}
public String getFillVar() {
@@ -99,7 +99,7 @@ public class ToggleButton extends Button implements ITooltip {
return name + '\n' + sb;
}
return null;
return "";
}
@Override
@@ -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()) {
@@ -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,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() {
+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();
}
}
@@ -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();
@@ -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,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";
}
}
@@ -93,7 +93,7 @@ public class FluidTankWidget extends Widget implements ITooltip {
return desc + "\n" + amountToText;
}
return null;
return "";
}
@Override
@@ -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);
}
}
}
@@ -109,7 +109,7 @@ 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 < products.size(); x++) {
final IAEItemStack ais = products.get(x);
final ItemStack gs = ais.createItemStack();
+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 {
@@ -226,7 +226,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) {
@@ -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) {
@@ -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();
}
}
@@ -408,7 +408,7 @@ public class AnnihilationPlanePart extends BasicStatePart implements IGridTickab
performBreakBlock(w, pos, blockState, energy, requiredPower, items);
} else {
this.breaking = true;
TickHandler.INSTANCE.addCallable(this.getTile().getWorld(), this);
TickHandler.instance().addCallable(this.getTile().getWorld(), this);
}
return TickRateModulation.URGENT;
}
@@ -158,7 +158,7 @@ public class FluidP2PTunnelPart extends P2PTunnelPart<FluidP2PTunnelPart> implem
return 0;
}
if (action == FluidAction.EXECUTE) {
if (action != FluidAction.EXECUTE) {
if (stack.pop() != this) {
throw new IllegalStateException("Invalid Recursion detected.");
}
@@ -138,14 +138,14 @@ public class MEP2PTunnelPart extends P2PTunnelPart<MEP2PTunnelPart> implements I
if (!this.getProxy().getPath().isNetworkBooting()) {
if (!this.getProxy().getEnergy().isNetworkPowered()) {
this.connection.markDestroy();
TickHandler.INSTANCE.addCallable(this.getTile().getWorld(), this.connection);
TickHandler.instance().addCallable(this.getTile().getWorld(), this.connection);
} else {
if (this.getProxy().isActive()) {
this.connection.markCreate();
TickHandler.INSTANCE.addCallable(this.getTile().getWorld(), this.connection);
TickHandler.instance().addCallable(this.getTile().getWorld(), this.connection);
} else {
this.connection.markDestroy();
TickHandler.INSTANCE.addCallable(this.getTile().getWorld(), this.connection);
TickHandler.instance().addCallable(this.getTile().getWorld(), this.connection);
}
}
@@ -21,6 +21,7 @@ import net.minecraftforge.registries.ForgeRegistryEntry;
import appeng.core.AEConfig;
import appeng.core.AppEng;
import appeng.core.sync.BasePacket;
public class GrinderRecipeSerializer extends ForgeRegistryEntry<IRecipeSerializer<?>>
implements IRecipeSerializer<GrinderRecipe> {
@@ -70,7 +71,7 @@ public class GrinderRecipeSerializer extends ForgeRegistryEntry<IRecipeSerialize
@Override
public GrinderRecipe read(ResourceLocation recipeId, PacketBuffer buffer) {
String group = buffer.readString();
String group = buffer.readString(BasePacket.MAX_STRING_LENGTH);
Ingredient ingredient = Ingredient.read(buffer);
int ingredientCount = buffer.readVarInt();
ItemStack result = buffer.readItemStack();
@@ -15,6 +15,7 @@ import net.minecraftforge.registries.ForgeRegistryEntry;
import appeng.api.features.InscriberProcessType;
import appeng.core.AppEng;
import appeng.core.sync.BasePacket;
public class InscriberRecipeSerializer extends ForgeRegistryEntry<IRecipeSerializer<?>>
implements IRecipeSerializer<InscriberRecipe> {
@@ -67,7 +68,7 @@ public class InscriberRecipeSerializer extends ForgeRegistryEntry<IRecipeSeriali
@Nullable
@Override
public InscriberRecipe read(ResourceLocation recipeId, PacketBuffer buffer) {
String group = buffer.readString();
String group = buffer.readString(BasePacket.MAX_STRING_LENGTH);
Ingredient middle = Ingredient.read(buffer);
ItemStack result = buffer.readItemStack();
Ingredient top = Ingredient.read(buffer);
@@ -434,7 +434,7 @@ public class AEBaseTileEntity extends TileEntity implements IOrientable, ICommon
if (this.world != null) {
this.world.markChunkDirty(this.pos, this);
if (!this.markDirtyQueued) {
TickHandler.INSTANCE.addCallable(null, this::markDirtyAtEndOfTick);
TickHandler.instance().addCallable(null, this::markDirtyAtEndOfTick);
this.markDirtyQueued = true;
}
}
@@ -29,30 +29,24 @@ import javax.annotation.Nonnull;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.common.util.Constants;
import appeng.api.config.Actionable;
import appeng.api.implementations.IPowerChannelState;
import appeng.api.networking.GridFlags;
import appeng.api.networking.IGridHost;
import appeng.api.networking.events.MENetworkChannelsChanged;
import appeng.api.networking.events.MENetworkEventSubscribe;
import appeng.api.networking.events.MENetworkPowerStatusChange;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.util.AEPartLocation;
import appeng.api.util.WorldCoord;
import appeng.block.crafting.AbstractCraftingUnitBlock;
import appeng.block.crafting.AbstractCraftingUnitBlock.CraftingUnitType;
import appeng.core.Api;
import appeng.me.cluster.IAECluster;
import appeng.me.cluster.IAEMultiBlock;
import appeng.me.cluster.implementations.CraftingCPUCalculator;
import appeng.me.cluster.implementations.CraftingCPUCluster;
@@ -61,7 +55,8 @@ import appeng.me.helpers.AENetworkProxyMultiblock;
import appeng.tile.grid.AENetworkTileEntity;
import appeng.util.Platform;
public class CraftingTileEntity extends AENetworkTileEntity implements IAEMultiBlock, IPowerChannelState {
public class CraftingTileEntity extends AENetworkTileEntity
implements IAEMultiBlock<CraftingCPUCluster>, IPowerChannelState {
private final CraftingCPUCalculator calc = new CraftingCPUCalculator(this);
private CompoundNBT previousState = null;
@@ -95,7 +90,7 @@ public class CraftingTileEntity extends AENetworkTileEntity implements IAEMultiB
@Override
public boolean canBeRotated() {
return true;// return BlockCraftingUnit.checkType( world.getBlockMetadata( xCoord, yCoord,
// zCoord ),
// zCoord ),
// BlockCraftingUnit.BASE_MONITOR );
}
@@ -112,7 +107,7 @@ public class CraftingTileEntity extends AENetworkTileEntity implements IAEMultiB
return false;
}
final AbstractCraftingUnitBlock unit = (AbstractCraftingUnitBlock) this.world.getBlockState(this.pos)
final AbstractCraftingUnitBlock<?> unit = (AbstractCraftingUnitBlock<?>) this.world.getBlockState(this.pos)
.getBlock();
return unit.type == CraftingUnitType.ACCELERATOR;
}
@@ -121,11 +116,11 @@ public class CraftingTileEntity extends AENetworkTileEntity implements IAEMultiB
public void onReady() {
super.onReady();
this.getProxy().setVisualRepresentation(this.getItemFromTile(this));
this.updateMultiBlock();
this.calc.calculateMultiblock(world, pos);
}
public void updateMultiBlock() {
this.calc.calculateMultiblock(this.world, this.getLocation());
public void updateMultiBlock(BlockPos changedPos) {
this.calc.updateMultiblockAfterNeighborUpdate(this.world, pos, changedPos);
}
public void updateStatus(final CraftingCPUCluster c) {
@@ -160,7 +155,7 @@ public class CraftingTileEntity extends AENetworkTileEntity implements IAEMultiB
// Not using flag 2 here (only send to clients, prevent block update) will cause
// infinite loops
// In case there is an inconsistency in the crafting clusters.
this.world.setBlockState(this.pos, newState, Constants.BlockFlags.BLOCK_UPDATE);
this.world.setBlockState(this.pos, newState, 2);
}
}
@@ -214,7 +209,7 @@ public class CraftingTileEntity extends AENetworkTileEntity implements IAEMultiB
}
@Override
public IAECluster getCluster() {
public CraftingCPUCluster getCluster() {
return this.cluster;
}
@@ -246,25 +241,27 @@ public class CraftingTileEntity extends AENetworkTileEntity implements IAEMultiB
}
public void breakCluster() {
// Since breaking the cluster will most likely also update the TE's state,
// it's essential that we're not working with outdated block-state information,
// since this particular TE's block might already have been removed (state=air)
updateContainingBlockInfo();
if (this.cluster != null) {
this.cluster.cancel();
final IMEInventory<IAEItemStack> inv = this.cluster.getInventory();
final LinkedList<WorldCoord> places = new LinkedList<>();
final LinkedList<BlockPos> places = new LinkedList<>();
final Iterator<IGridHost> i = this.cluster.getTiles();
final Iterator<CraftingTileEntity> i = this.cluster.getTiles();
while (i.hasNext()) {
final IGridHost h = i.next();
final CraftingTileEntity h = i.next();
if (h == this) {
places.add(new WorldCoord(this));
places.add(pos);
} else {
final TileEntity te = (TileEntity) h;
for (final AEPartLocation d : AEPartLocation.SIDE_LOCATIONS) {
final WorldCoord wc = new WorldCoord(te);
wc.add(d, 1);
if (this.world.isAirBlock(wc.getPos())) {
places.add(wc);
for (Direction d : Direction.values()) {
BlockPos p = h.pos.offset(d);
if (this.world.isAirBlock(p)) {
places.add(p);
}
}
}
@@ -288,10 +285,10 @@ public class CraftingTileEntity extends AENetworkTileEntity implements IAEMultiB
break;
}
final WorldCoord wc = places.poll();
places.add(wc);
final BlockPos pos = places.poll();
places.add(pos);
Platform.spawnDrops(this.world, wc.getPos(), Collections.singletonList(g.createItemStack()));
Platform.spawnDrops(this.world, pos, Collections.singletonList(g.createItemStack()));
}
}
@@ -124,7 +124,7 @@ public class CableBusTileEntity extends AEBaseTileEntity implements AEMultiTile
@Override
public void validate() {
super.validate();
TickHandler.INSTANCE.addInit(this);
TickHandler.instance().addInit(this);
}
@Override
@@ -69,4 +69,10 @@ public class CreativeEnergyCellTileEntity extends AENetworkTileEntity implements
public double extractAEPower(final double amt, final Actionable mode, final PowerMultiplier pm) {
return amt;
}
@Override
public int getPriority() {
// MAX_VALUE to move creative cells to the front.
return Integer.MAX_VALUE;
}
}
@@ -22,9 +22,16 @@ import net.minecraft.tileentity.TileEntityType;
public class DenseEnergyCellTileEntity extends EnergyCellTileEntity {
private final static double MAX_STORED = 200000 * 8;
public DenseEnergyCellTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
this.setInternalMaxPower(200000 * 8);
this.setInternalMaxPower(MAX_STORED);
}
@Override
public int getPriority() {
return 1600;
}
}
@@ -36,8 +36,10 @@ import appeng.util.SettingsFrom;
public class EnergyCellTileEntity extends AENetworkTileEntity implements IAEPowerStorage {
private static final double MAX_STORED = 200000.0;
private double internalCurrentPower = 0.0;
private double internalMaxPower = 200000.0;
private double internalMaxPower = MAX_STORED;
private byte currentMeta = -1;
@@ -179,6 +181,11 @@ public class EnergyCellTileEntity extends AENetworkTileEntity implements IAEPowe
return pm.divide(this.extractAEPower(pm.multiply(amt), mode));
}
@Override
public int getPriority() {
return 200;
}
private double extractAEPower(double amt, final Actionable mode) {
if (mode == Actionable.SIMULATE) {
if (this.internalCurrentPower > amt) {
@@ -218,4 +225,5 @@ public class EnergyCellTileEntity extends AENetworkTileEntity implements IAEPowe
void setInternalMaxPower(final double internalMaxPower) {
this.internalMaxPower = internalMaxPower;
}
}
@@ -32,6 +32,7 @@ import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelDataMap;
import net.minecraftforge.client.model.data.ModelProperty;
@@ -48,7 +49,6 @@ import appeng.api.util.DimensionalCoord;
import appeng.block.qnb.QnbFormedState;
import appeng.core.Api;
import appeng.me.GridAccessException;
import appeng.me.cluster.IAECluster;
import appeng.me.cluster.IAEMultiBlock;
import appeng.me.cluster.implementations.QuantumCalculator;
import appeng.me.cluster.implementations.QuantumCluster;
@@ -56,7 +56,8 @@ import appeng.tile.grid.AENetworkInvTileEntity;
import appeng.tile.inventory.AppEngInternalInventory;
import appeng.util.inv.InvOperation;
public class QuantumBridgeTileEntity extends AENetworkInvTileEntity implements IAEMultiBlock, ITickableTileEntity {
public class QuantumBridgeTileEntity extends AENetworkInvTileEntity
implements IAEMultiBlock<QuantumCluster>, ITickableTileEntity {
public static final ModelProperty<QnbFormedState> FORMED_STATE = new ModelProperty<>();
@@ -190,7 +191,7 @@ public class QuantumBridgeTileEntity extends AENetworkInvTileEntity implements I
}
@Override
public IAECluster getCluster() {
public QuantumCluster getCluster() {
return this.cluster;
}
@@ -209,11 +210,7 @@ public class QuantumBridgeTileEntity extends AENetworkInvTileEntity implements I
}
if (this.isCorner() || this.isCenter()) {
final EnumSet<Direction> sides = EnumSet.noneOf(Direction.class);
for (final Direction dir : this.getAdjacentQuantumBridges()) {
sides.add(dir);
}
EnumSet<Direction> sides = EnumSet.copyOf(this.getAdjacentQuantumBridges());
this.getProxy().setValidSides(sides);
} else {
this.getProxy().setValidSides(EnumSet.allOf(Direction.class));
@@ -272,8 +269,8 @@ public class QuantumBridgeTileEntity extends AENetworkInvTileEntity implements I
return AECableType.DENSE_SMART;
}
public void neighborUpdate() {
this.calc.calculateMultiblock(this.world, this.getLocation());
public void neighborUpdate(BlockPos fromPos) {
this.calc.updateMultiblockAfterNeighborUpdate(this.world, this.pos, fromPos);
}
@Override
@@ -289,6 +286,11 @@ public class QuantumBridgeTileEntity extends AENetworkInvTileEntity implements I
}
public void breakCluster() {
// Since breaking the cluster will most likely also update the TE's state,
// it's essential that we're not working with outdated block-state information,
// since this particular TE's block might already have been removed (state=air)
updateContainingBlockInfo();
if (this.cluster != null) {
this.cluster.destroy();
}
@@ -99,7 +99,7 @@ public class SpatialIOPortTileEntity extends AENetworkInvTileEntity implements I
if (Platform.isServer()) {
final ItemStack cell = this.inv.getStackInSlot(0);
if (this.isSpatialCell(cell)) {
TickHandler.INSTANCE.addCallable(null, this);// this needs to be cross world synced.
TickHandler.instance().addCallable(null, this);// this needs to be cross world synced.
}
}
}
@@ -26,6 +26,7 @@ import javax.annotation.Nonnull;
import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelDataMap;
import net.minecraftforge.client.model.data.ModelProperty;
@@ -42,7 +43,7 @@ import appeng.me.helpers.AENetworkProxy;
import appeng.me.helpers.AENetworkProxyMultiblock;
import appeng.tile.grid.AENetworkTileEntity;
public class SpatialPylonTileEntity extends AENetworkTileEntity implements IAEMultiBlock {
public class SpatialPylonTileEntity extends AENetworkTileEntity implements IAEMultiBlock<SpatialPylonCluster> {
public static final ModelProperty<Integer> STATE = new ModelProperty<>(value -> {
// The lower 6 bits are used
@@ -87,7 +88,7 @@ public class SpatialPylonTileEntity extends AENetworkTileEntity implements IAEMu
@Override
public void onReady() {
super.onReady();
this.neighborChanged();
this.calc.calculateMultiblock(world, pos);
}
@Override
@@ -96,8 +97,8 @@ public class SpatialPylonTileEntity extends AENetworkTileEntity implements IAEMu
super.remove();
}
public void neighborChanged() {
this.calc.calculateMultiblock(this.world, this.getLocation());
public void neighborChanged(BlockPos changedPos) {
this.calc.updateMultiblockAfterNeighborUpdate(this.world, pos, changedPos);
}
@Override
@@ -130,9 +131,9 @@ public class SpatialPylonTileEntity extends AENetworkTileEntity implements IAEMu
this.displayBits = 0;
if (this.cluster != null) {
if (this.cluster.getMin().equals(this.getLocation())) {
if (this.cluster.getBoundsMin().equals(this.pos)) {
this.displayBits = DISPLAY_END_MIN;
} else if (this.cluster.getMax().equals(this.getLocation())) {
} else if (this.cluster.getBoundsMax().equals(this.pos)) {
this.displayBits = DISPLAY_END_MAX;
} else {
this.displayBits = DISPLAY_MIDDLE;
@@ -29,6 +29,7 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.container.ContainerType;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.ITickableTileEntity;
@@ -42,44 +43,24 @@ import net.minecraftforge.fluids.IFluidTank;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.registries.ForgeRegistries;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable;
import appeng.api.config.PowerMultiplier;
import appeng.api.config.SecurityPermissions;
import appeng.api.config.Settings;
import appeng.api.config.SortDir;
import appeng.api.config.SortOrder;
import appeng.api.config.ViewItems;
import appeng.api.config.*;
import appeng.api.implementations.tiles.IColorableTile;
import appeng.api.implementations.tiles.IMEChest;
import appeng.api.networking.GridFlags;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridNode;
import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.events.MENetworkCellArrayUpdate;
import appeng.api.networking.events.MENetworkChannelsChanged;
import appeng.api.networking.events.MENetworkEventSubscribe;
import appeng.api.networking.events.MENetworkPowerStatusChange;
import appeng.api.networking.events.MENetworkPowerStorage;
import appeng.api.networking.events.*;
import appeng.api.networking.events.MENetworkPowerStorage.PowerEventType;
import appeng.api.networking.security.IActionHost;
import appeng.api.networking.security.IActionSource;
import appeng.api.networking.security.ISecurityGrid;
import appeng.api.networking.storage.IBaseMonitor;
import appeng.api.networking.storage.IStorageGrid;
import appeng.api.storage.IMEInventoryHandler;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.IMEMonitorHandlerReceiver;
import appeng.api.storage.IStorageChannel;
import appeng.api.storage.IStorageMonitorable;
import appeng.api.storage.IStorageMonitorableAccessor;
import appeng.api.storage.ITerminalHost;
import appeng.api.storage.cells.CellState;
import appeng.api.storage.cells.ICellGuiHandler;
import appeng.api.storage.cells.ICellHandler;
import appeng.api.storage.cells.ICellInventory;
import appeng.api.storage.cells.ICellInventoryHandler;
import appeng.api.storage.*;
import appeng.api.storage.cells.*;
import appeng.api.storage.channels.IFluidStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEFluidStack;
@@ -133,6 +114,10 @@ public class ChestTileEntity extends AENetworkPowerTileEntity
private ChestMonitorHandler cellHandler;
private Accessor accessor;
private IFluidHandler fluidHandler;
// This is only used on the client to display the right cell model without
// synchronizing the entire
// cell's inventory when a chest comes into view.
private Item cellItem = Items.AIR;
public ChestTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
@@ -273,6 +258,10 @@ public class ChestTileEntity extends AENetworkPowerTileEntity
if (slot != 0) {
return null;
}
// Client-side we'll need to actually use the synced state
if (world == null || world.isRemote) {
return cellItem;
}
ItemStack cell = getCell();
return cell.isEmpty() ? null : cell.getItem();
}
@@ -364,6 +353,12 @@ public class ChestTileEntity extends AENetworkPowerTileEntity
data.writeByte(this.state);
data.writeByte(this.paintedColor.ordinal());
// Note that we trust that the change detection in recalculateDisplay will trip
// when it changes from
// empty->non-empty, so when the cell is changed, it should re-send the state
// because of that
data.writeRegistryIdUnsafe(ForgeRegistries.ITEMS, getCell().getItem().getRegistryName());
}
@Override
@@ -375,6 +370,7 @@ public class ChestTileEntity extends AENetworkPowerTileEntity
this.state = data.readByte();
final AEColor oldPaintedColor = this.paintedColor;
this.paintedColor = AEColor.values()[data.readByte()];
this.cellItem = data.readRegistryIdUnsafe(ForgeRegistries.ITEMS);
this.lastStateChange = this.world.getGameTime();
@@ -65,6 +65,7 @@ import appeng.block.storage.DriveSlotsState;
import appeng.client.render.model.DriveModelData;
import appeng.container.implementations.DriveContainer;
import appeng.core.Api;
import appeng.core.sync.BasePacket;
import appeng.helpers.IPriorityHost;
import appeng.me.GridAccessException;
import appeng.me.helpers.MachineSource;
@@ -188,7 +189,7 @@ public class DriveTileEntity extends AENetworkInvTileEntity implements IChestOrD
int uniqueStrCount = data.readByte();
String[] uniqueStrs = new String[uniqueStrCount];
for (int i = 0; i < uniqueStrCount; i++) {
uniqueStrs[i] = data.readString();
uniqueStrs[i] = data.readString(BasePacket.MAX_STRING_LENGTH);
}
boolean changed = false;
+15 -13
View File
@@ -822,34 +822,36 @@ public class Platform {
Preconditions.checkNotNull(src);
Preconditions.checkNotNull(mode);
final T possible = cell.injectItems(input.copy(), Actionable.SIMULATE, src);
final T overflow = cell.injectItems(input.copy(), Actionable.SIMULATE, src);
long stored = input.getStackSize();
if (possible != null) {
stored -= possible.getStackSize();
long transferAmount = input.getStackSize();
if (overflow != null) {
transferAmount -= overflow.getStackSize();
}
final double energyFactor = Math.max(1.0, cell.getChannel().transferFactor());
final double availablePower = energy.extractAEPower(stored / energyFactor, Actionable.SIMULATE,
final double availablePower = energy.extractAEPower(transferAmount / energyFactor, Actionable.SIMULATE,
PowerMultiplier.CONFIG);
final long itemToAdd = Math.min((long) ((availablePower * energyFactor) + 0.9), stored);
final long itemToAdd = Math.min((long) ((availablePower * energyFactor) + 0.9), transferAmount);
if (itemToAdd > 0) {
if (mode == Actionable.MODULATE) {
energy.extractAEPower(stored / energyFactor, Actionable.MODULATE, PowerMultiplier.CONFIG);
energy.extractAEPower(transferAmount / energyFactor, Actionable.MODULATE, PowerMultiplier.CONFIG);
if (itemToAdd < input.getStackSize()) {
final long original = input.getStackSize();
final T leftover = input.copy();
final T split = input.copy();
split.decStackSize(itemToAdd);
input.setStackSize(itemToAdd);
split.add(cell.injectItems(input, Actionable.MODULATE, src));
leftover.decStackSize(itemToAdd);
split.setStackSize(itemToAdd);
leftover.add(cell.injectItems(split, Actionable.MODULATE, src));
src.player().ifPresent(player -> {
final long diff = original - split.getStackSize();
final long diff = original - leftover.getStackSize();
AeStats.ItemsInserted.addToPlayer(player, (int) diff);
});
return split;
return leftover;
}
final T ret = cell.injectItems(input, Actionable.MODULATE, src);
@@ -1125,7 +1127,7 @@ public class Platform {
public static void notifyBlocksOfNeighbors(final World world, final BlockPos pos) {
if (!world.isRemote) {
TickHandler.INSTANCE.addCallable(world, new BlockUpdate(pos));
TickHandler.instance().addCallable(world, new BlockUpdate(pos));
}
}
@@ -25,9 +25,9 @@ import appeng.api.networking.IGridNode;
import appeng.api.util.AEPartLocation;
public final class ProxyNodeIterator implements Iterator<IGridNode> {
private final Iterator<IGridHost> hosts;
private final Iterator<? extends IGridHost> hosts;
public ProxyNodeIterator(final Iterator<IGridHost> hosts) {
public ProxyNodeIterator(final Iterator<? extends IGridHost> hosts) {
this.hosts = hosts;
}
+1 -1
View File
@@ -16,7 +16,7 @@ description="A Mod about Matter, Energy and using them to conquer the world.."
[[dependencies.appliedenergistics2]]
modId="forge"
mandatory=true
versionRange="[31.0.0,)"
versionRange="[31.2.31,32.0.0)"
ordering="NONE"
side="BOTH"

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