Makes controller animations per storage network instead of globally (#1595)

This commit is contained in:
Worive authored and GitHub committed 2026-09-23 06:03:09 +00:00
1 parent 579ab2bed1
commit eee8fa38c6
17 files changed
+502 -59

No files matched your search

@@ -45,6 +45,7 @@ public enum ActionItems {
CONTROL_BUTTON_VALUES_OFF,
CONTROL_BUTTON_VALUES_ON,
PINS,
CONTROLLER_ANIMATION,
TOGGLE_SHOW_HIDDEN_INTERFACES_ON,
TOGGLE_SHOW_HIDDEN_INTERFACES_OFF,
RENAME_INTERFACE,
@@ -24,8 +24,8 @@ import appeng.block.AEBaseTileBlock;
import appeng.client.render.blocks.RenderBlockController;
import appeng.client.texture.ControllerLightTexture;
import appeng.client.texture.ExtraBlockTextures;
import appeng.core.AEConfig;
import appeng.core.features.AEFeature;
import appeng.core.settings.ControllerAnimation;
import appeng.tile.networking.TileController;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@@ -39,7 +39,7 @@ public class BlockController extends AEBaseTileBlock {
private IIcon[][] coloredTextures;
@SideOnly(Side.CLIENT)
private IIcon[][] lightTextures;
private IIcon[][][] lightTextures;
public BlockController() {
super(Material.iron);
@@ -68,18 +68,17 @@ public class BlockController extends AEBaseTileBlock {
super.registerBlockIcons(iconRegistry);
this.coloredTextures = new IIcon[COLORED_TEXTURE_COUNT][AEColor.VALUES.length];
if (!AEConfig.instance.controllerAnimation.usesOriginalTexture()) {
this.lightTextures = new IIcon[2][AEColor.VALUES.length];
final TextureMap map = (TextureMap) iconRegistry;
this.lightTextures = new IIcon[ControllerAnimation.values().length][2][AEColor.VALUES.length];
final TextureMap map = (TextureMap) iconRegistry;
for (final ControllerAnimation animation : ControllerAnimation.values()) {
if (animation.usesOriginalTexture()) continue;
for (final AEColor color : AEColor.VALUES) {
for (int id = 0; id < 2; id++) {
final String source = id == 0 ? "BlockControllerLights" : "BlockControllerColumnLights";
final ControllerLightTexture lights = new ControllerLightTexture(
source,
color,
AEConfig.instance.controllerAnimation);
final ControllerLightTexture lights = new ControllerLightTexture(source, color, animation);
map.setTextureEntry(lights.getIconName(), lights);
this.lightTextures[id][color.ordinal()] = map.getTextureExtry(lights.getIconName());
this.lightTextures[animation.ordinal()][id][color.ordinal()] = map
.getTextureExtry(lights.getIconName());
}
}
}
@@ -95,8 +94,8 @@ public class BlockController extends AEBaseTileBlock {
}
@SideOnly(Side.CLIENT)
public IIcon getLightTexture(final int id, final AEColor color) {
return this.lightTextures[id][color.ordinal()];
public IIcon getLightTexture(final int id, final AEColor color, final ControllerAnimation animation) {
return this.lightTextures[animation.ordinal()][id][color.ordinal()];
}
@SideOnly(Side.CLIENT)
@@ -12,12 +12,14 @@ package appeng.client;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.List;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.entity.RenderItem;
@@ -38,6 +40,8 @@ import net.minecraftforge.client.event.MouseEvent;
import net.minecraftforge.client.event.RenderLivingEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Property;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import org.lwjgl.opengl.GL11;
@@ -66,7 +70,9 @@ import appeng.client.texture.ExtraItemTextures;
import appeng.client.texture.WirelessTextures;
import appeng.core.AEConfig;
import appeng.core.AELog;
import appeng.core.AppEng;
import appeng.core.CommonHelper;
import appeng.core.settings.ControllerAnimation;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketAssemblerAnimation;
import appeng.core.sync.packets.PacketValueConfig;
@@ -80,6 +86,7 @@ import appeng.hooks.TickHandler.PlayerColor;
import appeng.server.ServerHelper;
import appeng.transformer.MissingCoreMod;
import appeng.util.Platform;
import cpw.mods.fml.client.event.ConfigChangedEvent;
import cpw.mods.fml.client.registry.ClientRegistry;
import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.common.FMLCommonHandler;
@@ -89,6 +96,7 @@ import cpw.mods.fml.common.eventhandler.SubscribeEvent;
public class ClientHelper extends ServerHelper {
private final EnumMap<ActionKey, KeyBinding> bindings = new EnumMap<>(ActionKey.class);
private static ControllerAnimation controllerAnimation = ControllerAnimation.ORIGINAL_RAINBOW;
private static final RenderItem ITEM_RENDERER = new RenderItem();
private static final RenderBlocks BLOCK_RENDERER = new RenderBlocks();
@@ -108,6 +116,7 @@ public class ClientHelper extends ServerHelper {
@Override
public void init() {
loadControllerAnimation();
MinecraftForge.EVENT_BUS.register(this);
MinecraftForge.EVENT_BUS.register(new BlockPosHighlighter());
MinecraftForge.EVENT_BUS.register(new NetworkVisualiserRender());
@@ -116,6 +125,7 @@ public class ClientHelper extends ServerHelper {
FMLCommonHandler.instance().bus().register(BlockRendererPreviewEvent.getInstance());
FMLCommonHandler.instance().bus().register(new KeyBindHandler());
FMLCommonHandler.instance().bus().register(new NotificationManager());
FMLCommonHandler.instance().bus().register(this);
for (ActionKey key : ActionKey.values()) {
final KeyBinding binding = new KeyBinding(key.getTranslationKey(), key.getDefaultKey(), KEY_CATEGORY);
@@ -124,6 +134,57 @@ public class ClientHelper extends ServerHelper {
}
}
public static ControllerAnimation cycleControllerAnimation() {
controllerAnimation = controllerAnimation.next();
AEConfig.instance.get("Client", "controllerAnimation", ControllerAnimation.ORIGINAL_RAINBOW.name())
.set(controllerAnimation.name());
AEConfig.instance.save();
syncControllerAnimationDefault();
return controllerAnimation;
}
public static ControllerAnimation getControllerAnimationDefault() {
return controllerAnimation;
}
@SubscribeEvent
public void onPlayerJoinWorld(final EntityJoinWorldEvent event) {
if (event.entity instanceof EntityPlayerSP) syncControllerAnimationDefault();
}
@SubscribeEvent
public void onConfigChanged(final ConfigChangedEvent.OnConfigChangedEvent event) {
if (!event.modID.equals(AppEng.MOD_ID)) return;
loadControllerAnimation();
syncControllerAnimationDefault();
}
private static void loadControllerAnimation() {
final Property property = AEConfig.instance.get(
"Client",
"controllerAnimation",
ControllerAnimation.ORIGINAL_RAINBOW.name(),
"Default animation for a controller placed into a network without another controller.");
property.setValidValues(Arrays.stream(ControllerAnimation.values()).map(Enum::name).toArray(String[]::new));
try {
controllerAnimation = ControllerAnimation.valueOf(property.getString());
} catch (IllegalArgumentException e) {
controllerAnimation = ControllerAnimation.ORIGINAL_RAINBOW;
property.set(controllerAnimation.name());
}
}
private static void syncControllerAnimationDefault() {
final Minecraft minecraft = Minecraft.getMinecraft();
if (minecraft.thePlayer == null || minecraft.theWorld == null) return;
try {
NetworkHandler.instance.sendToServer(
new PacketValueConfig(PacketValueConfig.CONTROLLER_ANIMATION_DEFAULT, controllerAnimation.name()));
} catch (final IOException e) {
AELog.debug(e);
}
}
@Override
public World getWorld() {
if (Platform.isClient()) {
@@ -10,7 +10,6 @@ import net.minecraft.world.World;
import com.gtnewhorizon.gtnhlib.event.PickBlockEvent;
import appeng.core.AEConfig;
import appeng.core.CommonHelper;
import appeng.core.settings.ControllerAnimation;
import appeng.core.sync.network.NetworkHandler;
@@ -55,16 +54,9 @@ public class KeyBindHandler {
final Minecraft minecraft = Minecraft.getMinecraft();
if (minecraft.currentScreen != null || minecraft.thePlayer == null) return;
final AEConfig config = AEConfig.instance;
config.controllerAnimation = config.controllerAnimation.next();
config.get("Client", "controllerAnimation", ControllerAnimation.WAVE.name())
.set(config.controllerAnimation.name());
config.save();
minecraft.refreshResources();
final ControllerAnimation animation = ClientHelper.cycleControllerAnimation();
minecraft.thePlayer.addChatMessage(
new ChatComponentTranslation(
"chat.appliedenergistics2.ControllerAnimation",
config.controllerAnimation.name()));
new ChatComponentTranslation("chat.appliedenergistics2.ControllerAnimation", animation.name()));
}
static boolean handlePickBlock() {
@@ -19,10 +19,13 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.IIcon;
import net.minecraftforge.common.util.ForgeDirection;
import org.lwjgl.input.Mouse;
@@ -30,6 +33,7 @@ import org.lwjgl.opengl.GL11;
import com.gtnewhorizon.gtnhlib.color.ColorResource;
import appeng.api.AEApi;
import appeng.api.config.ActionItems;
import appeng.api.config.Settings;
import appeng.api.config.SortDir;
@@ -38,7 +42,10 @@ import appeng.api.config.ViewItems;
import appeng.api.implementations.guiobjects.INetworkTool;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack;
import appeng.api.util.AEColor;
import appeng.api.util.NamedDimensionalCoord;
import appeng.block.networking.BlockController;
import appeng.client.ClientHelper;
import appeng.client.gui.AEBaseGui;
import appeng.client.gui.widgets.GuiContextMenu;
import appeng.client.gui.widgets.GuiImgButton;
@@ -47,12 +54,15 @@ import appeng.client.gui.widgets.GuiToggleButton;
import appeng.client.gui.widgets.ISortSource;
import appeng.client.me.ItemRepo;
import appeng.client.render.highlighter.BlockPosHighlighter;
import appeng.client.texture.ExtraBlockTextures;
import appeng.container.implementations.ContainerNetworkStatus;
import appeng.core.AEConfig;
import appeng.core.AELog;
import appeng.core.localization.ButtonToolTips;
import appeng.core.localization.ColorUtils;
import appeng.core.localization.GuiText;
import appeng.core.localization.PlayerMessages;
import appeng.core.settings.ControllerAnimation;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketClick;
import appeng.core.sync.packets.PacketNetworkStatusSelected;
@@ -69,6 +79,8 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource {
private GuiToggleButton diagnostics;
private GuiToggleButton liteCrafting;
private GuiToggleButton flowTracking;
private GuiImgButton controllerAnimation;
private final BlockController controllerPreview;
private int tooltip = -1;
private final DecimalFormat df;
private final boolean isAdvanced;
@@ -95,6 +107,8 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource {
this.repo.setRowSize(5);
this.isAdvanced = te.getSize() != 3;
this.isConsume = true;
this.controllerPreview = (BlockController) AEApi.instance().definitions().blocks().controller().maybeBlock()
.get();
menu = new GuiContextMenu(5) {
@Override
@@ -231,6 +245,17 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource {
// XD
}
}
} else if (btn == this.controllerAnimation) {
try {
NetworkHandler.instance.sendToServer(
new PacketValueConfig(
"NetworkStatus",
isShiftKeyDown() && !backwards ? PacketValueConfig.APPLY_CONTROLLER_ANIMATION_DEFAULT
: backwards ? PacketValueConfig.CYCLE_CONTROLLER_ANIMATION_BACKWARDS
: PacketValueConfig.CYCLE_CONTROLLER_ANIMATION));
} catch (final IOException e) {
AELog.debug(e);
}
}
if (oldConsume != this.isConsume) {
@@ -294,6 +319,19 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource {
GuiText.ItemFlowTrackingHint.getLocal());
this.buttonList.add(this.flowTracking);
}
this.controllerAnimation = new GuiImgButton(
this.guiLeft - 18,
this.guiTop + (this.isAdvanced ? 128 : 88),
Settings.ACTIONS,
ActionItems.CONTROLLER_ANIMATION) {
@Override
public void drawButton(final Minecraft mc, final int mouseX, final int mouseY) {
GuiNetworkStatus.this.drawControllerAnimationPreview();
}
};
this.buttonList.add(this.controllerAnimation);
}
@Override
@@ -349,11 +387,46 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource {
: ActionItems.OPEN_RESHUFFLE_OFF);
}
final ControllerAnimation animation = ControllerAnimation
.fromOrdinal(((ContainerNetworkStatus) this.inventorySlots).controllerAnimation);
final ControllerAnimation playerDefault = ClientHelper.getControllerAnimationDefault();
this.controllerAnimation.setFillVar(
(animation == playerDefault ? ButtonToolTips.ControllerAnimationStatusDefault
: ButtonToolTips.ControllerAnimationStatus).getLocal(animation.getLocal()));
super.drawScreen(mouseX, mouseY, btn);
menu.draw(mouseX, mouseY);
}
private void drawControllerAnimationPreview() {
final ControllerAnimation animation = ControllerAnimation
.fromOrdinal(((ContainerNetworkStatus) this.inventorySlots).controllerAnimation);
final IIcon lights = animation.usesOriginalTexture() ? ExtraBlockTextures.BlockControllerLights.getIcon()
: this.controllerPreview.getLightTexture(0, AEColor.Transparent, animation);
GL11.glPushAttrib(GL11.GL_ENABLE_BIT | GL11.GL_COLOR_BUFFER_BIT | GL11.GL_CURRENT_BIT);
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
this.mc.getTextureManager().bindTexture(TextureMap.locationBlocksTexture);
this.drawTexturedModelRectFromIcon(
this.controllerAnimation.xPosition,
this.controllerAnimation.yPosition,
this.controllerPreview.getRenderTexture(0, AEColor.Transparent),
16,
16);
this.drawTexturedModelRectFromIcon(
this.controllerAnimation.xPosition,
this.controllerAnimation.yPosition,
lights,
16,
16);
GL11.glPopAttrib();
}
@Override
public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) {
if (this.isConsume) drawConsume();
@@ -959,6 +959,14 @@ public class GuiImgButton extends GuiButton implements ITooltip {
ButtonToolTips.PinsSectionActive,
ButtonToolTips.PinsSectionHint);
this.registerApp(
255,
Settings.ACTIONS,
ActionItems.CONTROLLER_ANIMATION,
ButtonToolTips.ControllerAnimation,
ButtonToolTips.ControllerAnimationActive,
ButtonToolTips.ControllerAnimationHint);
this.registerApp(
16 * 3 + 7,
Settings.ACTIONS,
@@ -20,7 +20,7 @@ import appeng.block.networking.BlockController;
import appeng.block.networking.BlockCreativeEnergyController;
import appeng.client.render.BaseBlockRender;
import appeng.client.texture.ExtraBlockTextures;
import appeng.core.AEConfig;
import appeng.core.settings.ControllerAnimation;
import appeng.tile.networking.TileController;
public class RenderBlockController extends BaseBlockRender<BlockController, TileController> {
@@ -138,9 +138,9 @@ public class RenderBlockController extends BaseBlockRender<BlockController, Tile
final boolean out = renderer.renderStandardBlock(blk, x, y, z);
if (lights != null) {
final IIcon lightIcon = isConflict || AEConfig.instance.controllerAnimation.usesOriginalTexture()
? lights.getIcon()
: blk.getLightTexture(textureId, controller.getColor());
final ControllerAnimation animation = controller.getControllerAnimation();
final IIcon lightIcon = isConflict || animation.usesOriginalTexture() ? lights.getIcon()
: blk.getLightTexture(textureId, controller.getColor(), animation);
final Tessellator tess = Tessellator.instance;
tess.setColorOpaque_F(1.0f, 1.0f, 1.0f);
tess.setBrightness(14 << 20 | 14 << 4);
@@ -25,7 +25,7 @@ public class ControllerLightTexture extends TextureAtlasSprite {
private final ControllerAnimation style;
public ControllerLightTexture(final String source, final AEColor color, final ControllerAnimation style) {
super("appliedenergistics2:" + source + "_" + color.name());
super("appliedenergistics2:" + source + "_" + style.ordinal() + "_" + color.name());
this.source = new ResourceLocation("appliedenergistics2", "textures/blocks/" + source + ".png");
this.color = color;
this.style = style;
@@ -27,6 +27,7 @@ import com.gtnewhorizon.gtnhlib.util.map.ItemStackMap;
import appeng.api.AEApi;
import appeng.api.config.CellType;
import appeng.api.config.PowerMultiplier;
import appeng.api.config.SecurityPermissions;
import appeng.api.implementations.guiobjects.INetworkTool;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridBlock;
@@ -34,6 +35,8 @@ import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.pathing.IPathingGrid;
import appeng.api.networking.security.ISecurityGrid;
import appeng.api.networking.storage.IStorageGrid;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
@@ -41,6 +44,7 @@ import appeng.api.util.NamedDimensionalCoord;
import appeng.container.AEBaseContainer;
import appeng.container.guisync.GuiSync;
import appeng.core.AEConfig;
import appeng.core.settings.ControllerAnimation;
import appeng.core.sync.GuiBridge;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketMEInventoryUpdate;
@@ -48,6 +52,7 @@ import appeng.helpers.ICustomNameObject;
import appeng.me.cache.CraftingGridCache;
import appeng.me.cache.GridStorageCache;
import appeng.me.cache.ItemFlowGridCache;
import appeng.me.cache.PathGridCache;
import appeng.tile.misc.TileStorageReshuffle;
import appeng.util.Platform;
import appeng.util.item.AEItemStack;
@@ -168,6 +173,9 @@ public class ContainerNetworkStatus extends AEBaseContainer {
@GuiSync(37)
public boolean liteCraftingDefault;
@GuiSync(38)
public int controllerAnimation;
private IGrid network;
private int delay = 40;
private boolean isConsume = true;
@@ -262,6 +270,41 @@ public class ContainerNetworkStatus extends AEBaseContainer {
super.detectAndSendChanges();
}
private PathGridCache getPathGridCache() {
if (this.network == null) return null;
final IPathingGrid pathingGrid = this.network.getCache(IPathingGrid.class);
return pathingGrid instanceof PathGridCache cache ? cache : null;
}
private boolean hasControllerAnimationPermission() {
if (!Platform.isServer() || this.network == null) return false;
final ISecurityGrid security = this.network.getCache(ISecurityGrid.class);
return security != null && security.hasPermission(this.getInventoryPlayer().player, SecurityPermissions.BUILD);
}
private void refreshControllerAnimation() {
final PathGridCache cache = this.getPathGridCache();
this.controllerAnimation = cache == null ? 0 : cache.getControllerAnimation().ordinal();
}
public void cycleControllerAnimation(final boolean backwards) {
if (!this.hasControllerAnimationPermission()) return;
final PathGridCache cache = this.getPathGridCache();
if (cache == null) return;
cache.cycleControllerAnimation(backwards);
this.refreshControllerAnimation();
super.detectAndSendChanges();
}
public void setControllerAnimation(final ControllerAnimation animation) {
if (!this.hasControllerAnimationPermission()) return;
final PathGridCache cache = this.getPathGridCache();
if (cache == null) return;
cache.setControllerAnimation(animation);
this.refreshControllerAnimation();
super.detectAndSendChanges();
}
@Override
public void detectAndSendChanges() {
this.delay++;
@@ -271,6 +314,7 @@ public class ContainerNetworkStatus extends AEBaseContainer {
this.refreshDiagnosticsState();
this.refreshLiteCrafingState();
this.refreshFlowTrackingState();
this.refreshControllerAnimation();
final IEnergyGrid eg = this.network.getCache(IEnergyGrid.class);
if (eg != null) {
-23
View File
@@ -15,7 +15,6 @@ import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraftforge.common.config.ConfigCategory;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
@@ -40,7 +39,6 @@ import appeng.api.config.YesNo;
import appeng.api.util.IConfigManager;
import appeng.api.util.IConfigurableObject;
import appeng.core.features.AEFeature;
import appeng.core.settings.ControllerAnimation;
import appeng.core.settings.TickRates;
import appeng.items.materials.MaterialType;
import appeng.util.ConfigManager;
@@ -50,8 +48,6 @@ import cpw.mods.fml.client.event.ConfigChangedEvent;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public final class AEConfig extends Configuration implements IConfigurableObject, IConfigManagerHost {
@@ -90,7 +86,6 @@ public final class AEConfig extends Configuration implements IConfigurableObject
"Brass", "Platinum", "Nickel", "Invar", "Aluminium", "Electrum", "Osmium", "Zinc" };
public double oreDoublePercentage = 90.0;
public boolean enableEffects = true;
public ControllerAnimation controllerAnimation = ControllerAnimation.ORIGINAL_RAINBOW;
public boolean useColoredCraftingStatus;
public boolean previewBlocks;
public int previewLineWidth;
@@ -392,19 +387,6 @@ public final class AEConfig extends Configuration implements IConfigurableObject
this.disableColoredCableRecipesInNEI = this.get("Client", "disableColoredCableRecipesInNEI", true)
.getBoolean(true);
this.enableEffects = this.get("Client", "enableEffects", true).getBoolean(true);
final Property controllerAnimationProperty = this.get(
"Client",
"controllerAnimation",
ControllerAnimation.ORIGINAL_RAINBOW.name(),
"Powered controller animation. Changes apply when the config GUI is closed.");
controllerAnimationProperty
.setValidValues(Arrays.stream(ControllerAnimation.values()).map(Enum::name).toArray(String[]::new));
try {
this.controllerAnimation = ControllerAnimation.valueOf(controllerAnimationProperty.getString());
} catch (IllegalArgumentException e) {
this.controllerAnimation = ControllerAnimation.ORIGINAL_RAINBOW;
controllerAnimationProperty.set(this.controllerAnimation.name());
}
this.useColoredCraftingStatus = this.get("Client", "useColoredCraftingStatus", true).getBoolean(true);
this.previewBlocks = this.get("Client", "previewBlocks", true).getBoolean(true);
this.previewLineWidth = this.get("Client", "previewLineWidth", 3).getInt(3);
@@ -579,14 +561,9 @@ public final class AEConfig extends Configuration implements IConfigurableObject
public class EventHandler {
@SubscribeEvent
@SideOnly(Side.CLIENT)
public void onConfigChanged(final ConfigChangedEvent.OnConfigChangedEvent eventArgs) {
if (eventArgs.modID.equals(AppEng.MOD_ID)) {
final ControllerAnimation previousAnimation = AEConfig.this.controllerAnimation;
AEConfig.this.clientSync();
if (previousAnimation != AEConfig.this.controllerAnimation) {
Minecraft.getMinecraft().refreshResources();
}
}
}
}
@@ -254,6 +254,12 @@ public enum ButtonToolTips implements Localization {
PinsSectionActive,
PinsSectionHint,
ControllerAnimation,
ControllerAnimationActive,
ControllerAnimationHint,
ControllerAnimationStatus,
ControllerAnimationStatusDefault,
ToggleShowOnlySubstitute,
ToggleShowOnlySubstituteOnDesc,
ToggleShowOnlySubstituteOffDesc,
@@ -1,6 +1,8 @@
package appeng.core.settings;
public enum ControllerAnimation {
import appeng.core.localization.Localization;
public enum ControllerAnimation implements Localization {
ORIGINAL_RAINBOW,
WAVE,
@@ -11,11 +13,29 @@ public enum ControllerAnimation {
SINGULARITY,
CIRCUIT_TRACE;
public static ControllerAnimation fromOrdinal(final int ordinal) {
final ControllerAnimation[] styles = values();
return ordinal >= 0 && ordinal < styles.length ? styles[ordinal] : ORIGINAL_RAINBOW;
}
public static ControllerAnimation fromName(final String name) {
try {
return valueOf(name);
} catch (final IllegalArgumentException | NullPointerException ignored) {
return ORIGINAL_RAINBOW;
}
}
public ControllerAnimation next() {
final ControllerAnimation[] styles = values();
return styles[(ordinal() + 1) % styles.length];
}
public ControllerAnimation previous() {
final ControllerAnimation[] styles = values();
return styles[(ordinal() + styles.length - 1) % styles.length];
}
public boolean usesOriginalTexture() {
return this == ORIGINAL_RAINBOW;
}
@@ -24,6 +44,11 @@ public enum ControllerAnimation {
return this == CIRCUIT_TRACE;
}
@Override
public String getUnlocalized() {
return "gui.appliedenergistics2.ControllerAnimation." + this;
}
public int frameCount() {
// The two interference waves meet again after five 2.4-second cycles.
return this == SOFT_INTERFERENCE ? 240 : 48;
@@ -45,11 +45,17 @@ import appeng.container.interfaces.ICraftingCPUSelectorContainer;
import appeng.core.sync.AppEngPacket;
import appeng.core.sync.network.INetworkInfo;
import appeng.helpers.IMouseWheelItem;
import appeng.tile.networking.TileController;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
public class PacketValueConfig extends AppEngPacket {
public static final String CONTROLLER_ANIMATION_DEFAULT = "ControllerAnimationDefault";
public static final String APPLY_CONTROLLER_ANIMATION_DEFAULT = "ApplyControllerAnimationDefault";
public static final String CYCLE_CONTROLLER_ANIMATION = "CycleControllerAnimation";
public static final String CYCLE_CONTROLLER_ANIMATION_BACKWARDS = "CycleControllerAnimationBackwards";
private final String Name;
private final String Value;
@@ -86,7 +92,9 @@ public class PacketValueConfig extends AppEngPacket {
public void serverPacketData(final INetworkInfo manager, final AppEngPacket packet, final EntityPlayer player) {
final Container c = player.openContainer;
if (this.Name.equals("Item") && player.getHeldItem() != null
if (this.Name.equals(CONTROLLER_ANIMATION_DEFAULT)) {
TileController.setPlayerDefaultAnimation(player, this.Value);
} else if (this.Name.equals("Item") && player.getHeldItem() != null
&& player.getHeldItem().getItem() instanceof IMouseWheelItem) {
final ItemStack is = player.getHeldItem();
final IMouseWheelItem si = (IMouseWheelItem) is.getItem();
@@ -161,6 +169,12 @@ public class PacketValueConfig extends AppEngPacket {
qk.openReshuffle(player);
} else if (this.Value.equals("ToggleLiteCrafting")) {
qk.toggleLiteCraftingMode();
} else if (this.Value.equals(APPLY_CONTROLLER_ANIMATION_DEFAULT)) {
qk.setControllerAnimation(TileController.getPlayerDefaultAnimation(player));
} else if (this.Value.equals(CYCLE_CONTROLLER_ANIMATION)) {
qk.cycleControllerAnimation(false);
} else if (this.Value.equals(CYCLE_CONTROLLER_ANIMATION_BACKWARDS)) {
qk.cycleControllerAnimation(true);
}
} else if (c instanceof ContainerNetworkTool) {
if (this.Name.equals("NetworkTool")) {
@@ -7,13 +7,18 @@ import static appeng.gametests.AEGameTestHelpers.assertStoredAmount;
import static appeng.gametests.AEGameTestHelpers.cell1k;
import static appeng.gametests.AEGameTestHelpers.insertItems;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.common.util.ForgeDirection;
import com.gtnewhorizons.horizonqa.api.GameTestHelper;
@@ -23,11 +28,18 @@ import com.gtnewhorizons.horizonqa.api.annotation.GameTest;
import com.gtnewhorizons.horizonqa.api.annotation.GameTestHolder;
import appeng.api.AEApi;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridNode;
import appeng.api.networking.IGridStorage;
import appeng.api.networking.pathing.IPathingGrid;
import appeng.api.parts.IPart;
import appeng.api.parts.IPartHost;
import appeng.api.util.AEColor;
import appeng.core.AppEng;
import appeng.core.settings.ControllerAnimation;
import appeng.core.sync.packets.PacketValueConfig;
import appeng.me.GridStorage;
import appeng.me.cache.PathGridCache;
import appeng.tile.networking.TileCableBus;
import appeng.tile.networking.TileController;
import appeng.tile.storage.TileDrive;
@@ -122,6 +134,107 @@ public class NetworkCoreTests {
}).thenSucceed();
}
@GameTest(template = "network_core", timeoutTicks = 140)
public static void controllerAnimationFollowsNetworkAcrossMergeAndSplit(GameTestHelper helper) {
TileController controller = getController(helper);
TileDrive drive = getDrive(helper);
FakePlayer player = helper.spawnFakePlayer("controller_animation");
synchronizePlayerDefault(helper, player, ControllerAnimation.BREATHING);
installCableLine(helper, FULL_CABLE_LINE);
TileController[] placedController = new TileController[1];
helper.startSequence()
.thenWaitUntil(
"wait for the original network to form",
40,
() -> helper.assertSame(
controller.getProxy().getNode().getGrid(),
drive.getProxy().getNode().getGrid(),
"Controller and drive should share a grid"))
.thenExecute("place a controller with a different local default", () -> {
PathGridCache path = (PathGridCache) controller.getProxy().getNode().getGrid()
.getCache(IPathingGrid.class);
path.setControllerAnimation(ControllerAnimation.ORIGINAL_RAINBOW);
path.cycleControllerAnimation(true);
helper.assertEquals(
ControllerAnimation.CIRCUIT_TRACE,
path.getControllerAnimation(),
"Backwards cycling should wrap to the last animation");
path.cycleControllerAnimation(false);
helper.assertEquals(
ControllerAnimation.ORIGINAL_RAINBOW,
path.getControllerAnimation(),
"Forward cycling should wrap to the first animation");
path.setControllerAnimation(ControllerAnimation.WAVE);
helper.assertEquals(
ControllerAnimation.WAVE,
controller.getControllerAnimation(),
"Changing the network animation should update the existing controller");
placedController[0] = placeController(helper, "cable_8", player);
helper.assertEquals(
ControllerAnimation.BREATHING,
placedController[0].getControllerAnimation(),
"Controller placement should apply the placing player's synchronized default");
}).thenWaitUntil("wait for the placed controller to inherit the network animation", 40, () -> {
IGridNode placedNode = placedController[0].getProxy().getNode();
helper.assertNotNull(placedNode, "Placed controller should have a grid node");
helper.assertSame(
controller.getProxy().getNode().getGrid(),
placedNode.getGrid(),
"Placed controller should join the original grid");
helper.assertEquals(
ControllerAnimation.WAVE,
placedController[0].getControllerAnimation(),
"Existing network animation should override the placement default");
helper.assertEquals(
ControllerAnimation.WAVE,
((PathGridCache) placedNode.getGrid().getCache(IPathingGrid.class))
.getControllerAnimation(),
"Placed controller's grid cache should inherit the existing network animation");
}).thenExecute("round-trip controller and grid animation state", () -> {
IGrid grid = controller.getProxy().getNode().getGrid();
PathGridCache path = (PathGridCache) grid.getCache(IPathingGrid.class);
NBTTagCompound controllerData = new NBTTagCompound();
placedController[0].writeToNBT(controllerData);
TileController reloadedController = new TileController();
reloadedController.readFromNBT(controllerData);
helper.assertEquals(
ControllerAnimation.WAVE,
reloadedController.getControllerAnimation(),
"Controller animation should survive tile save and reload");
GridStorage gridStorage = new GridStorage();
path.populateGridStorage(gridStorage);
String persistedGridStorage = gridStorage.getValue();
helper.assertNotNull(persistedGridStorage, "Network animation should be written to grid storage");
IGridStorage reloadedGridStorage = new GridStorage(persistedGridStorage, gridStorage.getID(), null);
PathGridCache reloadedPath = new PathGridCache(grid);
reloadedPath.onJoin(reloadedGridStorage);
helper.assertEquals(
ControllerAnimation.WAVE,
reloadedPath.getControllerAnimation(),
"Network animation should survive grid storage save and reload");
}).thenExecute("split the two controllers", () -> removeBlock(helper, BREAKABLE_CABLE_LABEL))
.thenWaitUntil("wait for the split controller to retain its animation", 40, () -> {
IGridNode placedNode = placedController[0].getProxy().getNode();
helper.assertNotNull(placedNode, "Split controller should retain its grid node");
helper.assertNotSame(
controller.getProxy().getNode().getGrid(),
placedNode.getGrid(),
"Controllers should be on separate grids after the split");
helper.assertEquals(
ControllerAnimation.WAVE,
placedController[0].getControllerAnimation(),
"Split controller should retain the inherited animation");
helper.assertEquals(
ControllerAnimation.WAVE,
((PathGridCache) placedNode.getGrid().getCache(IPathingGrid.class))
.getControllerAnimation(),
"Split controller grid cache should retain the inherited animation");
}).thenSucceed();
}
// A glass cable can carry eight channels, so the ninth device must be left without a channel.
@GameTest(template = "network_core", timeoutTicks = 100)
public static void channelLimitDeactivatesOverflowDevice(GameTestHelper helper) {
@@ -211,6 +324,41 @@ public class NetworkCoreTests {
return helper.assertTileEntityPresent(TileDrive.class, DRIVE_LABEL);
}
private static void synchronizePlayerDefault(GameTestHelper helper, EntityPlayer player,
ControllerAnimation animation) {
try {
new PacketValueConfig(PacketValueConfig.CONTROLLER_ANIMATION_DEFAULT, animation.name())
.serverPacketData(null, null, player);
} catch (IOException e) {
throw new AssertionError("Player controller animation default should synchronize", e);
}
helper.assertEquals(
animation,
TileController.getPlayerDefaultAnimation(player),
"Player controller animation default should be synchronized");
}
private static TileController placeController(GameTestHelper helper, String label, FakePlayer player) {
TestPos position = helper.absolute(label);
helper.destroyBlock(label);
ItemStack stack = AEApi.instance().definitions().blocks().controller().maybeStack(1).get();
helper.assertTrue(
((ItemBlock) stack.getItem()).placeBlockAt(
stack,
player,
helper.getWorld(),
position.x(),
position.y(),
position.z(),
ForgeDirection.UP.ordinal(),
0.5F,
0.5F,
0.5F,
0),
"Controller item placement should succeed");
return helper.assertTileEntityPresent(TileController.class, label);
}
private static void installCableLine(GameTestHelper helper, String... cableRoles) {
for (String cableRole : cableRoles) {
placeCable(helper, cableRole);
+48 -5
View File
@@ -14,6 +14,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.util.ForgeDirection;
import org.apache.logging.log4j.Level;
@@ -34,6 +35,7 @@ import appeng.api.util.DimensionalCoord;
import appeng.core.AEConfig;
import appeng.core.AELog;
import appeng.core.features.AEFeature;
import appeng.core.settings.ControllerAnimation;
import appeng.core.stats.Achievements;
import appeng.me.pathfinding.AdHocChannelUpdater;
import appeng.me.pathfinding.ChannelFinalizer;
@@ -44,6 +46,8 @@ import appeng.util.Platform;
public class PathGridCache implements IPathingGrid {
private static final String CONTROLLER_ANIMATION_KEY = "controllerAnimation";
private final Set<TileController> controllers = new HashSet<>();
private final Set<IGridNode> nodesNeedingChannels = new HashSet<>();
private final Set<IGridNode> cannotCarryCompressedNodes = new HashSet<>();
@@ -55,6 +59,7 @@ public class PathGridCache implements IPathingGrid {
private boolean updateNetwork = true;
private boolean booting = false;
private ControllerState controllerState = ControllerState.NO_CONTROLLER;
private ControllerAnimation controllerAnimation;
private int lastChannels = 0;
public PathGridCache(final IGrid g) {
@@ -126,6 +131,7 @@ public class PathGridCache implements IPathingGrid {
if (machine instanceof TileController) {
this.controllers.remove(machine);
if (this.controllers.isEmpty()) this.controllerAnimation = null;
this.recalculateControllerNextTick = true;
}
@@ -148,8 +154,13 @@ public class PathGridCache implements IPathingGrid {
AELog.printStackTrace(Level.INFO);
}
if (machine instanceof TileController) {
this.controllers.add((TileController) machine);
if (machine instanceof TileController controller) {
if (this.controllerAnimation == null) {
this.controllerAnimation = controller.getControllerAnimation();
} else {
controller.setControllerAnimation(this.controllerAnimation);
}
this.controllers.add(controller);
this.recalculateControllerNextTick = true;
}
@@ -165,13 +176,45 @@ public class PathGridCache implements IPathingGrid {
}
@Override
public void onSplit(final IGridStorage storageB) {}
public void onSplit(final IGridStorage storageB) {
if (this.controllerAnimation != null) {
storageB.dataObject().setString(CONTROLLER_ANIMATION_KEY, this.controllerAnimation.name());
}
}
@Override
public void onJoin(final IGridStorage storageB) {}
public void onJoin(final IGridStorage storageB) {
if (this.controllerAnimation != null || storageB == null) return;
final NBTTagCompound data = storageB.dataObject();
if (data.hasKey(CONTROLLER_ANIMATION_KEY)) {
this.controllerAnimation = ControllerAnimation.fromName(data.getString(CONTROLLER_ANIMATION_KEY));
}
}
@Override
public void populateGridStorage(final IGridStorage storage) {}
public void populateGridStorage(final IGridStorage storage) {
if (this.controllerAnimation != null) {
storage.dataObject().setString(CONTROLLER_ANIMATION_KEY, this.controllerAnimation.name());
} else {
storage.dataObject().removeTag(CONTROLLER_ANIMATION_KEY);
}
}
public ControllerAnimation getControllerAnimation() {
return this.controllerAnimation == null ? ControllerAnimation.ORIGINAL_RAINBOW : this.controllerAnimation;
}
public void cycleControllerAnimation(final boolean backwards) {
final ControllerAnimation animation = this.getControllerAnimation();
this.setControllerAnimation(backwards ? animation.previous() : animation.next());
}
public void setControllerAnimation(final ControllerAnimation animation) {
this.controllerAnimation = animation;
for (final TileController controller : this.controllers) {
controller.setControllerAnimation(animation);
}
}
private void recalcController() {
this.recalculateControllerNextTick = false;
@@ -31,6 +31,7 @@ import appeng.api.networking.events.MENetworkPowerStorage.PowerEventType;
import appeng.api.networking.pathing.ControllerState;
import appeng.api.util.AECableType;
import appeng.api.util.AEColor;
import appeng.core.settings.ControllerAnimation;
import appeng.me.GridAccessException;
import appeng.tile.TileEvent;
import appeng.tile.events.TileEventType;
@@ -44,9 +45,12 @@ public class TileController extends AENetworkPowerTile implements IColorableTile
private static final IInventory NULL_INVENTORY = new AppEngInternalInventory(null, 0);
private static final int[] ACCESSIBLE_SLOTS_BY_SIDE = {};
private static final String ANIMATION_NBT_KEY = "controllerAnimation";
private static final String PLAYER_DEFAULT_NBT_KEY = "ae2.controllerAnimationDefault";
private boolean isValid = false;
private AEColor paintedColor = AEColor.Transparent;
private ControllerAnimation controllerAnimation = ControllerAnimation.ORIGINAL_RAINBOW;
public TileController() {
this.setInternalMaxPower(8000);
@@ -63,14 +67,17 @@ public class TileController extends AENetworkPowerTile implements IColorableTile
@TileEvent(TileEventType.NETWORK_WRITE)
public void writeToStream_TileController(final ByteBuf data) {
data.writeByte(this.paintedColor.ordinal());
data.writeByte(this.controllerAnimation.ordinal());
}
@TileEvent(TileEventType.NETWORK_READ)
public boolean readFromStream_TileController(final ByteBuf data) {
final AEColor oldPaintedColor = this.paintedColor;
final ControllerAnimation oldAnimation = this.controllerAnimation;
this.paintedColor = AEColor.fromOrdinal(data.readByte());
this.controllerAnimation = ControllerAnimation.fromOrdinal(data.readByte());
this.getProxy().setColor(this.paintedColor);
return oldPaintedColor != this.paintedColor;
return oldPaintedColor != this.paintedColor || oldAnimation != this.controllerAnimation;
}
@TileEvent(TileEventType.WORLD_NBT_READ)
@@ -79,11 +86,43 @@ public class TileController extends AENetworkPowerTile implements IColorableTile
this.paintedColor = AEColor.fromOrdinal(data.getByte("paintedColor"));
this.getProxy().setColor(this.paintedColor);
}
if (data.hasKey(ANIMATION_NBT_KEY)) {
this.controllerAnimation = ControllerAnimation.fromName(data.getString(ANIMATION_NBT_KEY));
}
}
@TileEvent(TileEventType.WORLD_NBT_WRITE)
public void writeToNBT_TileController(final NBTTagCompound data) {
data.setByte("paintedColor", (byte) this.paintedColor.ordinal());
data.setString(ANIMATION_NBT_KEY, this.controllerAnimation.name());
}
@Override
public void onPlacement(final ItemStack stack, final EntityPlayer player, final int side) {
super.onPlacement(stack, player, side);
if (!this.worldObj.isRemote && player != null) {
this.setControllerAnimation(getPlayerDefaultAnimation(player));
}
}
public static ControllerAnimation getPlayerDefaultAnimation(final EntityPlayer player) {
return ControllerAnimation.fromOrdinal(player.getEntityData().getByte(PLAYER_DEFAULT_NBT_KEY));
}
public static void setPlayerDefaultAnimation(final EntityPlayer player, final String animation) {
player.getEntityData()
.setByte(PLAYER_DEFAULT_NBT_KEY, (byte) ControllerAnimation.fromName(animation).ordinal());
}
public ControllerAnimation getControllerAnimation() {
return this.controllerAnimation;
}
public void setControllerAnimation(final ControllerAnimation animation) {
if (this.controllerAnimation == animation) return;
this.controllerAnimation = animation;
this.markDirty();
this.markForUpdate();
}
@Override
@@ -289,6 +289,14 @@ gui.appliedenergistics2.NetworkTool=Network Tool
gui.appliedenergistics2.AdvancedNetworkTool=Advanced Network Tool
gui.appliedenergistics2.CraftingDiagnostics=Crafting Diagnostics
gui.appliedenergistics2.CraftingDiagnosticsHint=Enable or disable crafting diagnostics collection for this network.
gui.appliedenergistics2.ControllerAnimation.ORIGINAL_RAINBOW=Original Rainbow
gui.appliedenergistics2.ControllerAnimation.WAVE=Wave
gui.appliedenergistics2.ControllerAnimation.COUNTERFLOW=Counterflow
gui.appliedenergistics2.ControllerAnimation.CORE_RIPPLE=Core Ripple
gui.appliedenergistics2.ControllerAnimation.BREATHING=Breathing
gui.appliedenergistics2.ControllerAnimation.SOFT_INTERFERENCE=Soft Interference
gui.appliedenergistics2.ControllerAnimation.SINGULARITY=Singularity
gui.appliedenergistics2.ControllerAnimation.CIRCUIT_TRACE=Circuit Trace
gui.appliedenergistics2.ItemFlowTracking=Item Flow Tracking
gui.appliedenergistics2.ItemFlowTrackingHint=Enable or disable item flow statistics collection for this network.
gui.appliedenergistics2.PowerUsageRate=Energy Usage
@@ -841,6 +849,11 @@ gui.tooltips.appliedenergistics2.AdvancedLevelEmitterSlotInvert=Invert Redstone
gui.tooltips.appliedenergistics2.PinsSection=Pins section
gui.tooltips.appliedenergistics2.PinsSectionActive=§6LMB§8 - §7Add player row\n§6RMB§8 - §7Remove player row\n§6CTRL + LMB§8 - §7Add crafting row\n§6CTRL + RMB§8 - §7Remove crafting row\n§6SHIFT + RMB§8 - §7Unpin§r
gui.tooltips.appliedenergistics2.PinsSectionHint=Hold §6ALT§7 for keybinds
gui.tooltips.appliedenergistics2.ControllerAnimation=Controller Animation
gui.tooltips.appliedenergistics2.ControllerAnimationActive=%s\n§6LMB§8 - §7Next animation\n§6RMB§8 - §7Previous animation\n§6SHIFT + LMB§8 - §7Apply default animation§r
gui.tooltips.appliedenergistics2.ControllerAnimationHint=%s\n§7Hold §6ALT§7 for keybinds
gui.tooltips.appliedenergistics2.ControllerAnimationStatus=§7%s
gui.tooltips.appliedenergistics2.ControllerAnimationStatusDefault=§7%s §a(Default)
gui.tooltips.appliedenergistics2.scheduledreason.SOMETHING_STUCK=§eTarget is full or can't accept the ingredients
gui.tooltips.appliedenergistics2.scheduledreason.BLOCKING_MODE=§eBlocking Mode
@@ -1288,7 +1301,7 @@ key.pick_block.desc=AE2 Pick Block
key.toggle_focus.desc=Toggle search box focus
key.search_connected_inventories.desc=Search network inventories for an item
key.locate_item_flow.desc=Highlight recent item flow for hovered item
key.cycle_controller_animation.desc=Cycle controller animation
key.cycle_controller_animation.desc=Cycle default controller animation
key.container_interaction.desc=Container Item Interaction
key.wireless_extra_action.desc=Wireless Extra Action
key.wireless_mode_switch.desc=Wireless Mode Switch