Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 59e40ccbd9 | |||
| 774f88ee90 | |||
| 0528879833 | |||
| b6110e4f4a | |||
| 5b82e59264 | |||
| 3a4b171443 | |||
| 2ac27fd9ce | |||
| d01aa28cdc | |||
| 21aa5ce33b | |||
| f7ef6eb772 | |||
| 10037a9ac5 | |||
| 888de430ba | |||
| 83d661ab2a | |||
| a537bcf0ee | |||
| 590e435ad6 | |||
| 8d92a51e4f | |||
| 4322910614 | |||
| ebe589a714 | |||
| 6187e6a7bb | |||
| d5f113eb35 | |||
| 9ad5bb21c0 | |||
| 1c88ea7b78 | |||
| 5a976ebfae | |||
| b45669bb82 | |||
| e52cc40dbf | |||
| 8a20d3c1d7 | |||
| 749ebeb91d | |||
| 82586732e3 | |||
| e023d83e62 | |||
| de7cbc4949 | |||
| 71a91e51fb | |||
| 223163aa0a | |||
| bdd22093c3 | |||
| 0367b35ce0 | |||
| 755ac12b8a | |||
| e1f9e01404 | |||
| 7121426fc9 | |||
| a94e8504f8 | |||
| 9275bfe001 | |||
| 5b3c4aef79 | |||
| 4a289470e2 | |||
| d79c0f642c | |||
| 9ecad8749f | |||
| e8b57c6dc5 | |||
| 8142eb90a6 | |||
| 08abd4a770 | |||
| b8722dbbc0 | |||
| 1ac6d5d967 | |||
| 5c290789e0 | |||
| 38f6bf16f2 | |||
| 4953509255 | |||
| 188f105730 |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
+3
-3
@@ -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
-1
@@ -1,4 +1,4 @@
|
||||
package appeng.forge.data.providers;
|
||||
package appeng.datagen.providers;
|
||||
|
||||
import net.minecraft.data.IDataProvider;
|
||||
|
||||
+2
-2
@@ -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()
|
||||
+2
-2
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user