Merge remote-tracking branch 'origin/master' into fabric/master
# Conflicts: # build.gradle # gradle.properties # gradle/scripts/artifacts.gradle # gradle/scripts/curseforge.gradle # gradle/wrapper/gradle-wrapper.jar # gradle/wrapper/gradle-wrapper.properties # src/main/java/appeng/block/networking/CableBusBlock.java # src/main/java/appeng/client/gui/AEBaseScreen.java # src/main/java/appeng/client/gui/implementations/InterfaceTerminalScreen.java # src/main/java/appeng/client/gui/widgets/Scrollbar.java # src/main/java/appeng/core/sync/packets/JEIRecipePacket.java # src/main/java/appeng/tile/AEBaseBlockEntity.java # src/main/resources/META-INF/mods.toml
This commit is contained in:
@@ -300,22 +300,36 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
|
||||
}
|
||||
}
|
||||
|
||||
if (this.getScrollBar() != null) {
|
||||
this.getScrollBar().click(xCoord - this.x, yCoord - this.y);
|
||||
// Forward left mouse button down events to the scrollbar
|
||||
if (btn == 0 && this.getScrollBar() != null) {
|
||||
if (this.getScrollBar().mouseDown(xCoord - this.x, yCoord - this.y)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return super.mouseClicked(xCoord, yCoord, btn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseDragged(double mouseX, double mouseY, int mouseButton, double dragX, double dragY) {
|
||||
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
||||
// Forward left mouse button up events to the scrollbar
|
||||
if (button == 0 && this.getScrollBar() != null) {
|
||||
if (this.getScrollBar().mouseUp(mouseX - this.guiLeft, mouseY - this.guiTop)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return super.mouseReleased(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseDragged(double mouseX, double mouseY, int mouseButton, double dragX, double dragY) {
|
||||
final Slot slot = this.getSlot((int) mouseX, (int) mouseY);
|
||||
final ItemStack itemstack = getPlayer().inventory.getCursorStack();
|
||||
|
||||
if (this.getScrollBar() != null) {
|
||||
// FIXME: Coordinate system of mouseX/mouseY is unclear
|
||||
this.getScrollBar().click((int) mouseX - this.x, (int) mouseY - this.y);
|
||||
this.getScrollBar().mouseDragged((int) mouseX - this.x, (int) mouseY - this.y);
|
||||
}
|
||||
|
||||
if (slot instanceof FakeSlot && !itemstack.isEmpty()) {
|
||||
@@ -798,6 +812,11 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScr
|
||||
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
if (this.getScrollBar() != null) {
|
||||
this.getScrollBar().tick();
|
||||
}
|
||||
|
||||
for (Element child : children) {
|
||||
if (child instanceof ITickingWidget) {
|
||||
((ITickingWidget) child).tick();
|
||||
|
||||
@@ -93,6 +93,8 @@ public class CraftConfirmScreen extends AEBaseScreen<CraftConfirmContainer> {
|
||||
|
||||
addButton(new ButtonWidget(this.x + 6, this.y + this.backgroundHeight - 25, 50, 20, GuiText.Cancel.text(),
|
||||
btn -> subGui.goBack()));
|
||||
|
||||
this.setScrollBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -70,8 +70,7 @@ public class InterfaceTerminalScreen extends AEBaseScreen<InterfaceTerminalConta
|
||||
|
||||
public InterfaceTerminalScreen(InterfaceTerminalContainer container, PlayerInventory playerInventory, Text title) {
|
||||
super(container, playerInventory, title);
|
||||
final Scrollbar scrollbar = new Scrollbar();
|
||||
this.setScrollBar(scrollbar);
|
||||
this.setScrollBar(new Scrollbar().setLeft(175).setTop(18).setHeight(106));
|
||||
this.backgroundWidth = 195;
|
||||
this.backgroundHeight = 222;
|
||||
}
|
||||
@@ -80,10 +79,6 @@ public class InterfaceTerminalScreen extends AEBaseScreen<InterfaceTerminalConta
|
||||
public void init() {
|
||||
super.init();
|
||||
|
||||
this.getScrollBar().setLeft(175);
|
||||
this.getScrollBar().setHeight(106);
|
||||
this.getScrollBar().setTop(18);
|
||||
|
||||
this.searchField = new AETextField(this.textRenderer, this.x + 104, this.y + 4, 65, 12);
|
||||
this.searchField.setHasBorder(false);
|
||||
this.searchField.setMaxLength(25);
|
||||
|
||||
@@ -283,6 +283,8 @@ public class MEMonitorableScreen<T extends MEMonitorableContainer> extends AEBas
|
||||
craftingGridOffsetX -= 25;
|
||||
craftingGridOffsetY -= 6;
|
||||
|
||||
this.setScrollBar();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
|
||||
*
|
||||
* Applied Energistics 2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Applied Energistics 2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
||||
*/
|
||||
|
||||
package appeng.client.gui.widgets;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* This class can be used to implement repeating events such as holding down a
|
||||
* button to fire an event repeatedly while the button is still being held, or
|
||||
* repeatedly scrolling down a page, while the mouse is held down on the
|
||||
* scrollbar.
|
||||
*/
|
||||
public class EventRepeater {
|
||||
|
||||
/**
|
||||
* -1 if no repeat event is scheduled. Otherwise contains the
|
||||
* {@link System#nanoTime()} at which the next event should occur.
|
||||
*/
|
||||
private long nextEventTime = -1;
|
||||
|
||||
private EventCallback eventCallback = null;
|
||||
|
||||
private final long eventDelay; // In nanoseconds
|
||||
|
||||
private final long eventInterval; // In nanoseconds
|
||||
|
||||
public EventRepeater(Duration delay, Duration interval) {
|
||||
this.eventDelay = delay.toNanos();
|
||||
this.eventInterval = interval.toNanos();
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (this.eventCallback == null) {
|
||||
return; // No event scheduled
|
||||
}
|
||||
|
||||
// Use nanoTime here because it is monotonically increasing, while
|
||||
// System.currentTimeMillis is not
|
||||
long nanoTime = System.nanoTime();
|
||||
if (nanoTime < this.nextEventTime) {
|
||||
return; // Event time not reached
|
||||
}
|
||||
|
||||
// Before triggering, recompute the next event, since
|
||||
// the event callback itself may reschedule/cancel, and
|
||||
// we should not overwrite that
|
||||
this.nextEventTime = nanoTime + this.eventInterval;
|
||||
this.eventCallback.trigger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the given callback to be called after a given initial delay, and
|
||||
* then after the given interval repeatedly.
|
||||
*
|
||||
* <p>
|
||||
* Replaces any previously queued callback.
|
||||
*/
|
||||
public void repeat(EventCallback callback) {
|
||||
long time = System.nanoTime();
|
||||
this.eventCallback = callback;
|
||||
this.nextEventTime = time + eventDelay;
|
||||
}
|
||||
|
||||
public boolean isRepeating() {
|
||||
return this.eventCallback != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop repeating the event.
|
||||
*/
|
||||
public void stop() {
|
||||
this.eventCallback = null;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface EventCallback {
|
||||
void trigger();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,18 +18,76 @@
|
||||
|
||||
package appeng.client.gui.widgets;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import java.time.Duration;
|
||||
|
||||
import net.minecraft.client.gui.DrawableHelper;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
|
||||
import net.minecraft.client.renderer.Rectangle2d;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
import appeng.client.gui.AEBaseScreen;
|
||||
|
||||
public class Scrollbar implements IScrollSource {
|
||||
/**
|
||||
* Implements a vertical scrollbar using Vanilla's scrollbar handle texture from
|
||||
* the creative tab.
|
||||
* <p>
|
||||
* It is expected that the background of the UI contains a pre-baked scrollbar
|
||||
* track border, and that the exact rectangle of that track is set on this
|
||||
* object via {@link #setLeft(int)}, {@link #setTop(int)} and
|
||||
* {@link #setHeight(int)}. While the width of the track can also be set, the
|
||||
* drawn handle will use vanilla's sprite width (see {@link #HANDLE_WIDTH}.
|
||||
*/
|
||||
public class Scrollbar extends DrawableHelper implements IScrollSource {
|
||||
|
||||
/**
|
||||
* Width of the scrollbar handle sprite in the source texture.
|
||||
*/
|
||||
private static final int HANDLE_WIDTH = 12;
|
||||
|
||||
/**
|
||||
* Height of the scrollbar handle sprite in the source texture.
|
||||
*/
|
||||
private static final int HANDLE_HEIGHT = 15;
|
||||
|
||||
/**
|
||||
* Texture containing the scrollbar handle sprites.
|
||||
*/
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation("minecraft",
|
||||
"textures/gui/container/creative_inventory/tabs.png");
|
||||
|
||||
/**
|
||||
* Rectangle in the source texture that contains the sprite for an enabled
|
||||
* handle.
|
||||
*/
|
||||
private static final Rectangle2d ENABLED = new Rectangle2d(232, 0, HANDLE_WIDTH, HANDLE_HEIGHT);
|
||||
|
||||
/**
|
||||
* Rectangle in the source texture that contains the sprite for a disabled
|
||||
* handle.
|
||||
*/
|
||||
private static final Rectangle2d DISABLED = new Rectangle2d(232 + HANDLE_WIDTH, 0, HANDLE_WIDTH, HANDLE_HEIGHT);
|
||||
|
||||
/**
|
||||
* The screen x-coordinate of the scrollbar's inner track.
|
||||
*/
|
||||
private int displayX = 0;
|
||||
|
||||
/**
|
||||
* The screen y-coordinate of the scrollbar's inner track.
|
||||
*/
|
||||
private int displayY = 0;
|
||||
private int width = 12;
|
||||
|
||||
/**
|
||||
* The inner width of the scrollbar track.
|
||||
*/
|
||||
private int width = HANDLE_WIDTH;
|
||||
|
||||
/**
|
||||
* The inner height of the scrollbar track.
|
||||
*/
|
||||
private int height = 16;
|
||||
private int pageSize = 1;
|
||||
|
||||
@@ -37,20 +95,58 @@ public class Scrollbar implements IScrollSource {
|
||||
private int minScroll = 0;
|
||||
private int currentScroll = 0;
|
||||
|
||||
private final DrawableHelper drawable = new DrawableHelper() {
|
||||
};
|
||||
/**
|
||||
* True if the scrollbar's handle is currently being dragged.
|
||||
*/
|
||||
private boolean dragging;
|
||||
/**
|
||||
* The y-coordinate relative to the upper edge of the scrollbar handle, where
|
||||
* the user pressed the mouse button to drag. While dragging, this is applied as
|
||||
* an offset to the effective scrollbar position.
|
||||
*/
|
||||
private int dragYOffset;
|
||||
|
||||
private final EventRepeater eventRepeater = new EventRepeater(Duration.ofMillis(250), Duration.ofMillis(150));
|
||||
|
||||
/**
|
||||
* Draws the handle of the scrollbar.
|
||||
* <p>
|
||||
* The GUI is assumed to already contain a prebaked scrollbar track in its
|
||||
* background.
|
||||
*/
|
||||
public void draw(MatrixStack matrices, final AEBaseScreen<?> g) {
|
||||
g.bindTexture("minecraft", "gui/container/creative_inventory/tabs.png");
|
||||
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
setBlitOffset(g.getBlitOffset());
|
||||
|
||||
drawable.setZOffset(g.getZOffset());
|
||||
// Draw the track (nice for debugging)
|
||||
// fill(matrices, displayX, displayY, this.displayX + width, this.displayY +
|
||||
// height, 0xffff0000);
|
||||
|
||||
g.bindTexture(TEXTURE);
|
||||
|
||||
int yOffset;
|
||||
Rectangle2d sourceRect;
|
||||
if (this.getRange() == 0) {
|
||||
drawable.drawTexture(matrices, this.displayX, this.displayY, 232 + this.width, 0, this.width, 15);
|
||||
yOffset = 0;
|
||||
sourceRect = DISABLED;
|
||||
} else {
|
||||
final int offset = (this.currentScroll - this.minScroll) * (this.height - 15) / this.getRange();
|
||||
drawable.drawTexture(matrices, this.displayX, offset + this.displayY, 232, 0, this.width, 15);
|
||||
yOffset = getHandleYOffset();
|
||||
sourceRect = ENABLED;
|
||||
}
|
||||
|
||||
blit(matrices, this.displayX, this.displayY + yOffset, sourceRect.getX(), sourceRect.getY(),
|
||||
sourceRect.getWidth(), sourceRect.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the y-position of the scrollbar handle in relation to the upper edge
|
||||
* of the scrollbar's track.
|
||||
*/
|
||||
private int getHandleYOffset() {
|
||||
if (getRange() == 0) {
|
||||
return 0;
|
||||
}
|
||||
int availableHeight = this.height - HANDLE_HEIGHT;
|
||||
return (this.currentScroll - this.minScroll) * availableHeight / this.getRange();
|
||||
}
|
||||
|
||||
private int getRange() {
|
||||
@@ -114,24 +210,96 @@ public class Scrollbar implements IScrollSource {
|
||||
return this.currentScroll;
|
||||
}
|
||||
|
||||
public void click(final double x, final double y) {
|
||||
if (this.getRange() == 0) {
|
||||
public boolean mouseDown(double x, double y) {
|
||||
this.dragging = false;
|
||||
|
||||
// Clicks to the left or right of the scrollbar don't do anything
|
||||
if (x < displayX || x >= displayX + width) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clicks to the top or bottom don't do anything either
|
||||
int relY = (int) Math.round(y - displayY);
|
||||
if (relY < 0 || relY >= height) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do nothing when there's no range, but swallow the event
|
||||
if (getRange() == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int handleYOffset = getHandleYOffset();
|
||||
|
||||
if (relY < handleYOffset) {
|
||||
// Clicks above the handle will page up, repeatedly
|
||||
pageUp();
|
||||
eventRepeater.repeat(this::pageUp);
|
||||
|
||||
} else if (relY < handleYOffset + HANDLE_HEIGHT) {
|
||||
// Clicks on the handle will initiate dragging it
|
||||
this.dragging = true;
|
||||
this.dragYOffset = relY - handleYOffset;
|
||||
} else {
|
||||
// Clicks below the handle will page down, repeatedly
|
||||
pageDown();
|
||||
eventRepeater.repeat(this::pageDown);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean mouseUp(double x, double y) {
|
||||
this.dragging = false;
|
||||
this.eventRepeater.stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
public void mouseDragged(double x, double y) {
|
||||
if (this.getRange() == 0 || !this.dragging || this.eventRepeater.isRepeating()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (x > this.displayX && x <= this.displayX + this.width) {
|
||||
if (y > this.displayY && y <= this.displayY + this.height) {
|
||||
this.currentScroll = (int) (y - this.displayY);
|
||||
this.currentScroll = this.minScroll + ((this.currentScroll * 2 * this.getRange() / this.height));
|
||||
this.currentScroll = (this.currentScroll + 1) >> 1;
|
||||
this.applyRange();
|
||||
}
|
||||
}
|
||||
// Compute the position of the mouse (adjusted for where it grabbed the handle,
|
||||
// so as if it grabbed
|
||||
// the upper edge of it) within the scrollable area of the track (minus the
|
||||
// handle height).
|
||||
double handleUpperEdgeY = y - this.displayY - this.dragYOffset;
|
||||
double availableHeight = this.height - HANDLE_HEIGHT;
|
||||
double position = MathHelper.clamp(handleUpperEdgeY / availableHeight, 0.0, 1.0);
|
||||
|
||||
this.currentScroll = this.minScroll + (int) Math.round(position * this.getRange());
|
||||
this.applyRange();
|
||||
}
|
||||
|
||||
public void wheel(double delta) {
|
||||
// Do nothing when there's no range
|
||||
if (getRange() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
delta = Math.max(Math.min(-delta, 1), -1);
|
||||
this.currentScroll += delta * this.pageSize;
|
||||
this.applyRange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ticks the scrollbar for the purposes of input-repeats (since mouse-downs are
|
||||
* not repeat-triggered), used to repeatedly page-up or page-down when the mouse
|
||||
* is held in the area above or below the scrollbar handle.
|
||||
*/
|
||||
public void tick() {
|
||||
this.eventRepeater.tick();
|
||||
}
|
||||
|
||||
private void pageUp() {
|
||||
this.currentScroll -= this.pageSize;
|
||||
this.applyRange();
|
||||
}
|
||||
|
||||
private void pageDown() {
|
||||
this.currentScroll += this.pageSize;
|
||||
this.applyRange();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
package appeng.core.sync.packets;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -325,15 +326,10 @@ public class JEIRecipePacket extends BasePacket {
|
||||
*/
|
||||
private IAEItemStack findBestMatchingItemStack(Ingredient ingredients, IPartitionList<IAEItemStack> filter,
|
||||
IMEMonitor<IAEItemStack> storage, IContainerCraftingPacket cct) {
|
||||
return Arrays.stream(getMatchingStacks(ingredients)).map(AEItemStack::fromItemStack) //
|
||||
.filter(r -> r != null && (filter == null || filter.isListed(r))) //
|
||||
.map(s -> {
|
||||
// Determine the stored count
|
||||
IAEItemStack stored = storage.extractItems(s.copy().setStackSize(Long.MAX_VALUE),
|
||||
Actionable.SIMULATE, cct.getActionSource());
|
||||
return Pair.of(s, stored != null ? stored.getStackSize() : 0);
|
||||
}).min((left, right) -> Long.compare(right.getSecond(), left.getSecond()))//
|
||||
.map(Pair::getFirst).orElse(null);
|
||||
Stream<AEItemStack> stacks = Arrays.stream(getMatchingStacks(ingredients))//
|
||||
.map(AEItemStack::fromItemStack) //
|
||||
.filter(r -> r != null && (filter == null || filter.isListed(r)));
|
||||
return getMostStored(stacks, storage, cct);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -344,16 +340,30 @@ public class JEIRecipePacket extends BasePacket {
|
||||
*/
|
||||
private IAEItemStack findBestMatchingPattern(Ingredient ingredients, IPartitionList<IAEItemStack> filter,
|
||||
ICraftingGrid crafting, IMEMonitor<IAEItemStack> storage, IContainerCraftingPacket cct) {
|
||||
return Arrays.stream(getMatchingStacks(ingredients)).map(AEItemStack::fromItemStack)
|
||||
.filter(r -> r != null && (filter == null || filter.isListed(r)))
|
||||
.map(s -> s.setCraftable(!crafting.getCraftingFor(s, null, 0, null).isEmpty()))
|
||||
.filter(IAEItemStack::isCraftable).map(s -> {
|
||||
final IAEItemStack stored = storage.extractItems(s, Actionable.SIMULATE, cct.getActionSource());
|
||||
return s.setStackSize(stored != null ? stored.getStackSize() : 0);
|
||||
}).min((left, right) -> {
|
||||
final int craftable = Boolean.compare(left.isCraftable(), right.isCraftable());
|
||||
return craftable != 0 ? craftable : Long.compare(right.getStackSize(), left.getStackSize());
|
||||
}).orElse(null);
|
||||
Stream<IAEItemStack> stacks = Arrays.stream(getMatchingStacks(ingredients))//
|
||||
.map(AEItemStack::fromItemStack)//
|
||||
.filter(r -> r != null && (filter == null || filter.isListed(r)))//
|
||||
.map(s -> s.setCraftable(!crafting.getCraftingFor(s, null, 0, null).isEmpty()))//
|
||||
.filter(IAEItemStack::isCraftable);
|
||||
return getMostStored(stacks, storage, cct);
|
||||
}
|
||||
|
||||
/**
|
||||
* From a stream of AE item stacks, pick the one with the highest available
|
||||
* amount in the network. Returns null if the stream is empty.
|
||||
*/
|
||||
private static IAEItemStack getMostStored(Stream<? extends IAEItemStack> stacks, IMEMonitor<IAEItemStack> storage,
|
||||
IContainerCraftingPacket cct) {
|
||||
return stacks//
|
||||
.map(s -> {
|
||||
// Determine the stored count
|
||||
IAEItemStack stored = storage.extractItems(s.copy().setStackSize(Long.MAX_VALUE),
|
||||
Actionable.SIMULATE, cct.getActionSource());
|
||||
return Pair.of(s, stored != null ? stored.getStackSize() : 0);
|
||||
})//
|
||||
.min((left, right) -> Long.compare(right.getSecond(), left.getSecond()))//
|
||||
.map(Pair::getFirst)//
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private void handleProcessing(ScreenHandler con, IContainerCraftingPacket cct, Recipe<?> recipe) {
|
||||
|
||||
@@ -327,8 +327,9 @@ public class GridNode implements IGridNode, IPathItem {
|
||||
|
||||
@Override
|
||||
public void setPlayerID(final int playerID) {
|
||||
if (playerID >= 0) {
|
||||
if (playerID >= 0 && this.playerID != playerID) {
|
||||
this.playerID = playerID;
|
||||
gridProxy.onGridNotification(GridNotification.OWNER_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -96,7 +96,11 @@ public class CraftingGridCache
|
||||
nextDetail) -> nextDetail.getPriority() - firstDetail.getPriority();
|
||||
|
||||
static {
|
||||
final ThreadFactory factory = ar -> new Thread(ar, "AE Crafting Calculator");
|
||||
final ThreadFactory factory = ar -> {
|
||||
final Thread crafting = new Thread(ar, "AE Crafting Calculator");
|
||||
crafting.setDaemon(true);
|
||||
return crafting;
|
||||
};
|
||||
|
||||
CRAFTING_POOL = Executors.newCachedThreadPool(factory);
|
||||
}
|
||||
|
||||
+14
-2
@@ -81,8 +81,16 @@ public class SecurityCache implements ISecurityGrid {
|
||||
private void updateSecurityKey() {
|
||||
final long lastCode = this.securityKey;
|
||||
|
||||
/**
|
||||
* Placing a security station will propagate the security station's owner to all
|
||||
* connected grid nodes to prevent the network from not reforming due to
|
||||
* different owners later.
|
||||
*/
|
||||
int newOwner = -1;
|
||||
if (this.securityProvider.size() == 1) {
|
||||
this.securityKey = this.securityProvider.get(0).getSecurityKey();
|
||||
ISecurityProvider securityProvider = this.securityProvider.get(0);
|
||||
this.securityKey = securityProvider.getSecurityKey();
|
||||
newOwner = securityProvider.getOwner();
|
||||
} else {
|
||||
this.securityKey = -1;
|
||||
}
|
||||
@@ -90,7 +98,11 @@ public class SecurityCache implements ISecurityGrid {
|
||||
if (lastCode != this.securityKey) {
|
||||
this.getGrid().postEvent(new MENetworkSecurityChange());
|
||||
for (final IGridNode n : this.getGrid().getNodes()) {
|
||||
((GridNode) n).setLastSecurityKey(this.securityKey);
|
||||
GridNode gridNode = (GridNode) n;
|
||||
gridNode.setLastSecurityKey(this.securityKey);
|
||||
if (gridNode.getPlayerID() != newOwner) {
|
||||
gridNode.setPlayerID(newOwner);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,6 +279,11 @@ public class AENetworkProxy implements IGridBlock {
|
||||
|
||||
@Override
|
||||
public void onGridNotification(final GridNotification notification) {
|
||||
if (notification == GridNotification.OWNER_CHANGED) {
|
||||
gp.saveChanges();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.gp instanceof CablePart) {
|
||||
((CablePart) this.gp).markForUpdate();
|
||||
}
|
||||
|
||||
@@ -28,4 +28,7 @@ public interface IGridProxyable extends IGridHost {
|
||||
DimensionalCoord getLocation();
|
||||
|
||||
void gridChanged();
|
||||
|
||||
void saveChanges();
|
||||
|
||||
}
|
||||
|
||||
@@ -33,7 +33,9 @@ public final class CompassThreadFactory implements ThreadFactory {
|
||||
@Override
|
||||
public Thread newThread(@Nonnull final Runnable job) {
|
||||
Preconditions.checkNotNull(job);
|
||||
final Thread compass = new Thread(job, "AE Compass Service");
|
||||
compass.setDaemon(true);
|
||||
|
||||
return new Thread(job, "AE Compass Service");
|
||||
return compass;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user