diff --git a/dependencies.gradle b/dependencies.gradle index e908852c3e6..394dd851284 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -10,6 +10,12 @@ dependencies { // Configuration jarJar(modApi(forge.configuration.get())) + // Math Parser + compileOnly(libs.evalEx.get()) + + // MUI + jarJar(modImplementation(forge.mui.get())) + // Mixin (& Extras) annotationProcessor(variantOf(libs.mixin) { classifier("processor") }) compileOnly(annotationProcessor(forge.mixinExtras.common.get())) @@ -119,4 +125,8 @@ dependencies { modExtraLocalRuntime(forge.ponder) modExtraLocalRuntime(variantOf(forge.create) { classifier("slim") }) modExtraLocalRuntime(forge.flywheel.forge) + + modLocalRuntime(forge.curios) + + } diff --git a/docs/content/Development/MUI2/Layout_MainAxisAlignments.png b/docs/content/Development/MUI2/Layout_MainAxisAlignments.png new file mode 100644 index 00000000000..308916e9eb6 Binary files /dev/null and b/docs/content/Development/MUI2/Layout_MainAxisAlignments.png differ diff --git a/docs/content/Development/MUI2/Syncing/Sync-Basics.md b/docs/content/Development/MUI2/Syncing/Sync-Basics.md new file mode 100644 index 00000000000..12cd19e6337 --- /dev/null +++ b/docs/content/Development/MUI2/Syncing/Sync-Basics.md @@ -0,0 +1,268 @@ +# Sync Basics + +## Basics of Syncing +To display dynamic values on the client, you have to send the data from the server to the client. When making UIs, it is very important to keep track of if and how your data is being synced to the client. There are a few ways to do so, which will be discussed below. + +When opening a UI, a copy of the UI is created both on the server and on the client. It is important to note here that the server's copy will have access to most everything about e.g. the machine, block state, the world etc., but the client's copy will not. + +To sync this data back and forth, you need to use `SyncHandler`s. These will send your data from the server to the client when it updates. + +Because of this, you cannot just use values you create SyncHandlers for directly in the client. An example: + +```java + +var tickSyncValue = new IntSyncValue(() -> this.ticks, (newValue) -> this.ticks = newValue); +for(int i=0;i)` - Queries the supplier every frame to retrieve the component to display +- `new DynamicDrawable(Supplier)` - Queries the supplier every frame to retrieve the drawable to display + + +!!! Note + To convert IKeys or Drawables to Widgets, you need to chain `.asWidget()` + +```java +public class MuiTestMachine extends MetaMachine implements IMuiMachine { + + public int ticks = 0; + + public MuiTestMachine(BlockEntityCreationInfo info) { + super(info); + this.subscribeServerTick(() -> ticks++); + } + + @Override + public ModularPanel buildUI(PosGuiData data, PanelSyncManager syncManager, UISettings settings) { + var panel = GTGuis.createPanel(this, 176, 168); + var tickSyncValue = new IntSyncValue(() -> this.ticks, (newValue) -> this.ticks = newValue); + syncManager.syncValue("tickSyncValue", tickSyncValue); + + var column = Flow.column(); + + column.child(IKey.dynamic(() -> Component.literal("Ticks: " + this.ticks)) // note that this is a Supplier instead of a Component + .asWidget() + .margin(4)); + + column.child( + new DynamicDrawable(() -> { // note that this is a Supplier instead of an IDrawable + if (ticks % 40 < 20) { // flip every second + return GTGuiTextures.BUTTON_FLUID_OUTPUT; + } else { + return GTGuiTextures.BUTTON_ITEM_OUTPUT; + } + }) + .asWidget() + .background(GTGuiTextures.BACKGROUND_STEEL) + ); + + panel.child(column); + + return panel; + } +} +``` + +Here, we create a basic `SyncValue` for an integer. This takes a `Supplier` and a `Consumer`, more commonly known as a getter and a setter. Generally speaking, `SyncValue`s will take a `Supplier` and `Consumer` of the type of value they are syncing. + +If the value returned by the getter changed on the server, the value gets serialized and sent to the client by the `SyncManager`. The `SyncHandler`'s value can always be manually updated, for example to do client-to-server syncing. + +Then, the value on the client (being set every time the server sends an update) is retrieved every frame by the lambdas used in the dynamic widgets. + +If you want to update the value from the client, you can call `syncValue.setValue()` on the client. This will also update the value on the server side. + +## Method 2: DynamicLinkedSyncHandler + +This method is great for widgets whose structure and layout can change depending on your synced values. + +```java +public class MuiTestMachine extends MetaMachine implements IMuiMachine { + + public int ticks = 0; + + public MuiTestMachine(BlockEntityCreationInfo info) { + super(info); + this.subscribeServerTick(() -> ticks++); + } + + @Override + public ModularPanel buildUI(PosGuiData data, PanelSyncManager syncManager, UISettings settings) { + var panel = GTGuis.createPanel(this, 176, 168); + var tickSyncValue = new IntSyncValue(() -> this.ticks, (newValue) -> this.ticks = newValue); + syncManager.syncValue("tickSyncValue", tickSyncValue); + + DynamicLinkedSyncHandler dynamicLinkedSyncHandler = new DynamicLinkedSyncHandler<>(tickSyncValue) + .widgetProvider((widgetSyncManager, intSyncHandler) -> { + var list = new ListWidget<>() + .widthRel(1) + .coverChildrenHeight() + .crossAxisAlignment(Alignment.CrossAxis.START); + int tickValue = intSyncHandler.getValue(); // It is also possible to just reference this.ticks directly + int amountOfItems = 1 + (tickValue % 200) / 20; + for (int i = 0; i < amountOfItems; i++) { + list.child(IKey.str("Value nr. " + (i + 1)).asWidget()); // No need for IKey.dynamic since we have the value as a variable here, inside the lambda + } + return list; + }); + + panel.child(new DynamicSyncedWidget<>() + .widthRel(1) + .coverChildrenHeight() + .syncHandler(dynamicLinkedSyncHandler) + .padding(3)); + + return panel; + } +} +``` + +This method works in three steps: + +The first step is creating a `SyncHandler` and registering it to the `PanelSyncManager`. +The second step is creating a `DynamicLinkedSyncHandler` based on the first `SyncHandler`. This is effectively a wrapper class to provide your widget whenever your initial `SyncHandler` updates. +The third step is creating a `DynamicSyncedWidget` with that `DynamicLinkedSyncHandler` as its `SyncHandler`. + +This effectively lets us create a new "version" of the widget whenever our value (in this case the `ticks` int) changes. Furthermore, in this example we have the actual values of the things we want to sync when constructing our widget tree on the client, allowing for much greater customization. + + +!!! note + For even more complex systems where you need to dynamically register sync handlers within the `DynamicLinkedSyncHandler`'s `.widgetProvider(...)`, this can be done by calling `.getOrCreateSyncHandler(...)` on the `widgetSyncManager` parameter of the lambda. + +## Method 3: Types that take SyncHandlers +There are some widgets that have built in support for working directly with SyncHandlers. + +```java +public class MuiTestMachine extends MetaMachine implements IMuiMachine { + + public boolean buttonPressed = false; + + public MuiTestMachine(BlockEntityCreationInfo info) { + super(info); + } + + @Override + public ModularPanel buildUI(PosGuiData data, PanelSyncManager syncManager, UISettings settings) { + var panel = GTGuis.createPanel(this, 176, 168); + + var column = Flow.column().paddingTop(3); + + column.child( + IKey.dynamic(() -> Component.literal("Pressed: " + this.buttonPressed)) + .asWidget()); + + var buttonSyncValue = new BooleanSyncValue(() -> this.buttonPressed, (newValue) -> this.buttonPressed = newValue); + column.child(new ToggleButton().value(buttonSyncValue)); + + panel.child(column); + + return panel; + } +} +``` + +Note that in this case, the ToggleButton takes care of registering the SyncValue for us, so we do not register it to the syncManager ourselves. This method is great for simple functions using widgets that support it. + +A few examples of this would be: + +- `new ToggleButton().value(BooleanSyncValue)` - A ToggleButton that affects the Boolean sync value +- `new TextFieldWidget().value(StringSyncValue)` - A TextField that updates the String sync value +- `new ProgressWidget().value(DoubleSyncValue)` - A ProgressWidget (e.g. bar) that shows progress, can also be constructed with `new ProgressWidget().progress(() -> this.progress)` +- `new SliderWidget().value(DoubleSyncValue)` - A SliderWidget that updates the Double sync value + +## Method 4: Manually notifying DynamicSyncHandlers +This method is useful when your custom widget needs complex data coming in, like through multiple sync handlers. + +```java +public class MuiTestMachine extends MetaMachine implements IMuiMachine { + + public int rows = 0; + public int columns = 0; + public int counter = 0; + + public MuiTestMachine(BlockEntityCreationInfo info) { + super(info); + this.subscribeServerTick(() -> { + counter += 1; + if (counter % 20 == 0) { + rows = (rows + 1) % 10; + } + if (counter % 15 == 0) { + columns = (columns + 1) % 10; + } + }); + } + + @Override + public ModularPanel buildUI(PosGuiData data, PanelSyncManager syncManager, UISettings settings) { + var panel = GTGuis.createPanel(this, 200, 200); + + var rowsSyncValue = new IntSyncValue(() -> this.rows, (newValue) -> this.rows = newValue); + syncManager.syncValue("rows", rowsSyncValue); + + var columnsSyncValue = new IntSyncValue(() -> this.columns, (newValue) -> this.columns = newValue); + syncManager.syncValue("columns", columnsSyncValue); + + DynamicSyncHandler gridWidgetHandler = new DynamicSyncHandler().widgetProvider((slotsSyncManger, buffer) -> { + + Flow grid = Flow.column().width(200); + for (int rowNr = 0; rowNr < this.rows; rowNr++) { + Flow row = Flow.row(); + for (int columnNr = 0; columnNr < this.columns; columnNr++) { + row.child(IKey.str(rowNr + ", " + columnNr).asWidget().width(20)); + } + grid.child(row); + } + return grid; + }); + + rowsSyncValue.setChangeListener(() -> { + gridWidgetHandler.notifyUpdate(buffer -> {}); + }); + columnsSyncValue.setChangeListener(() -> { + gridWidgetHandler.notifyUpdate(buffer -> {}); + }); + + panel.child(new DynamicSyncedWidget<>().syncHandler(gridWidgetHandler)); + return panel; + } +} +``` + +This is very similar to method 2, but instead of a `DynamicLinkedSyncHandler` we use a normal `DynamicSyncHandler` where we have to manually let it know when to update. We do this in the change listener of our two `SyncValue`s by calling notifyUpdate. + +Do note there's also a buffer where you can serialize data to, to be consumed in the `.widgetProvider(...)` in the spot where in a `DynamicLinkedSyncHandler` our syncValue would be. It is usually not needed to put anything in this buffer. + +## Other sync information + +### SyncHandler panel separation + +SyncValues are separated across panels. So if you do `mainPanelSyncManager.syncValue("rows", rowsSyncValue);` in one panel, you can't just call `popupSyncManager.getSyncHandlerFromMapKey("rows:0")`. +You can, however, call `syncManager.getModularSyncManager().getPanelSyncManager("panel name here").getSyncHandlerFromMapKey("rows:0");`. + +### Value.Dynamic +Sometimes you need to quickly create a Value for something that already exists client side. For this you can use `new [Type]Value.Dynamic(...)`. +For example, if you have a client-only value that's affected by a button, you could do +`panel.child(new ToggleButton().value(new BoolValue.Dynamic(() -> this.toggled, (newValue) -> this.toggled = newValue)));` + +Another reason to use a dynamic value is if you want to change the type of a variable, e.g. `.value(new DoubleValue.Dynamic(() -> (double) this.x, val -> this.x = (double) val)` where x is an int. + +The third reason is if you want to use a `SyncHandler` in two separate widgets that would both auto-register it. +``` + var boolSyncValue = new BooleanSyncValue(() -> this.toggled, (newValue) -> this.toggled = newValue); + panel.child(new ToggleButton().value(boolSyncValue)); + panel.child(new ToggleButton().value(BoolValue.wrap(boolSyncValue)).left(32)); +``` +Without the wrap around the second boolSyncValue call, it would complain of registration of an already registered SyncValue. + diff --git a/docs/content/Development/MUI2/Syncing/Synced-Actions.md b/docs/content/Development/MUI2/Syncing/Synced-Actions.md new file mode 100644 index 00000000000..f774ffd201a --- /dev/null +++ b/docs/content/Development/MUI2/Syncing/Synced-Actions.md @@ -0,0 +1,48 @@ +# Synced Actions + +```java +public class MuiTestMachine extends MetaMachine implements IMuiMachine { + + public MuiTestMachine(BlockEntityCreationInfo info) { + super(info); + } + + public int number = 0; + + @Override + public ModularPanel buildUI(PosGuiData data, PanelSyncManager syncManager, UISettings settings) { + var panel = GTGuis.createPanel(this, 176, 168); + + var numberSyncValue = new IntSyncValue(() -> this.number, (newValue) -> this.number = newValue); + syncManager.syncValue("number", numberSyncValue); + + syncManager.registerServerSyncedAction("randomButtonPressed", (packet) -> { + this.number = getLevel().getRandom().nextInt(); + }); + + Column contents = new Column(); + contents.child(IKey.dynamic(() -> Component.literal("Number: " + number)) + .asWidget() + .width(100) + .height(16) + .margin(4)); + + contents.child(new ButtonWidget<>() + .onMousePressed((x, y, button) -> { + if (button == 0) { + syncManager.callSyncedAction("randomButtonPressed"); + } + return true; + }) + .size(16)); + return panel.child(contents); + } +} + +``` + +Synced actions are useful when you need a client-side input (e.g. a button press) to trigger an action on the server. + +In this case we create a synced action called `randomButtonPressed`, and when the button is pressed on the client, the `randomButtonPressed` signal is sent to the server and the relevant action is executed. + +If you need to pass other data with your action, you can pass a `(packet) -> {...}` as second argument to `callSyncedAction` and serialize your data there, and then deserialize it from the `packet` argument in the synced action definition. \ No newline at end of file diff --git a/docs/content/Development/MUI2/Syncing/index.md b/docs/content/Development/MUI2/Syncing/index.md new file mode 100644 index 00000000000..ed0a1fb6e5f --- /dev/null +++ b/docs/content/Development/MUI2/Syncing/index.md @@ -0,0 +1 @@ +Syncing is the concept of synchronising data between client and server. This folder will contain files relevant to setting up syncing on your UIs. \ No newline at end of file diff --git a/docs/content/Development/MUI2/Test-Machine.md b/docs/content/Development/MUI2/Test-Machine.md new file mode 100644 index 00000000000..63d3a9135c5 --- /dev/null +++ b/docs/content/Development/MUI2/Test-Machine.md @@ -0,0 +1,35 @@ +# Making a MUI2 Test Machine +To make a basic machine to test your UI, simply create the following class: + +```java title="MultiMachines.java" +public class MuiTestMachine extends MetaMachine implements IMuiMachine { + + public MuiTestMachine(BlockEntityCreationInfo info) { + super(info); + } + + @Override + public ModularPanel buildUI(PosGuiData data, PanelSyncManager syncManager, UISettings settings) { + var panel = GTGuis.createPanel(this, 176, 168); + // Do stuff with your panel here, add children, etc. + // For example: + panel.child(IKey.str("Test machine") + .asWidget() + .margin(4)); + + return panel; + } +} +``` + +and in your machines definitions class, add the following entry: + +```java + public static final MachineDefinition MUI_TEST_MACHINE = REGISTRATE + .machine("mui_test", MuiTestMachine::new) + .model(createOverlayCasingMachineModel(GTCEu.id("block/casings/solid/machine_casing_clean_stainless_steel"), + GTCEu.id("block/machine/part/computer_monitor"))) + .register(); +``` + +Make sure to run datagen after making the initial machine to register the lang keys, model, etc. Running datagen afterward for UI changes is not required. \ No newline at end of file diff --git a/docs/content/Development/MUI2/Widget-Layout.md b/docs/content/Development/MUI2/Widget-Layout.md new file mode 100644 index 00000000000..17bed127395 --- /dev/null +++ b/docs/content/Development/MUI2/Widget-Layout.md @@ -0,0 +1,189 @@ +# Widget Layout, Sizing and Positioning + +Each widget has several builder setter methods for position and size. They all come from the `IPositioned` interface. + + +## Coordinate system +- Widget coordinates are local to the widget; (0, 0) is the top-left corner of the widget. +- Positions are relative to the parent by default. + +## Sizing + +- `width(int)` sets the widget width in pixels +- `widthRel(float)` sets the widget width relative to its parent (e.g. if the parent is 120 px wide and we + call `widthRel(0.5f)`, our widget will be 60 px wide) +- `height(int)` and `heightRel(float)` work analogous to previous methods +- `size(int width, int height)` is equivalent to `.width(width).height(height)` +- `size(int val)` is equivalent to `.width(val).height(val)` +- `sizeRel(float width, float height)` and `sizeRel(float val)` work analogous to previous methods +- `fullWidth()` and `fullHeight()` are shortcuts for `widthRel(1f)` and `heightRel(1f)` respectively +- `full()` combines the previous two methods +- `coverChildrenWidth()` makes the widget width wrap tightly around its children +- `coverChildrenHeight()` works analogous to previous method +- `coverChildren()` wraps width and height tightly +- `expanded()` is only useful for children of `Row` and `Column` widgets. It will make the widget expand as much as + possible in the widgets axis (width in row and height in column) + +## Positioning + +We can set position on four different points, two for each axis. `left()`, `right()`, `top()` and `bottom()`. +To understand what they are doing take a look at the following picture: + +![grafik](https://github.com/CleanroomMC/ModularUI/assets/45517902/ab173431-1509-414c-8db4-4545c985a9bd) + +As you can see the methods are fairly self-explanatory. Each of those methods has multiple variants much like `width()` +and `widthRel()`. Only methods for `left()` will be listed here. + +- `left(int x)` sets the x position in pixels relative to its parent +- `leftRel(float x)` sets the x position relative to its parent (f.e. 0.5f will center the widget) +- `leftRelOffset(float val, int offset)` is the same as `leftRel(float x)`, but also adds an `offset` in pixels after the calculation +- `leftRelAnchor(float val, float anchor)` is the same as `leftRel(float x)`, but with a different anchor + (see [Anchor](#anchor)) +- `leftRel(float val, int offset, float anchor)` combines `leftRelOffset()` and `leftRelAnchor()` +- `left(DoubleSupplier val, Measure measure)` is like `left()` and `leftRel()`, but with a dynamic value. Note that the + supplier is only evaluated during resizing. You can't use it for animating widgets. +- `leftRelOffset(DoubleSupplier val, int offset)` is like `leftRelOffset(float val, int offset)` with a dynamic value +- `leftRelAnchor(DoubleSupplier val, float anchor)` is like `leftRelAnchor(float val, float anchor)` with a dynamic + value +- `leftRel(DoubleSupplier val, int offset, float anchor)` combines the two methods above + +All the above variants also exist for `right()`, `top()` and `bottom()`. +Additionally, there is + +- `pos(int x, int y)` combines `left(int x)` and `top(int y)` +- `posRel(float x, float y)` combines `leftRel(float x)` and `topRel(float y)` +- `posRel(Alignment a)` calls `posRel(float x, float y)` using a specific alignment enum value +- `horizontalCenter()` is short for `leftRel(0.5f)` +- `verticalCenter()` is short for `topRel(0.5f)` +- `center()` is short for `posRel(Alignment.Center)` +## Anchor + +The anchor is the point of the widget at which the widget will be positioned with the relative value. The following +picture should make this clear. In the picture `leftRelAnchor(0.5f, 0.3f)` is called. + +![anchor.png](https://raw.githubusercontent.com/CleanroomMC/Website/refs/heads/main/docs/wiki/modularui/anchor.png) + +Here the anchor is placed at `0.3f`, which is about a third of the widget. +And that anchor is positioned at `0.5f` of the parent widget (the center). +Try imagining what happens with different anchor values and play around with it by yourself. + +If we had called `leftRel(float val, int offset, float anchor)`, then the offset would be added after the anchor +and relative position calculation. + +## Combining Size and Position + +You can call multiple different position and size methods, but you should be aware of its effects and limitations. + +Each axis (x and y) has three setters (x has `left()`, `right()` and `width()`, y has `top()`, `bottom()` and `height()`) +without including all the variations. + +!!! Note + You can call at most two setters for each axis, since with two properties set the last one can always be calculated. + +For example of you call `left()` and `right()` then the width can be calculated with `right - left`. +Setting all three properties for an axis will remove one of the other properties and log an info message. + +!!! Note + By default, the position is (0, 0) and the size is 18x18 in pixels for most widgets. + +## Changing the relative Parent + +By default, the size and position are calculated relative to the widget's parent, but that can be changed with +`relative(Area)`, `relative(IGuiElement)` and `relativeToScreen()`. +The parent of all panels is by default the screen. + +!!! Warning + Changing the relative widget might cause some unexpected results in some edge cases. Please notify us if you run + into one of those. + + +## Flow layout (Row / Column) +`Flow` is the core layout widget for arranging children along one axis. + +- `Flow.row()` lays out children **left-to-right** (X axis). +- `Flow.column()` lays out children **top-to-bottom** (Y axis). +- `mainAxisAlignment(...)` controls how children are distributed on the main axis: + - `START`, `CENTER`, `END`, `SPACE_BETWEEN`, `SPACE_AROUND` + - e.g. `Flow.row().mainAxisAlignment(Alignment.MainAxis.CENTER)` centers the row's children horizontally, given that it has a set width +- `crossAxisAlignment(...)` controls alignment on the perpendicular axis: + - `START`, `CENTER`, `END` + - e.g. `Flow.row().crossAxisAlignment(Alignment.CrossAxis.CENTER)` centers the row's children vertically, given that it has a set height +- `childPadding(int)` adds fixed spacing between children. +- `coverChildren()` / `coverChildrenWidth()` / `coverChildrenHeight()` sizes the flow to fit its children. +- `collapseDisabledChild()` does not consider disabled children during position calculations. + - This is useful when the enabled state of children changes dynamically. +- `reverseLayout(bool)` reverses the order that children are drawn. + +Notes: + +- Centering (main or cross axis) requires the flow to have a known size on that axis. If you want a row to center its children horizontally, give it a width (e.g. `widthRel(1f)` or `width(120)`). +- By default, a `Flow` is `full()`, which means they take up as much space as their parents size. + +Here is how all the MainAxisAlignments apply to widgets: + +![MainAxisAlignments](./Layout_MainAxisAlignments.png) + + +## Centering widgets +There are two common ways to center things: + +1) Center a widget within its parent (positioning) + +- `widget.center()` or `widget.posRel(Alignment.Center)` +- `widget.horizontalCenter()` or `widget.verticalCenter()` + +2) Center children inside a Row/Column (layout) + +- `Flow.row().mainAxisAlignment(Alignment.MainAxis.CENTER)` centers children along the flow's direction. +- `Flow.column().crossAxisAlignment(Alignment.CrossAxis.CENTER)` centers children perpendicular to the flow's direction. +- Remember to give the row/column a size on that axis (e.g. `widthRel(1f)` for a row). + +## Margin vs padding +Spacing is handled via two different concepts: + +- Margin: space outside a widget. Layouts (like `Flow`) include margins when positioning children. + - `marginTop(px)`, `marginBottom(px)`, `marginLeft(px)`, `marginRight(px)` set the padding in pixels for the directions + - `margin(all)`, `margin(horizontal, vertical)`, `margin(left, right, top, bottom)` are shortcuts for the respective methods +- Padding: space inside a widget. It reduces the content area and affects how children are placed. + - `paddingTop(px)`, `paddingBottom(px)`, `paddingLeft(px)`, `paddingRight(px)` sets the margin in pixels for the directions + - `padding(all)`, `padding(horizontal, vertical)`, `padding(left, right, top, bottom)` are shortcuts for the respective methods + +## Examples + +### Simple centered panel with a row of buttons +```java +ModularPanel panel = new ModularPanel("example") + .size(176, 168); + +panel.child(new ParentWidget<>() + .size(90, 63) + .align(Alignment.CENTER) + .child(Flow.row() + .coverChildren() + .childPadding(4) + .child(new ButtonWidget<>().size(16)) + .child(new ButtonWidget<>().size(16)) + .child(new ButtonWidget<>().size(16)))); +``` + +### Column with padding and left-aligned content +```java +Flow column = Flow.column() + .widthRel(1f) + .padding(10) + .crossAxisAlignment(Alignment.CrossAxis.START) + .child(new TextWidget<>(IKey.str("Title")).marginBottom(4)) + .child(new TextWidget<>(IKey.str("Body"))); +``` + +### Slot grid using absolute positioning +```java +ParentWidget slots = new ParentWidget<>(); +for (int y = 0; y < rows; y++) { + for (int x = 0; x < cols; x++) { + slots.child(new ItemSlot() + .left(18 * x) + .top(18 * y)); + } +} +``` diff --git a/docs/content/Development/MUI2/index.md b/docs/content/Development/MUI2/index.md new file mode 100644 index 00000000000..f06372b41a0 --- /dev/null +++ b/docs/content/Development/MUI2/index.md @@ -0,0 +1,5 @@ +# ModularUI 2 +ModularUI 2 is the UI library used in GTM starting from 8.0.0, and is the successor to LDLib UI. +From ModularUI 1.12's github: + +With ModularUI you can build GUIs fast by adding Widgets to panels with layout widgets, so you don't have to calculate positions and sizes yourself. ModularUI is very dynamic and allows for very complicated client-server synced GUIs. \ No newline at end of file diff --git a/docs/content/Modpacks/Examples/Example_Coil_Multiblock.md b/docs/content/Modpacks/Examples/Example_Coil_Multiblock.md new file mode 100644 index 00000000000..09fa577b996 --- /dev/null +++ b/docs/content/Modpacks/Examples/Example_Coil_Multiblock.md @@ -0,0 +1,102 @@ +--- +title: "Example Coil Multiblock" +--- + +### Superheated Pyrolyzing Oven Multiblock (by Phoenixvine) + + +Below is an example of a multiblock using the CoilWorkableElectricMultiblockMachine class and the pyrolyseOvenOverclock machine logic. + +### Multiblock +=== "JavaScript" + ```js title="superheated_pyrolyzing_oven_multiblock.js" + // In order to use multiblock logic extending beyond the normal WorkableElectricMultiblockMachine, (This is the multiblock type used by default for kubejs) you need to load a class. Coil multiblocks such as the Electric Blast Furnace, Pyrolyse Oven, and the Cracker use this class. + const CoilWorkableElectricMultiblockMachine = Java.loadClass("com.gregtechceu.gtceu.api.machine.multiblock.CoilWorkableElectricMultiblockMachine") + + GTCEuStartupEvents.registry('gtceu:machine', event => { + event.create("superheated_pyrolyzing_oven", "multiblock") + .machine((holder) => new CoilWorkableElectricMultiblockMachine(holder)) + .rotationState(RotationState.NON_Y_AXIS) + .recipeTypes('pyrolyse_oven') + .recipeModifiers( + [ + GTRecipeModifiers.PARALLEL_HATCH, + (machine, recipe) => GTRecipeModifiers.pyrolyseOvenOverclock(machine, recipe) + ] + ) + .appearanceBlock(GTBlocks.CASING_STEEL_SOLID) + .pattern(definition => FactoryBlockPattern.start() + .aisle("BBCCCBB", "BBCDCBB", "BBCCCBB", "BBCCCBB", "BBEEEBB", "BBEEEBB") + .aisle("BCCCCCB", "BCAFACB", "BCAFACB", "BCGGGCB", "BEAAAEB", "BEHHHEB") + .aisle("CCCCCCC", "CAAFAAC", "CAAFAAC", "CGGGGGC", "EAAAAAE", "EHHHHHE") + .aisle("CCCCCCC", "DFFFFFD", "CFFFFFC", "CGGGGGC", "EAAAAAE", "EHHMHHE") + .aisle("CCCCCCC", "CAAFAAC", "CAAFAAC", "CGGGGGC", "EAAAAAE", "EHHHHHE") + .aisle("BCCCCCB", "BCAFACB", "BCAFACB", "BCGGGCB", "BEAAAEB", "BEHHHEB") + .aisle("BBCCCBB", "BBCICBB", "BBCCCBB", "BBCCCBB", "BBEEEBB", "BBEEEBB") + .where('A', Predicates.blocks("minecraft:air")) + .where('B', Predicates.any()) + .where('C', Predicates.blocks('gtceu:solid_machine_casing').setMinGlobalLimited(10) + .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1)) + .or(Predicates.abilities(PartAbility.PARALLEL_HATCH).setMaxGlobalLimited(1)) + .or(Predicates.autoAbilities(definition.getRecipeTypes()))) + .where('D', Predicates.blocks("gtceu:steel_firebox_casing")) + .where('E', Predicates.blocks("gtceu:laminated_glass")) + .where('F', Predicates.blocks("gtceu:ptfe_pipe_casing")) + .where('G', Predicates.heatingCoils()) + .where('H', Predicates.blocks("gtceu:high_temperature_smelting_casing")) + .where('M', Predicates.abilities(PartAbility.MUFFLER).setExactLimit(1)) + .where('I', Predicates.controller(Predicates.blocks(definition.get()))) + .build()) + .workableCasingModel("gtceu:block/casings/solid/machine_casing_solid_steel", + "gtceu:block/multiblock/pyrolyse_oven"); + + }) + ``` + + +=== "Java" + ```java title="MultiMachines.java" + + public static final MultiblockMachineDefinition SUPERHEATED_PYROLYZING_OVEN = REGISTRATE + .multiblock("superheated_pyrolyzing_oven", (holder) -> new CoilWorkableElectricMultiblockMachine(holder)) + .rotationState(RotationState.NON_Y_AXIS) + .recipeType(GTRecipeTypes.PYROLYSE_RECIPES) + .recipeModifiers(GTRecipeModifiers.PARALLEL_HATCH, + (machine, recipe) -> GTRecipeModifiers.pyrolyseOvenOverclock(machine, recipe)) + .appearanceBlock(GTBlocks.CASING_STEEL_SOLID) + .pattern(definition -> FactoryBlockPattern.start() + .aisle("BBCCCBB", "BBCDCBB", "BBCCCBB", "BBCCCBB", "BBEEEBB", "BBEEEBB") + .aisle("BCCCCCB", "BCAFACB", "BCAFACB", "BCGGGCB", "BEAAAEB", "BEHHHEB") + .aisle("CCCCCCC", "CAAFAAC", "CAAFAAC", "CGGGGGC", "EAAAAAE", "EHHHHHE") + .aisle("CCCCCCC", "DFFFFFD", "CFFFFFC", "CGGGGGC", "EAAAAAE", "EHHMHHE") + .aisle("CCCCCCC", "CAAFAAC", "CAAFAAC", "CGGGGGC", "EAAAAAE", "EHHHHHE") + .aisle("BCCCCCB", "BCAFACB", "BCAFACB", "BCGGGCB", "BEAAAEB", "BEHHHEB") + .aisle("BBCCCBB", "BBCICBB", "BBCCCBB", "BBCCCBB", "BBEEEBB", "BBEEEBB") + .where('A', Predicates.air()) + .where('B', Predicates.any()) + .where('C', Predicates.blocks(GTBlocks.CASING_STEEL_SOLID.get()).setMinGlobalLimited(10) + .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1)) + .or(Predicates.abilities(PartAbility.PARALLEL_HATCH).setMaxGlobalLimited(1)) + .or(Predicates.autoAbilities(definition.getRecipeTypes()))) + .where('D', Predicates.blocks(GTBlocks.FIREBOX_STEEL.get())) + .where('E', Predicates.blocks(CASING_LAMINATED_GLASS.get())) + .where('F', Predicates.blocks(GTBlocks.CASING_POLYTETRAFLUOROETHYLENE_PIPE.get())) + .where('G', Predicates.heatingCoils()) + .where('H', Predicates.blocks(GCYMBlocks.CASING_HIGH_TEMPERATURE_SMELTING.get())) + .where('M', Predicates.abilities(PartAbility.MUFFLER).setExactLimit(1)) + .where('I', Predicates.controller(Predicates.blocks(definition.get()))) + .build()) + .workableCasingModel(GTCEu.id("block/casings/solid/machine_casing_solid_steel"), + GTCEu.id("block/multiblock/pyrolyse_oven")) + .register(); + ``` + +### Lang + +```json title="en_us.json" +{ + "block.gtceu.superheated_pyrolyzing_oven": "Superheated Pyrolyzing Oven", +} +``` + + diff --git a/docs/content/Modpacks/Examples/Example_Steam_Multiblock.md b/docs/content/Modpacks/Examples/Example_Steam_Multiblock.md new file mode 100644 index 00000000000..57b06f47885 --- /dev/null +++ b/docs/content/Modpacks/Examples/Example_Steam_Multiblock.md @@ -0,0 +1,87 @@ +--- +title: "Example Steam Multiblock" +--- + +### Large Steam Compressor Multiblock + +Below is an example of a multiblock using the SteamParallelMultiblockMachine class. +Steam multiblocks such as the Steam Grinder and Steam Oven use this class. + +### Multiblock + +=== "JavaScript" + ```js title="example_steam_multiblock_multiblock.js" + + // In order to use multiblock logic extending beyond the default multiblock type for KJS (WorkableElectricMultiblockMachine), you need to load a class. + const $SteamMulti = Java.loadClass('com.gregtechceu.gtceu.common.machine.multiblock.steam.SteamParallelMultiblockMachine'); + + GTCEuStartupEvents.registry('gtceu:machine', event => { + event.create('large_steam_compressor', 'multiblock') + .machine((holder) => new $SteamMulti(holder, 4)) + // The number in holder is the max amount of parallel it can use. + .rotationState(RotationState.NON_Y_AXIS) + .recipeType('compressor') + .recipeModifier((machine, recipe) => $SteamMulti.recipeModifier(machine, recipe), true) + .pattern(definition => FactoryBlockPattern.start() + .aisle("BCCCB", "BBCBB", "BBCBB", "BBBBB", "BBBBB") + .aisle("CDDDC", "BDBDB", "BDEDB", "BBDBB", "BBBBB") + .aisle("CDDDC", "CBBBC", "CEFEC", "BDDDB", "BBGBB") + .aisle("CDDDC", "BDBDB", "BDEDB", "BBDBB", "BBBBB") + .aisle("BCCCB", "BBHBB", "BBCBB", "BBBBB", "BBBBB") + .where('B', Predicates.any()) + .where('C', Predicates.blocks('gtceu:steam_machine_casing').setMinGlobalLimited(10) + .or(Predicates.abilities(PartAbility.STEAM_IMPORT_ITEMS).setMaxGlobalLimited(1)) + .or(Predicates.abilities(PartAbility.STEAM).setMaxGlobalLimited(1)) + .or(Predicates.abilities(PartAbility.STEAM_EXPORT_ITEMS).setMaxGlobalLimited(1))) + .where('D', Predicates.blocks("gtceu:industrial_steam_casing")) + .where('E', Predicates.blocks("gtceu:bronze_brick_casing")) + .where('F', Predicates.blocks("gtceu:bronze_firebox_casing")) + .where('G', Predicates.blocks("gtceu:bronze_machine_casing")) + .where('H', Predicates.controller(Predicates.blocks(definition.get()))) + .build()) + .workableCasingModel("gtceu:block/casings/steam/bronze/bottom", + "gtceu:block/machines/compressor") + }) + ``` + +=== "Java" + ```java title="MultiMachines.java" + public static final MultiblockMachineDefinition LARGE_STEAM_COMPRESSOR = REGISTRATE + .multiblock("large_steam_compressor", (holder) -> new SteamParallelMultiblockMachine(holder, 4)) + .rotationState(RotationState.NON_Y_AXIS) + .recipeType(COMPRESSOR_RECIPES) + .recipeModifier((machine, recipe) -> SteamParallelMultiblockMachine.recipeModifier(machine, recipe), true) + .pattern(definition -> FactoryBlockPattern.start() + .aisle("BCCCB", "BBCBB", "BBCBB", "BBBBB", "BBBBB") + .aisle("CDDDC", "BDBDB", "BDEDB", "BBDBB", "BBBBB") + .aisle("CDDDC", "CBBBC", "CEFEC", "BDDDB", "BBGBB") + .aisle("CDDDC", "BDBDB", "BDEDB", "BBDBB", "BBBBB") + .aisle("BCCCB", "BBHBB", "BBCBB", "BBBBB", "BBBBB") + .where('B', Predicates.any()) + .where('C', Predicates.blocks(GTBlocks.CASING_BRONZE_BRICKS.get()).setMinGlobalLimited(10) + .or(Predicates.abilities(PartAbility.STEAM_IMPORT_ITEMS).setMaxGlobalLimited(1)) + .or(Predicates.abilities(PartAbility.STEAM).setMaxGlobalLimited(1)) + .or(Predicates.abilities(PartAbility.STEAM_EXPORT_ITEMS).setMaxGlobalLimited(1))) + .where('D', Predicates.blocks(GCYMBlocks.CASING_INDUSTRIAL_STEAM.get())) + .where('E', Predicates.blocks(GTBlocks.BRONZE_BRICKS_HULL.get())) + .where('F', Predicates.blocks(GTBlocks.FIREBOX_BRONZE.get())) + .where('G', Predicates.blocks(GTBlocks.BRONZE_HULL.get())) + .where('H', Predicates.controller(Predicates.blocks(definition.get()))) + .build()) + .workableCasingModel(GTCEu.id("block/casings/steam/bronze/bottom"), + GTCEu.id("block/machines/compressor")) + .register(); + ``` + +### Lang + +```json title="en_us.json" +{ + "block.gtceu.large_steam_compressor": "Large Steam Compressor", +} +``` + + + + + diff --git a/docs/content/Modpacks/Examples/Example_Turbine.md b/docs/content/Modpacks/Examples/Example_Turbine.md new file mode 100644 index 00000000000..4abdeefe1d5 --- /dev/null +++ b/docs/content/Modpacks/Examples/Example_Turbine.md @@ -0,0 +1,94 @@ +--- +title: "Example Turbine" +--- + +### Example Turbine + +Below is an example of a multiblock using the LargeTurbineMachine class for making custom large turbines. + +### Multiblock + +=== "JavaScript" + ```js title="hyper_gas_turbine.js" + // In order to use multiblock logic extending beyond the normal WorkableElectricMultiblockMachine, (This is the multiblock type used by default for kubejs) you need to load a class. LargeTurbineMachines such as the gas, steam, and plasma turbines use this class. + const $LargeTurbineMachine = Java.loadClass("com.gregtechceu.gtceu.common.machine.multiblock.generator.LargeTurbineMachine") + + GTCEuStartupEvents.registry('gtceu:machine', event => { + event.create('hyper_gas_turbine', 'multiblock') + .machine((holder) => new $LargeTurbineMachine(holder, GTValues.LuV)) // The value shows one rotor holder tier above the recommended minimum rotor holder. The tier of rotor holder provides a boost based on the efficiency stat. + .rotationState(RotationState.NON_Y_AXIS) + .recipeTypes("gas_turbine") + .recipeModifiers([GTRecipeModifiers.OC_NON_PERFECT_SUBTICK, GTRecipeModifiers.BATCH_MODE, (machine, recipe) => GTRecipeModifiers.LargeTurbineMachine(machine, recipe)]) + .appearanceBlock(GTBlocks.CASING_TITANIUM_STABLE) + .pattern(definition => FactoryBlockPattern.start() + .aisle("BBBBBBB", "BBBCBBB", "BBBDBBB", "BBBCBBB", "BBBBBBB") + .aisle("BBBCBBB", "BBCACBB", "BBCFCBB", "BBCACBB", "BBBCBBB") + .aisle("BBCCCBB", "BCAAACB", "BCAFACB", "BCAFACB", "BBCCCBB") + .aisle("BCCCCCB", "CAAFAAC", "CFFFFFC", "CAFFFAC", "BCCECCB") + .aisle("BBCCCBB", "BCAAACB", "BCAFACB", "BCAFACB", "BBCCCBB") + .aisle("BBBCBBB", "BBCACBB", "BBCFCBB", "BBCACBB", "BBBCBBB") + .aisle("BBBBBBB", "BBBCBBB", "BBBGBBB", "BBBCBBB", "BBBBBBB") + .where("A", Predicates.blocks("minecraft:air")) + .where("B", Predicates.any()) + .where("C", Predicates.blocks("gtceu:stainless_steel_turbine_casing") + .or(Predicates.autoAbilities(definition.getRecipeTypes())) + .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1))) + .where("D", Predicates.ability(PartAbility.MUFFLER).setExactLimit(1)) + .where("E", Predicates.ability(PartAbility.ROTOR_HOLDER).setExactLimit(1)) + .where("F", Predicates.blocks("gtceu:stainless_steel_frame")) + .where("G", Predicates.controller(Predicates.blocks(definition.get()))) + .build()) + .workableCasingModel("gtceu:block/casings/mechanic/machine_casing_turbine_stainless_steel", + "gtceu:block/multiblock/generator/large_gas_turbine") + }); + ``` + +=== "Java" + ```java title="MultiMachines.java" + public static final MultiblockMachineDefinition HYPER_GAS_TURBINE = REGISTRATE + .multiblock("hyper_gas_turbine", (holder) -> new LargeTurbineMachine(holder, GTValues.LuV, 4)) // The value shows one rotor holder tier above the recommended minimum rotor holder. The tier of rotor holder provides a boost based on the efficiency stat. + .rotationState(RotationState.NON_Y_AXIS) + .recipeType(GTRecipeTypes.GAS_TURBINE_FUELS) + .recipeModifiers(GTRecipeModifiers.OC_NON_PERFECT_SUBTICK, GTRecipeModifiers.BATCH_MODE, LargeTurbineMachine::recipeModifier) + .pattern(definition -> FactoryBlockPattern.start() + .aisle("BBBBBBB", "BBBCBBB", "BBBDBBB", "BBBCBBB", "BBBBBBB") + .aisle("BBBCBBB", "BBCACBB", "BBCECBB", "BBCACBB", "BBBCBBB") + .aisle("BBCCCBB", "BCAAACB", "BCAEACB", "BCAEACB", "BBCCCBB") + .aisle("BCCCCCB", "CAAEAAC", "CEEEEEC", "CAEEEAC", "BCCFCCB") + .aisle("BBCCCBB", "BCAAACB", "BCAEACB", "BCAEACB", "BBCCCBB") + .aisle("BBBCBBB", "BBCACBB", "BBCECBB", "BBCACBB", "BBBCBBB") + .aisle("BBBBBBB", "BBBCBBB", "BBBGBBB", "BBBCBBB", "BBBBBBB") + .where("A", Predicates.blocks("minecraft:air")) + .where("B", Predicates.any()) + .where("C", Predicates.blocks("gtceu:stainless_steel_turbine_casing") + .or(Predicates.autoAbilities(definition.getRecipeTypes())) + .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1))) + .where("D", Predicates.ability(PartAbility.MUFFLER).setExactLimit(1)) + .where("F", Predicates.ability(PartAbility.ROTOR_HOLDER).setExactLimit(1)) + .where("E", Predicates.blocks("gtceu:stainless_steel_frame")) + .where("G", Predicates.controller(Predicates.blocks(definition.get()))) + .build()) + .workableCasingModel(GTCEu.id("block/casings/steam/bronze/bottom"), + GTCEu.id("block/machines/compressor")) + .register(); + ``` + + +### Lang + +```json title="en_us.json" +{ + "block.gtceu.hyper_gas_turbine": "Hyper Gas Turbine", +} +``` + + + + + + + + + + + diff --git a/docs/content/Modpacks/Examples/Greenhouse.md b/docs/content/Modpacks/Examples/Greenhouse.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/docs/content/Modpacks/Other-Topics/Modular-Items.md b/docs/content/Modpacks/Other-Topics/Modular-Items.md new file mode 100644 index 00000000000..8d83390c21c --- /dev/null +++ b/docs/content/Modpacks/Other-Topics/Modular-Items.md @@ -0,0 +1,154 @@ +--- +title: Modular Items +--- + +# Modular Items + +### IModularItem + +`IModularItem` is a capability that can be attached to item stacks. +Its recommended implementation is `ModularItemStack`, which can be attached to a stack +in an `AttachCapabilitiesEvent` listener, or attached as an item component +to a `ComponentItem` using `ModularItemComponent`. Note that if it is attached not as +a component, module-related tooltips won't be displayed, and `onUse` and related methods won't work. + +!!! example "Attaching a `ModularItemStack` using an event" + ```java + @Mod.EventBusSubscriber(modid = "your_mod_id", bus = Mod.EventBusSubscriber.Bus.FORGE) + public static class ExampleEventListener { + @SubscribeEvent + public static void onAttachCapabilities(AttachCapabilitiesEvent event) { + ItemStack stack = event.getObject(); + if (stack.is(Items.DIAMOND_CHESTPLATE)) { + int slots = 5, maxTier = GTValues.HV; + List defaultSlots = new ArrayList<>(); + for (int i = 0; i < slots; i++) defaultSlots.add(GTItemModules.TIERED_SLOTS[maxTier]); + // ModularItemStack accepts a Function> in the constructor + // The stack provided to that function is the same stack as here, so we can ignore it + event.addCapability(GTCEu.id("modular"), new ModularItemStack(stack, ignored -> defaultSlots)); + } + } + } + ``` + +!!! example "Attaching a `ModularItemComponent` to a `ComponentItem`" + ```java + public void attachModularComponent() { + // fertilizer will now have 3 MV module slots + GTItems.FERTILIZER.get().attachComponents(new ModularItemComponent(3, GTValues.MV)); + } + ``` + +### ItemModuleSlot + +An `ItemModuleSlot` is basically a `Predicate` (a function that accepts an `ItemModule` and returns a `boolean`) with some other methods. +It has 2 abstract methods for your subclasses to implement: + +- `acceptsModule(ItemModule)` -> `boolean` + returns whether the provided module can be put into this slot +- `getDisplayName()` -> `Component` + returns the text to be displayed as part of the tooltip +- `getSlotTexture()` -> `IDrawable` (returns `null` by default) + returns the texture to use for this slot in the equipment foundry UI, `null` means to use the default + +!!! example "Tiered slot implementation" + ```java + public class TieredItemModuleSlot extends ItemModuleSlot { + + @Getter + private final int tier; + + public TieredItemModuleSlot(ResourceLocation id, int tier) { + super(id); + this.tier = tier; + } + + @Override + public boolean acceptsModule(ItemModule module) { + return !(module instanceof ITieredItemModule tieredModule) || tieredModule.getTier() <= getTier(); + } + + @Override + public Component getDisplayName() { + return Component.translatable("metaarmor.tooltip.modifier_slot.tiered", GTValues.VNF[getTier()]); + } + } + ``` + +### ItemModule + +`ItemModule` is an NBT-serializable object that can be attached to modular items.
+`AppliedItemModule` is an object that contains info about the module itself, the item +it is applied to, and the module's NBT. + +??? info "List of all overridable methods in `ItemModule`" + - `getInfo()` -> `Component` (override required)
+ returns the info about this module to display in XEI + - `onAttach(AppliedItemModule)` -> `void`
+ called when this module is attached to a modular item + - `onRemove(AppliedItemModule)` -> `void`
+ called when this module is removed from a modular item + - `onEquip(LivingEntity, AppliedItemModule)` -> `void`
+ called when the armor piece this module is attached to is equipped + - `onUnequip(LivingEntity, AppliedItemModule)` -> `void`
+ called when the armor piece this module is attached to is unequipped + - `onArmorTick(LivingEntity, AppliedItemModule)` -> `void`
+ called each tick while the armor piece this module is attached to is equipped + - `onInventoryTick(Player, AppliedItemModule)` -> `void`
+ called each tick while the item this module is attached to is in a player's inventory + - `appendHoverText(Level, TooltipFlag, List, AppliedItemModule)` -> `void`
+ called to insert lines into the modular item's tooltip + - `useEnergyInInventory(LivingEntity, AppliedItemModule)` -> `boolean` (default `true`)
+ returns whether to consume energy while the item is in a player's inventory, if `false`, the item + consumes energy only in armor slots + - `energyUsagePerTick(LivingEntity, AppliedItemModule)` -> `long` (default `0`)
+ returns the amount of energy to consume this tick (called every tick) + - `changeDamage(LivingEntity, AppliedItemModule, float damage, DamageSource)`-> `float` (returns `damage` by default)
+ returns the amount of damage to actually inflict, called each time the entity wearing the armor piece is damaged + - `canRemove(AppliedItemModule)` -> `boolean` (default `true`)
+ returns whether this module can be removed from the item in an equipment foundry + - `isPPE(AppliedItemModule)` -> `boolean` (default `false`)
+ returns whether armor pieces with this module should be considered personal protection equipment (hazmat) + - `canApplyTo(ItemStack)` -> `boolean`
+ returns whether this module can be attached to the provided stack, by default returns whether a module of this type + is already attached to the stack (blocking more than one module of the same type) + - `isEnabled(AppliedItemModule)` -> `boolean` (default `true`)
+ returns whether this module is enabled (all other methods, such as `onInventoryTick` won't be calld if it's disabled) + - `setEnabled(AppliedItemModule, boolean)` -> `void`
+ by default, sets the return value of `isEnabled` by modifying this module's NBT; this method is not required to actually enable/disable this module + - `use(AppliedItemModule, Level, Player, InteractionHand)` -> `InteractionResultHolder`
+ called when the item this module is attached to is used + - `useOn(AppliedItemModule, UseOnContext)` -> `InteractionResult`
+ called when the item this module is attached to is used on a block + +!!! example "Example of an energy shield module" + ```java + public class EnergyShieldItemModule extends TieredItemModule { + + public EnergyShieldItemModule(ResourceLocation id, int tier) { + super(id, tier); + } + + @Override + public Component getInfo() { + return Component.literal("Makes you invulnerable and consumes 1A " + GTValues.VNF[getTier()]); + } + + @Override + public long energyUsagePerTick(LivingEntity entity, AppliedItemModule module) { + return GTValues.V[getTier()]; + } + + @Override + public float changeDamage(LivingEntity entity, AppliedItemModule module, float amount, DamageSource source) { + return 0; + } + + @Override + public void appendHoverText(Level level, TooltipFlag isAdvanced, List tooltips, + AppliedItemModule module) { + super.appendHoverText(level, isAdvanced, tooltips, module); + tooltips.add(Component.literal("Energy shield (" + GTValues.VNF[getTier()] + ")")); + } + } + ``` \ No newline at end of file diff --git a/gradle/forge.versions.toml b/gradle/forge.versions.toml index 51f1f825a7a..0dbbe67ff0f 100644 --- a/gradle/forge.versions.toml +++ b/gradle/forge.versions.toml @@ -8,9 +8,11 @@ jei = "15.20.0.115" rei = "12.1.785" emi = "1.1.13+1.20.1" ae2 = "15.0.18" +mui = "3.1.5" kubejs = "2001.6.5-build.16" rhino = "2001.2.3-build.10" architectury = "9.2.14" +clothmath = "+" clothconfig = "11.1.136" curios = "5.9.1+1.20.1" kotlinforforge = "4.11.0" @@ -60,6 +62,8 @@ configuration = { module = "dev.toma.configuration:configuration-forge-1.2 mixinExtras-common = { module = "io.github.llamalad7:mixinextras-common", version.ref = "mixinExtras" } mixinExtras-forge = { module = "io.github.llamalad7:mixinextras-forge", version.ref = "mixinExtras" } +mui = { module = "brachy.modularui:modularui-mc1.20.1", version.ref = "mui" } + jei-common-api = { module = "mezz.jei:jei-1.20.1-common-api", version.ref = "jei" } jei-forge-api = { module = "mezz.jei:jei-1.20.1-forge-api", version.ref = "jei" } jei-forge-impl = { module = "mezz.jei:jei-1.20.1-forge", version.ref = "jei" } @@ -76,6 +80,7 @@ flywheel-forge = { module = "dev.engine-room.flywheel:flywheel-forge-1.20.1 kubejs = { module = "dev.latvian.mods:kubejs-forge", version.ref = "kubejs" } rhino = { module = "dev.latvian.mods:rhino-forge", version.ref = "rhino" } architectury = { module = "dev.architectury:architectury-forge", version.ref = "architectury" } +clothmath = { module = "me.shedaniel.cloth:basic-math", version.ref = "clothmath" } clothconfig = { module = "me.shedaniel.cloth:cloth-config-forge", version.ref = "clothconfig" } curios = { module = "top.theillusivec4.curios:curios-forge", version.ref = "curios" } kotlinforforge = { module = "thedarkcolour:kotlinforforge", version.ref = "kotlinforforge" } @@ -118,7 +123,7 @@ ftbchunks-cm = { module = "curse.maven:ftb-chunks-forge-314906", version. [bundles] jei = ["jei-common-api", "jei-forge-api", "jei-forge-impl"] -rei = ["rei-plugin", "rei-forge"] +rei = ["rei-plugin", "rei-forge", "clothmath"] rei-runtime = ["rei-forge", "architectury", "clothconfig"] kjs = ["kubejs", "rhino", "architectury"] diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 96029a58b06..880fc1a6e45 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,6 +10,7 @@ lombok = "8.14" jetbrains-annotations = "26.0.1" renderNurse = "0.0.12" mixin = "0.8.7" +evalEx = "3.6.0" [libraries] minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" } @@ -17,6 +18,7 @@ minecraftForge = { module = "net.minecraftforge:forge", version.ref = " jetbrains-annotations = { module = "org.jetbrains:annotations", version.ref = "jetbrains-annotations" } renderNurse = { module = "net.neoforged:render-nurse", version.ref = "renderNurse" } mixin = { module = "org.spongepowered:mixin", version.ref = "mixin" } +evalEx = { module = "com.ezylang:EvalEx", version.ref = "evalEx" } [plugins] modDevGradle = { id = "net.neoforged.moddev.legacyforge", version.ref = "modDevGradle" } diff --git a/gradle/scripts/repositories.gradle b/gradle/scripts/repositories.gradle index 1b4d59ec81c..79543347d21 100644 --- a/gradle/scripts/repositories.gradle +++ b/gradle/scripts/repositories.gradle @@ -1,17 +1,23 @@ repositories { mavenLocal() mavenCentral() - // force gradle to download FastUtil & LWJGL from the central maven so we can get source artifacts + // force gradle to download FastUtil and LWJGL from the central maven so we can get source artifacts exclusiveContent { // Force forRepository { mavenCentral() } filter { includeGroup("it.unimi.dsi") includeGroup("org.lwjgl") + includeGroupAndSubgroups("io.netty") includeGroup("com.google.guava") includeGroup("io.netty") } } + maven { + name 'GTCEu Maven' + url 'https://maven.gtceu.com' + } + maven { // JEI name = "Jared's Maven" url = "https://maven.blamejared.com/" diff --git a/src/generated/resources/assets/gtceu/blockstates/equipment_foundry.json b/src/generated/resources/assets/gtceu/blockstates/equipment_foundry.json new file mode 100644 index 00000000000..54d31f3ed4a --- /dev/null +++ b/src/generated/resources/assets/gtceu/blockstates/equipment_foundry.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "gtceu:block/equipment_foundry" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/blockstates/test_mui.json b/src/generated/resources/assets/gtceu/blockstates/test_mui.json new file mode 100644 index 00000000000..c96e32638d9 --- /dev/null +++ b/src/generated/resources/assets/gtceu/blockstates/test_mui.json @@ -0,0 +1,28 @@ +{ + "variants": { + "facing=down": { + "model": "gtceu:block/machine/test_mui", + "x": 90 + }, + "facing=east": { + "model": "gtceu:block/machine/test_mui", + "y": 90 + }, + "facing=north": { + "model": "gtceu:block/machine/test_mui" + }, + "facing=south": { + "model": "gtceu:block/machine/test_mui", + "y": 180 + }, + "facing=up": { + "gtceu:z": 180, + "model": "gtceu:block/machine/test_mui", + "x": 270 + }, + "facing=west": { + "model": "gtceu:block/machine/test_mui", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/blockstates/test_mui_new.json b/src/generated/resources/assets/gtceu/blockstates/test_mui_new.json new file mode 100644 index 00000000000..41ab9b075f2 --- /dev/null +++ b/src/generated/resources/assets/gtceu/blockstates/test_mui_new.json @@ -0,0 +1,28 @@ +{ + "variants": { + "facing=down": { + "model": "gtceu:block/machine/test_mui_new", + "x": 90 + }, + "facing=east": { + "model": "gtceu:block/machine/test_mui_new", + "y": 90 + }, + "facing=north": { + "model": "gtceu:block/machine/test_mui_new" + }, + "facing=south": { + "model": "gtceu:block/machine/test_mui_new", + "y": 180 + }, + "facing=up": { + "gtceu:z": 180, + "model": "gtceu:block/machine/test_mui_new", + "x": 270 + }, + "facing=west": { + "model": "gtceu:block/machine/test_mui_new", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/lang/en_ud.json b/src/generated/resources/assets/gtceu/lang/en_ud.json index 53efcdcd9bf..954f793a4ff 100644 --- a/src/generated/resources/assets/gtceu/lang/en_ud.json +++ b/src/generated/resources/assets/gtceu/lang/en_ud.json @@ -58,6 +58,7 @@ "behavior.prospector.not_enough_energy": "¡ʎbɹǝuƎ ɥbnouƎ ʇoN", "behavior.toggle_energy_consumer.tooltip": "ǝpoɯ ǝןbboʇ oʇ ǝs∩", "behaviour.boor.by": "%s ʎq", + "behaviour.charger_linked": "ɹǝbɹɐɥɔ pǝʞuıꞀ", "behaviour.hammer": ")ɯǝɥʇ buıʇʇıɥ ʎq( sǝuıɥɔɐW ɹoɟ buıןɟɟnW ɟɟo puɐ uo suɹn⟘", "behaviour.hoe": "ʇɹıp ןןıʇ uɐƆ", "behaviour.lighter.fluid.tooltip": "ǝuɐdoɹԀ ɹo ǝuɐʇnᗺ ɥʇıʍ ǝɹıɟ uo sbuıɥʇ ʇɥbıן uɐƆ", @@ -211,6 +212,7 @@ "block.gtceu.empty_tier_ii_battery": "ɹoʇıɔɐdɐƆ II ɹǝı⟘ ʎʇdɯƎ", "block.gtceu.empty_tier_iii_battery": "ɹoʇıɔɐdɐƆ III ɹǝı⟘ ʎʇdɯƎ", "block.gtceu.engine_intake_casing": "buısɐƆ ǝʞɐʇuI ǝuıbuƎ", + "block.gtceu.equipment_foundry": "ʎɹpunoℲ ʇuǝɯdınbƎ", "block.gtceu.ev_16a_energy_converter": "ɹǝʇɹǝʌuoƆ ʎbɹǝuƎ ɹ§Ɐǝ§9Ɩ ɹ§ΛƎϛ§", "block.gtceu.ev_1a_energy_converter": "ɹǝʇɹǝʌuoƆ ʎbɹǝuƎ ɹ§Ɐǝ§Ɩ ɹ§ΛƎϛ§", "block.gtceu.ev_4a_energy_converter": "ɹǝʇɹǝʌuoƆ ʎbɹǝuƎ ɹ§Ɐǝ§ㄣ ɹ§ΛƎϛ§", @@ -1133,6 +1135,8 @@ "block.gtceu.substation_capacitor.tooltip_filled": "∩Ǝ %dɟ§ :ʎʇıɔɐdɐƆ ʎbɹǝuƎɔ§", "block.gtceu.superconducting_coil": "ʞɔoןᗺ ןıoƆ buıʇɔnpuoɔɹǝdnS", "block.gtceu.tempered_glass": "ssɐן⅁ pǝɹǝdɯǝ⟘", + "block.gtceu.test_mui": "ınW ʇsǝ⟘", + "block.gtceu.test_mui_new": "ʍǝN ınW ʇsǝ⟘", "block.gtceu.the_end_marker": "puƎ ǝɥ⟘", "block.gtceu.the_nether_marker": "ɹǝɥʇǝN ǝɥ⟘", "block.gtceu.titanium_crate": "ǝʇɐɹƆ ɯnıuɐʇı⟘", @@ -1777,7 +1781,9 @@ "config.gtceu.option.coloredWireOutline": "ǝuıןʇnOǝɹıMpǝɹoןoɔ", "config.gtceu.option.compat": "ʇɐdɯoɔ", "config.gtceu.option.createCompat": "ʇɐdɯoƆǝʇɐǝɹɔ", + "config.gtceu.option.cursorColor": "ɹoןoƆɹosɹnɔ", "config.gtceu.option.debug": "bnqǝp", + "config.gtceu.option.debugUI": "I∩bnqǝp", "config.gtceu.option.debugWorldgen": "uǝbpןɹoMbnqǝp", "config.gtceu.option.defaultPaintingColor": "ɹoןoƆbuıʇuıɐԀʇןnɐɟǝp", "config.gtceu.option.defaultUIColor": "ɹoןoƆI∩ʇןnɐɟǝp", @@ -1805,6 +1811,7 @@ "config.gtceu.option.energyUsageMultiplier": "ɹǝıןdıʇןnWǝbɐs∩ʎbɹǝuǝ", "config.gtceu.option.environmentalHazardDecayRate": "ǝʇɐᴚʎɐɔǝᗡpɹɐzɐHןɐʇuǝɯuoɹıʌuǝ", "config.gtceu.option.environmentalHazards": "spɹɐzɐHןɐʇuǝɯuoɹıʌuǝ", + "config.gtceu.option.escRestoresLastText": "ʇxǝ⟘ʇsɐꞀsǝɹoʇsǝᴚɔsǝ", "config.gtceu.option.euToFeRatio": "oıʇɐᴚǝℲo⟘nǝ", "config.gtceu.option.extractorRecyclingYield": "pןǝıʎbuıןɔʎɔǝᴚɹoʇɔɐɹʇxǝ", "config.gtceu.option.feToEuRatio": "oıʇɐᴚnƎo⟘ǝɟ", @@ -1856,6 +1863,7 @@ "config.gtceu.option.meHatchEnergyUsage": "ǝbɐs∩ʎbɹǝuƎɥɔʇɐHǝɯ", "config.gtceu.option.minerSpeed": "pǝǝdSɹǝuıɯ", "config.gtceu.option.minimap": "dɐɯıuıɯ", + "config.gtceu.option.mui": "ınɯ", "config.gtceu.option.nanoSaber": "ɹǝqɐSouɐu", "config.gtceu.option.nanoSaberBaseDamage": "ǝbɐɯɐᗡǝsɐᗺɹǝqɐSouɐu", "config.gtceu.option.nanoSaberDamageBoost": "ʇsooᗺǝbɐɯɐᗡɹǝqɐSouɐu", @@ -1876,6 +1884,7 @@ "config.gtceu.option.oreVeinGridSize": "ǝzıSpıɹ⅁uıǝΛǝɹo", "config.gtceu.option.oreVeinRandomOffset": "ʇǝsɟɟOɯopuɐᴚuıǝΛǝɹo", "config.gtceu.option.oreVeins": "suıǝΛǝɹo", + "config.gtceu.option.outlineColor": "ɹoןoƆǝuıןʇno", "config.gtceu.option.ownerOPBypass": "ssɐdʎᗺԀOɹǝuʍo", "config.gtceu.option.prospectorEnergyUseMultiplier": "ɹǝıןdıʇןnWǝs∩ʎbɹǝuƎɹoʇɔǝdsoɹd", "config.gtceu.option.quantumTank": "ʞuɐ⟘ɯnʇuɐnb", @@ -1889,14 +1898,28 @@ "config.gtceu.option.renderGrowingPlants": "sʇuɐןԀbuıʍoɹ⅁ɹǝpuǝɹ", "config.gtceu.option.renderer": "ɹǝɹǝpuǝɹ", "config.gtceu.option.replaceMinedBlocksWith": "ɥʇıMsʞɔoןᗺpǝuıWǝɔɐןdǝɹ", + "config.gtceu.option.replaceVanillaTooltips": "sdıʇןoo⟘ɐןןıuɐΛǝɔɐןdǝɹ", "config.gtceu.option.replaceWithCobbleVersion": "uoısɹǝΛǝןqqoƆɥʇıMǝɔɐןdǝɹ", "config.gtceu.option.requireGTToolsForBlocks": "sʞɔoןᗺɹoℲsןoo⟘⟘⅁ǝɹınbǝɹ", "config.gtceu.option.rngDamageElectricTools": "sןoo⟘ɔıɹʇɔǝןƎǝbɐɯɐᗡbuɹ", "config.gtceu.option.rubberTreeSpawnChance": "ǝɔuɐɥƆuʍɐdSǝǝɹ⟘ɹǝqqnɹ", "config.gtceu.option.sandOresFall": "ןןɐℲsǝɹOpuɐs", + "config.gtceu.option.scale": "ǝןɐɔs", "config.gtceu.option.shouldWeatherOrTerrainExplosion": "uoısoןdxƎuıɐɹɹǝ⟘ɹOɹǝɥʇɐǝMpןnoɥs", "config.gtceu.option.showDimensionTier": "ɹǝı⟘uoısuǝɯıᗡʍoɥs", + "config.gtceu.option.showExtra": "ɐɹʇxƎʍoɥs", + "config.gtceu.option.showHovered": "pǝɹǝʌoHʍoɥs", + "config.gtceu.option.showOutline": "ǝuıןʇnOʍoɥs", + "config.gtceu.option.showParent": "ʇuǝɹɐԀʍoɥs", + "config.gtceu.option.showParentOutline": "ǝuıןʇnOʇuǝɹɐԀʍoɥs", + "config.gtceu.option.showParentPos": "soԀʇuǝɹɐԀʍoɥs", + "config.gtceu.option.showParentSize": "ǝzıSʇuǝɹɐԀʍoɥs", + "config.gtceu.option.showParentWidgetTheme": "ǝɯǝɥ⟘ʇǝbpıMʇuǝɹɐԀʍoɥs", + "config.gtceu.option.showPos": "soԀʍoɥs", + "config.gtceu.option.showSize": "ǝzıSʍoɥs", + "config.gtceu.option.showWidgetTheme": "ǝɯǝɥ⟘ʇǝbpıMʍoɥs", "config.gtceu.option.smallBoilers": "sɹǝןıoᗺןןɐɯs", + "config.gtceu.option.smoothProgressBar": "ɹɐᗺssǝɹboɹԀɥʇooɯs", "config.gtceu.option.solarBoilerBaseOutput": "ʇndʇnOǝsɐᗺɹǝןıoᗺɹɐןos", "config.gtceu.option.solidBoilerBaseOutput": "ʇndʇnOǝsɐᗺɹǝןıoᗺpıןos", "config.gtceu.option.sprayCanChainLength": "ɥʇbuǝꞀuıɐɥƆuɐƆʎɐɹds", @@ -1908,17 +1931,21 @@ "config.gtceu.option.surfaceRockProspectRange": "ǝbuɐᴚʇɔǝdsoɹԀʞɔoᴚǝɔɐɟɹns", "config.gtceu.option.tankItemFluidPreview": "ʍǝıʌǝɹԀpınןℲɯǝʇIʞuɐʇ", "config.gtceu.option.temperaturesInCelsius": "snısןǝƆuIsǝɹnʇɐɹǝdɯǝʇ", + "config.gtceu.option.textColor": "ɹoןoƆʇxǝʇ", "config.gtceu.option.titaniumBoilerHeatSpeed": "pǝǝdSʇɐǝHɹǝןıoᗺɯnıuɐʇıʇ", "config.gtceu.option.titaniumBoilerMaxTemperature": "ǝɹnʇɐɹǝdɯǝ⟘xɐWɹǝןıoᗺɯnıuɐʇıʇ", "config.gtceu.option.toggle": "ǝןbboʇ", "config.gtceu.option.toolCraftingSounds": "spunoSbuıʇɟɐɹƆןooʇ", "config.gtceu.option.toolUseSounds": "spunoSǝs∩ןooʇ", "config.gtceu.option.tools": "sןooʇ", + "config.gtceu.option.tooltipPos": "soԀdıʇןooʇ", "config.gtceu.option.treeFellingDelay": "ʎɐןǝᗡbuıןןǝℲǝǝɹʇ", "config.gtceu.option.tungstensteelBoilerHeatSpeed": "pǝǝdSʇɐǝHɹǝןıoᗺןǝǝʇsuǝʇsbunʇ", "config.gtceu.option.tungstensteelBoilerMaxTemperature": "ǝɹnʇɐɹǝdɯǝ⟘xɐWɹǝןıoᗺןǝǝʇsuǝʇsbunʇ", + "config.gtceu.option.ui": "ın", "config.gtceu.option.universalHazards": "spɹɐzɐHןɐsɹǝʌıun", "config.gtceu.option.updateIntervals": "sןɐʌɹǝʇuIǝʇɐpdn", + "config.gtceu.option.useDarkThemeByDefault": "ʇןnɐɟǝᗡʎᗺǝɯǝɥ⟘ʞɹɐᗡǝsn", "config.gtceu.option.useVBO": "OᗺΛǝsn", "config.gtceu.option.voltageTierAdvImpeller": "ɹǝןןǝdɯIʌpⱯɹǝı⟘ǝbɐʇןoʌ", "config.gtceu.option.voltageTierAdvNanoSuit": "ʇınSouɐNʌpⱯɹǝı⟘ǝbɐʇןoʌ", @@ -2029,20 +2056,18 @@ "cover.conveyor.transfer_rate": "ɔǝs/sɯǝʇıㄥ§", "cover.detector_base.message_inverted_state": "pǝʇɹǝʌuI :snʇɐʇS buıɹoʇıuoW", "cover.detector_base.message_normal_state": "ןɐɯɹoN :snʇɐʇS buıɹoʇıuoW", - "cover.ender_fluid_link.incomplete_hex.0": "¡ǝʇǝןdɯoɔuı sı ɹoןoɔ pǝʇʇnduI", - "cover.ender_fluid_link.incomplete_hex.1": ")sʇıbıp xǝɥ 8 ןןɐ( ǝʇǝןdɯoɔ ǝɔuo pǝıןddɐ ǝq ןןıʍ ʇI", - "cover.ender_fluid_link.incomplete_hex.2": "¡sʇıpǝ ǝsoן ןןıʍ ınb ǝɥʇ buısoןƆ", "cover.ender_fluid_link.iomode.disabled": "pǝןqɐsıᗡ O/I", "cover.ender_fluid_link.iomode.enabled": "pǝןqɐuƎ O/I", - "cover.ender_fluid_link.private.tooltip.disabled.0": "ǝpoɯ ʞuɐʇ ǝʇɐʌıɹd oʇ ɥɔʇıʍS", - "cover.ender_fluid_link.private.tooltip.disabled.1": "ɹǝʌoɔ ǝɥʇ pǝɔɐןd ʎןןɐuıbıɹo oɥʍ ɹǝʎɐןd ǝɥʇ sǝsn ǝpoɯ ǝʇɐʌıɹԀ", - "cover.ender_fluid_link.private.tooltip.enabled": "ǝpoɯ ʞuɐʇ ɔıןqnd oʇ ɥɔʇıʍS", "cover.ender_fluid_link.title": "ʞuıꞀ pınןℲ ɹǝpuƎ", - "cover.ender_fluid_link.tooltip.channel_description": "ʇxǝʇ ʇnduı ɥʇıʍ uoıʇdıɹɔsǝp ןǝuuɐɥɔ ʇǝS", - "cover.ender_fluid_link.tooltip.channel_name": "ʇxǝʇ ʇnduı ɥʇıʍ ǝɯɐu ןǝuuɐɥɔ ʇǝS", - "cover.ender_fluid_link.tooltip.clear_button": "uoıʇdıɹɔsǝp ןǝuuɐɥɔ ɹɐǝןƆ", - "cover.ender_fluid_link.tooltip.list_button": "ʇsıן ןǝuuɐɥɔ ʍoɥS", "cover.ender_item_link.title": "ʞuıꞀ ɯǝʇI ɹǝpuƎ", + "cover.ender_link.description_empty": "uoıʇdıɹɔsǝᗡ ʎʇdɯƎ", + "cover.ender_link.private.tooltip": "ɹǝʌoɔ sıɥʇ pǝɔɐןd oɥʍ ɹǝʎɐןd ǝɥʇ oʇ ǝןqıssǝɔɔɐ ʎןuO :ǝpoɯ ǝʇɐʌıɹԀ", + "cover.ender_link.protected.tooltip": "˙ɯɐǝʇ ǝɯɐs ǝɥʇ uo sɹǝʎɐןd oʇ ǝןqıssǝɔɔⱯ :ǝpoW pǝʇɔǝʇoɹԀ", + "cover.ender_link.public.tooltip": "sɹǝʎɐןd ןןɐ oʇ ǝןqıssǝɔɔⱯ :ǝpoɯ ɔıןqnԀ", + "cover.ender_link.tooltip.channel_description": "uoıʇdıɹɔsǝp ןǝuuɐɥƆ", + "cover.ender_link.tooltip.channel_name": ")ǝnןɐʌ ןɐɯıɔǝpɐxǝɥ ʇıq-ᄅƐ( ᗡI ןǝuuɐɥƆ", + "cover.ender_link.tooltip.clear_button": "uoıʇdıɹɔsǝp ןǝuuɐɥɔ ɹɐǝןƆ", + "cover.ender_link.tooltip.list_button": "ʇsıן ןǝuuɐɥɔ ʍoɥS", "cover.ender_redstone_link.title": "ʞuıꞀ ǝuoʇspǝᴚ ɹǝpuƎ", "cover.filter.blacklist.disabled": "ʇsıןǝʇıɥM", "cover.filter.blacklist.enabled": "ʇsıןʞɔɐןᗺ", @@ -2080,6 +2105,7 @@ "cover.item_smart_filter.filtering_mode.electrolyzer": "ɹǝzʎןoɹʇɔǝןƎ", "cover.item_smart_filter.filtering_mode.sifter": "ɹǝʇɟıS", "cover.item_smart_filter.title": "ɹǝʇןıℲ ɯǝʇI ʇɹɐɯS", + "cover.machine_controller.control": "ʇǝbɹɐ⟘ ɹǝןןoɹʇuoƆ", "cover.machine_controller.invert.disabled.0": "unɹ oʇ ןǝʌǝן ǝuoʇspǝɹ ʇǝs ǝɥʇ uɐɥʇ ɹǝʞɐǝʍ ןɐubıs ɐ ǝɹınbǝɹ ןןıʍ ɹǝʌoɔ ǝɥʇ 'ǝpoɯ sıɥʇ uı - ɹ§ןɐɯɹoNǝ§", "cover.machine_controller.invert.enabled.0": "unɹ oʇ ןǝʌǝן ǝuoʇspǝɹ ʇǝs ǝɥʇ uɐɥʇ ɹǝbuoɹʇs ןɐubıs ɐ ǝɹınbǝɹ ןןıʍ ɹǝʌoɔ ǝɥʇ 'ǝpoɯ sıɥʇ uı - ɹ§pǝʇɹǝʌuIǝ§", "cover.machine_controller.inverted": "pǝʇɹǝʌuI", @@ -2192,6 +2218,7 @@ "death.attack.gtceu.wrench_iv": "%s ʎq suɐןd ɹıǝɥʇ oʇuı uʍoɹɥʇ ɥɔuǝɹʍ ɐ pɐɥ %s", "death.attack.gtceu.wrench_lv": "%s ʎq pǝuǝsooן ǝɹǝʍ sǝdıd s,%s", "effect.gtceu.weak_poison": "uosıoԀ ʞɐǝM", + "emi.category.gtceu.equipment_foundry": "ʎɹpunoℲ ʇuǝɯdınbƎ", "enchantment.damage.disjunction": "uoıʇɔunظsıᗡ", "enchantment.disjunction": "uoıʇɔunظsıᗡ", "enchantment.gtceu.disjunction.description": "˙sqoɯ pǝʇɐןǝɹ-ɹǝpuƎ oʇ ssǝuʍoןS puɐ ssǝuʞɐǝM sǝıןddⱯ", @@ -2235,6 +2262,10 @@ "gtceu.canner": "ɹǝuuɐƆ", "gtceu.central_monitor.gui.create_group": "dnoɹb ǝʇɐǝɹƆ", "gtceu.central_monitor.gui.currently_editing": "%s :buıʇıpǝ ʎןʇuǝɹɹnƆ", + "gtceu.central_monitor.gui.data_slot": "ʞɔıʇs ɐʇɐp ɟo ɹǝqɯnu ʇoןs ʇǝS", + "gtceu.central_monitor.gui.group_editor": "dnoɹb ɹoʇıuoɯ buıʇıpƎ", + "gtceu.central_monitor.gui.group_name": ":ǝɯɐN", + "gtceu.central_monitor.gui.monitor_groups": "sdnoɹb ɹoʇıuoW", "gtceu.central_monitor.gui.remove_from_group": "dnoɹb ɯoɹɟ ǝʌoɯǝᴚ", "gtceu.central_monitor.gui.set_target": "ʇǝbɹɐʇ ʇǝS", "gtceu.central_monitor.info_tooltip.0": "˙ʇı uı ǝןnpoɯ Ɩ ǝʌɐɥ ʎןuo ʎɐɯ dnoɹb Ɐ ˙ʇsɹıɟ sdnoɹb oʇuı ɯǝɥʇ ʇıןds oʇ ǝʌɐɥ noʎ 'sɹoʇıuoɯ ǝsn oʇ ɹǝpɹo uI", @@ -2291,7 +2322,8 @@ "gtceu.creative.chest.ipc": "ǝןɔʎƆ ɹǝd sɯǝʇI", "gtceu.creative.chest.item": "ɯǝʇI", "gtceu.creative.chest.tpc": "ǝןɔʎƆ ɹǝd sʞɔı⟘", - "gtceu.creative.computation.average": "ʇ∩MƆ pǝʇsǝnbǝᴚ ǝbɐɹǝʌⱯ", + "gtceu.creative.computation.average": "%d :ʞɔıʇ/∩MƆ ǝbɐɹǝʌⱯ", + "gtceu.creative.computation.max_usage": ":ʞɔıʇ/∩MƆ xɐW", "gtceu.creative.energy.amperage": "ǝbɐɹǝdɯⱯ", "gtceu.creative.energy.sink": "ʞuıS", "gtceu.creative.energy.source": "ǝɔɹnoS", @@ -2327,6 +2359,12 @@ "gtceu.ender_redstone_link_cover.label": "%d :ɹǝʍod ǝuoʇspǝᴚ", "gtceu.ender_redstone_link_cover.title": "ʞuıꞀ ǝuoʇspǝᴚ ɹǝpuƎ", "gtceu.ender_redstone_link_cover.tooltip": "˙ㄥ§ɹǝʌoƆɟ§ sɐ ㄥ§uoıʇɔǝuuoƆ ɟ§ɹǝpuƎp§ ssǝןǝɹıMɟ§ ɐ ɥʇıʍ ㄥ§sןɐubıs ǝuoʇspǝᴚɟ§ sʇıɯsuɐɹ⟘ㄥ§", + "gtceu.equipment_foundry.gui.applied_to": ":oʇ pǝıןddⱯ", + "gtceu.equipment_foundry.gui.module_item": ":ɯǝʇı ǝןnpoW", + "gtceu.equipment_foundry.gui.supports_tiers": "%s-%s :sɹǝıʇ ǝןnpoW", + "gtceu.equipment_foundry.gui.tier": "%s :ɹǝıʇ ɹoɟ sʇɐʇs buıʍǝıΛ", + "gtceu.equipment_foundry.gui.tier_too_high": "ɹǝıʇ sıɥʇ ɹoɟ sʇsıxǝ ɯǝʇı ǝןnpoɯ oN", + "gtceu.equipment_foundry.gui.tooltip.tier_switch": "Ɩ ʎq ɹǝıʇ ǝsɐǝɹɔǝp oʇ ʞɔıןɔ-ʇɥbıᴚ\nƖ ʎq ɹǝıʇ ǝsɐǝɹɔuı oʇ ʞɔıןɔ-ʇɟǝꞀ", "gtceu.extractor": "ɹoʇɔɐɹʇxƎ", "gtceu.extruder": "ɹǝpnɹʇxƎ", "gtceu.fermenter": "ɹǝʇuǝɯɹǝℲ", @@ -2371,10 +2409,24 @@ "gtceu.gui.adv_stocking_config.title": "buıʞɔoʇS ɔıʇɐɯoʇnⱯ ǝɹnbıɟuoƆ", "gtceu.gui.all_voiding": "ןןⱯɔ§ buıpıoΛㄥ§", "gtceu.gui.auto_output.name": "oʇnɐ", + "gtceu.gui.central_monitor.data_hatch_target": "˙pɐǝʇsuı ʇǝbɹɐʇ ǝɥʇ pǝɹǝpısuoɔ ǝq ןןıʍ )ɹǝʌoɔ ɹǝʇʇıɯsuɐɹʇ ssǝןǝɹıʍ ɐ buıʞɔıןɔ-ʇɥbıɹ ɐıʌ( oʇ pǝʞuıן sı ʇoןs pǝıɟıɔǝds ǝɥʇ uı ʞɔıʇs ɐʇɐp ǝɥʇ ʇɐɥʇ ʞɔoןq ǝɥʇ uǝɥ⟘ ˙ɹǝqɯnu ʇoןs ɐ ɹǝʇuǝ oʇ pǝʇdɯoɹd ǝq ןןıʍ noʎ 'ʇǝbɹɐʇ ɐ sɐ ɥɔʇɐɥ ɐʇɐp ɐ ʇɔǝןǝs noʎ ɟI", "gtceu.gui.central_monitor.group": "%s :dnoɹ⅁", "gtceu.gui.central_monitor.group_default_name": "%d# dnoɹ⅁", - "gtceu.gui.central_monitor.none": "ǝuou", + "gtceu.gui.central_monitor.gui_module_info": "˙ɹoʇıpǝ dnoɹb ɹoʇıuoɯ ǝɥʇ uı ʇǝbɹɐʇ ɐ ʇɔǝןǝs 'ɯoɹɟ I∩⅁ ǝɥʇ ʇǝb oʇ ʞɔoןq ɐ ʇɔǝןǝs o⟘", + "gtceu.gui.central_monitor.help": ":suoıʇɔǝןǝs ɟo sǝdʎʇ ǝɹɐ ǝɹǝɥ 'xoqʇxǝʇ ǝɯɐu dnoɹb ǝɥʇ ʍoןǝq pıɹb ǝɥʇ uı ɹoʇıuoɯ Ɩ ʇsɐǝן ʇɐ ʇɔǝןǝs oʇ ǝʌɐɥ noʎ uǝɥ⟘\n)ʎɐןdsıp oʇ ʇxǝʇ ǝɥʇ ɹǝʇuǝ ʇsnظ ǝןdɯɐxǝ ɹoɟ( ǝןnpoɯ ǝɥʇ ǝɹnbıɟuoɔ oʇ ɹɐǝddɐ ןןıʍ uoʇʇnq ɐ 'ʇı ʇɹǝsuı noʎ uǝɥM\n˙xoqʇxǝʇ ǝɯɐu dnoɹb ǝɥʇ ɟo ʇɥbıɹ ǝɥʇ oʇ ʇoןs ǝɥʇ uı pǝʇɹǝsuı ǝq ʇsnɯ ǝןnpoɯ Ɐ\nǝןnpoɯ ɹoʇıuoɯ pǝɹnbıɟuoɔ puɐ pǝʇɹǝsuı uɐ - \nuo buıɥʇǝɯos ʎɐןdsıp oʇ ʇuɐʍ noʎ ʇɐɥʇ sɹoʇıuoɯ ǝɥʇ ʇɔǝןǝs oʇ noʎ - \n:sbuıɥʇ ᄅ spǝǝu ʇı 'buıɥʇʎuɐ ʎɐןdsıp oʇ dnoɹb ɐ ɹoℲ\n˙ʞɔoןqıʇןnɯ ǝɥʇ uı sɹoʇıuoɯ ɟo ʇunoɯɐ ʎuɐ ɟo uoıʇɔǝןןoɔ ɐ sı dnoɹb ɹoʇıuoɯ Ɐ", + "gtceu.gui.central_monitor.in_group": "ɟɟnʇs ʎɐןdsıp oʇ pǝsn ǝq ןןıʍ puɐ 'dnoɹb ǝɥʇ oʇ pǝppɐ ǝɹɐ ʎɐʍ sıɥʇ pǝʇɔǝןǝs sɹoʇıuoW", + "gtceu.gui.central_monitor.in_group_and_target": "˙ǝɯıʇ ǝɯɐs ǝɥʇ ʇɐ ʇǝbɹɐʇ ɐ sɐ puɐ buıʎɐןdsıp ɹoɟ pǝsn sı ʎɐʍ sıɥʇ pǝʇɔǝןǝs ɹoʇıuoɯ ǝɥ⟘", + "gtceu.gui.central_monitor.left_click": "ʇı buıʞɔıןɔ-ʇɟǝן ʎq ɹoʇıuoɯ ɐ ʇɔǝןǝsun/ʇɔǝןǝS", + "gtceu.gui.central_monitor.module_editor_button": "ǝןnpoɯ ʇıpƎ", + "gtceu.gui.central_monitor.module_editor_disabled": "ʇı ʇıpǝ oʇ I∩⅁ sıɥʇ uǝdo-ǝɹ ǝsɐǝןd 'ǝןnpoɯ ǝɥʇ pǝbuɐɥɔ ʎןʇuǝɔǝɹ noʎ", + "gtceu.gui.central_monitor.pause": "˙unɹ ǝq ʇ,uoʍ ǝpoɔ puɐ 'pǝʇɐpdn ǝq ʇ,uoʍ ʇxǝ⟘\n˙uoıʇnɔǝxǝ ɹǝpןoɥǝɔɐןd ǝsnɐԀ", + "gtceu.gui.central_monitor.resume": "˙uoıʇnɔǝxǝ ɹǝpןoɥǝɔɐןd ǝsnɐdu∩", + "gtceu.gui.central_monitor.right_click": "˙ʇǝbɹɐʇ ɐ ǝq uɐɔ ʞɔoןq Ɩ ʎןuO ˙ʇı buıʞɔıןɔ-ʇɥbıɹ ʎq ʞɔoןq ɐ ʇɔǝןǝS", + "gtceu.gui.central_monitor.target": "˙ǝןnpoɯ ʇxǝʇ ɐ uı sɹǝpןoɥǝɔɐןd ɥʇıʍ pǝsn ǝq oʇ 'ʇǝbɹɐʇ ɐ pǝɹǝpısuoɔ sı ʎɐʍ sıɥʇ pǝʇɔǝןǝs ʞɔoןq ǝɥ⟘", + "gtceu.gui.central_monitor.text_module_help": "\n:%0ϛ< sı ʎbɹǝuǝ uǝɥʍ ןɐubıs ǝuoʇspǝɹ ɐ spuǝs puɐ oɟuı ʎbɹǝuǝ ǝɯos sʎɐןdsıp ʇɐɥʇ 'sɹǝpןoɥǝɔɐןd ɟo ǝbɐsn ǝןdɯɐxǝ uɐ s,ǝɹǝH\n˙oɟuı ǝɹoɯ ɹoɟ ǝɹǝɥʇ ǝbɐd dןǝɥ ǝɥʇ ʇno ʞɔǝɥɔ 'ʍopuıʍ buıʇıpǝ dnoɹb ɹoʇıuoɯ ǝɥʇ uı ʇǝbɹɐʇ ɐ ʇɔǝןǝS\n˙SSԀ ɐ ɹo ɹǝɟɟnq ʎɹǝʇʇɐq ɐ ʎןןɐnsn 'ʞɔoןq ʇǝbɹɐʇ sʇı uı ʎbɹǝuǝ ɟo ʇunoɯɐ ǝɥʇ sʎɐןdsıp }ʎbɹǝuǝ{ ǝןdɯɐxǝ ɹoℲ ˙ʞɔoןqıʇןnɯ ɹoʇıuoɯ ןɐɹʇuǝɔ\nǝɥʇ ɟo ʇɹɐd sı ɹo sɹǝʌoɔ ʇdǝɔɔɐ uɐɔ ʇɐɥʇ ʞɔoןq ʎuɐ ʎןןɐɔısɐq sı ʇǝbɹɐʇ Ɐ ˙uoıʇɔunɟ oʇ ʇǝbɹɐʇ ɐ ǝʌɐɥ ʇsnɯ }ʎbɹǝuǝ{ ǝʞıן 'sɹǝpןoɥǝɔɐןd ǝɯoS\n˙ɔʇǝ 'suoıʇɐןnɔןɐɔ unɹ 'ʇnduı ǝuoʇspǝɹ pɐǝɹ/ʇndʇno ǝuoʇspǝɹ ɐ ʇǝs sɐ ɥɔns 'sbuıɥʇ ɹǝɥʇo ǝɯos op osןɐ uɐɔ ʎǝɥ⟘\n˙)ʎbɹǝuǝ ɟo ʇunoɯɐ ǝɥʇ ǝsɐɔ sıɥʇ uı( pɐǝʇsuı ǝnןɐʌ ɹıǝɥʇ ʎɐןdsıp ןןıʍ 'pǝʎɐןdsıp uǝɥʍ ʇɐɥʇ \"}ʎbɹǝuǝ{\" ǝʞıן sbuıɹʇs ǝɹɐ sɹǝpןoɥǝɔɐןԀ\n˙sɹǝpןoɥǝɔɐןd ǝʌɐɥ uɐɔ ʇɐɥʇ ʇxǝʇ sʎɐןdsıp ǝןnpoɯ sıɥ⟘", "gtceu.gui.central_monitor.text_scale": "ǝןɐɔs ʇxǝ⟘", + "gtceu.gui.central_monitor.update_once": "˙ǝɔuo ʎןʇɔɐxǝ ʇı uı sɹǝpןoɥǝɔɐןd ןןɐ unɹ puɐ ʇxǝʇ ǝʇɐpd∩", + "gtceu.gui.central_monitor.url": ":Ꞁᴚ∩ ǝbɐɯı ʇnduI", "gtceu.gui.charger_slot.tooltip.0": "ɹ§ʇoןS ɹǝbɹɐɥƆɟ§", "gtceu.gui.charger_slot.tooltip.1": "ɹ§sǝıɹǝʇʇɐq %s ɯoɹɟ ɹǝʍod sʍɐɹᗡㄥ§", "gtceu.gui.charger_slot.tooltip.2": "sǝıɹǝʇʇɐq puɐ sןooʇ %s sǝbɹɐɥƆㄥ§", @@ -2392,8 +2444,7 @@ "gtceu.gui.computer_monitor_cover.placeholder_reference.1": ")oɟuı ǝɹoɯ ɹoɟ ɹǝʌoɥ(", "gtceu.gui.computer_monitor_cover.second_page_textbox_tooltip.0": "˙ǝɹǝɥ ,}{, %s ɟo ǝɔɐןd uı pǝsn ǝq oʇ ɹǝpןoɥǝɔɐןd ʇnduI", "gtceu.gui.computer_monitor_cover.second_page_textbox_tooltip.1": "˙sǝxoq ʇxǝʇ ǝsǝɥʇ uı ,ʎʇıɔɐdɐƆʎbɹǝuǝ, puɐ ,ʎbɹǝuǝ, puɐ ,∩Ǝ }{/}{ :ʎbɹǝuƎ, buıɹʇs ɐ ǝʌɐɥ uɐɔ noʎ 'ǝןdɯɐxǝ ɹoℲ", - "gtceu.gui.computer_monitor_cover.slot_tooltip.0": "ǝɔuǝɹǝɟǝɹ uɐɔ sɹǝpןoɥǝɔɐןd ǝɯos ʇɐɥʇ sɯǝʇı ɹoɟ ʇoןs Ɐ", - "gtceu.gui.computer_monitor_cover.slot_tooltip.1": "%d :ɹǝqɯnu ʇoןS", + "gtceu.gui.computer_monitor_cover.slot_tooltip": "\n%d :ɹǝqɯnu ʇoןS\nǝɔuǝɹǝɟǝɹ uɐɔ sɹǝpןoɥǝɔɐןd ǝɯos ʇɐɥʇ sɯǝʇı ɹoɟ ʇoןs Ɐ", "gtceu.gui.computer_monitor_cover.update_interval": ")sʞɔıʇ uı( ןɐʌɹǝʇuı ǝʇɐpd∩", "gtceu.gui.config_slot": "ɹ§ʇoןS bıɟuoƆɟ§", "gtceu.gui.config_slot.auto_pull_managed": "ןןnԀ-oʇnⱯ ʎq pǝbɐuɐW ㄥ§:pǝןqɐsıᗡㄣ§", @@ -2435,8 +2486,6 @@ "gtceu.gui.fluid_amount": ":ʇunoɯⱯ pınןℲ", "gtceu.gui.fluid_auto_input.tooltip.disabled": "pǝןqɐsıᗡ ʇnduI-oʇnⱯ pınןℲ", "gtceu.gui.fluid_auto_input.tooltip.enabled": "pǝןqɐuƎ ʇnduI-oʇnⱯ pınןℲ", - "gtceu.gui.fluid_auto_output.allow_input.disabled": "ǝpıs ʇndʇno ǝɥʇ ɯoɹɟ ʇnduı spınןɟ ǝןqɐsıp", - "gtceu.gui.fluid_auto_output.allow_input.enabled": "ǝpıs ʇndʇno ǝɥʇ ɯoɹɟ ʇnduı spınןɟ ʍoןןɐ", "gtceu.gui.fluid_auto_output.disabled": "pǝןqɐsıᗡɔ§ :ʇndʇnO oʇnⱯ pınןℲ", "gtceu.gui.fluid_auto_output.enabled": "pǝןqɐuƎɐ§ :ʇndʇnO oʇnⱯ pınןℲ", "gtceu.gui.fluid_auto_output.other_direction.0": "uoıʇɔǝɹıᗡ ɹǝɥʇO9§ :ʇndʇnO oʇnⱯ pınןℲ", @@ -2446,6 +2495,8 @@ "gtceu.gui.fluid_auto_output.tooltip.enabled": "pǝןqɐuƎ ʇndʇnO-oʇnⱯ pınןℲ", "gtceu.gui.fluid_auto_output.unselected.0": "ʇndʇnO oʇnⱯ pınןℲ", "gtceu.gui.fluid_auto_output.unselected.1": "˙ʇndʇno sʇı ǝɹnbıɟuoɔ oʇ ǝuıɥɔɐɯ ǝɥʇ ɟo ǝpıs ɐ ʇɔǝןǝSㄥ§", + "gtceu.gui.fluid_input_from_output.disabled": "pǝןqɐsıᗡɔ§ :ǝpıS ʇndʇnO ɯoɹɟ ʇnduI pınןℲ ʍoןןⱯ", + "gtceu.gui.fluid_input_from_output.enabled": "pǝןqɐuƎɐ§ :ǝpıS ʇndʇnO ɯoɹɟ ʇnduI pınןℲ ʍoןןⱯ", "gtceu.gui.fluid_lock.tooltip.disabled": "pǝןqɐsıᗡ buıʞɔoꞀ pınןℲ", "gtceu.gui.fluid_lock.tooltip.enabled": "pǝןqɐuƎ buıʞɔoꞀ pınןℲ", "gtceu.gui.fluid_voiding": "spınןℲ6§ buıpıoΛㄥ§", @@ -2454,8 +2505,6 @@ "gtceu.gui.fuel_amount": ":ʇunoɯⱯ ןǝnℲ", "gtceu.gui.item_auto_input.tooltip.disabled": "pǝןqɐsıᗡ ʇnduI-oʇnⱯ ɯǝʇI", "gtceu.gui.item_auto_input.tooltip.enabled": "pǝןqɐuƎ ʇnduI-oʇnⱯ ɯǝʇI", - "gtceu.gui.item_auto_output.allow_input.disabled": "ǝpıs ʇndʇno ǝɥʇ ɯoɹɟ ʇnduı sɯǝʇı ǝןqɐsıp", - "gtceu.gui.item_auto_output.allow_input.enabled": "ǝpıs ʇndʇno ǝɥʇ ɯoɹɟ ʇnduı sɯǝʇı ʍoןןɐ", "gtceu.gui.item_auto_output.disabled": "pǝןqɐsıᗡɔ§ :ʇndʇnO oʇnⱯ ɯǝʇI", "gtceu.gui.item_auto_output.enabled": "pǝןqɐuƎɐ§ :ʇndʇnO oʇnⱯ ɯǝʇI", "gtceu.gui.item_auto_output.other_direction.0": "uoıʇɔǝɹıᗡ ɹǝɥʇO9§ :ʇndʇnO oʇnⱯ ɯǝʇI", @@ -2465,6 +2514,9 @@ "gtceu.gui.item_auto_output.tooltip.enabled": "pǝןqɐuƎ ʇndʇnO-oʇnⱯ ɯǝʇI", "gtceu.gui.item_auto_output.unselected.0": "ʇndʇnO oʇnⱯ ɯǝʇI", "gtceu.gui.item_auto_output.unselected.1": "˙ʇndʇno sʇı ǝɹnbıɟuoɔ oʇ ǝuıɥɔɐɯ ǝɥʇ ɟo ǝpıs ɐ ʇɔǝןǝSㄥ§", + "gtceu.gui.item_collector.range": " :ǝbuɐᴚ", + "gtceu.gui.item_input_from_output.disabled": "pǝןqɐsıᗡɔ§ :ǝpıS ʇndʇnO ɯoɹɟ ʇnduI ɯǝʇI ʍoןןⱯ", + "gtceu.gui.item_input_from_output.enabled": "pǝןqɐuƎɐ§ :ǝpıS ʇndʇnO ɯoɹɟ ʇnduI ɯǝʇI ʍoןןⱯ", "gtceu.gui.item_lock.tooltip.disabled": "pǝןqɐsıᗡ buıʞɔoꞀ ɯǝʇI", "gtceu.gui.item_lock.tooltip.enabled": "pǝןqɐuƎ buıʞɔoꞀ ɯǝʇI", "gtceu.gui.item_voiding": "sɯǝʇI9§ buıpıoΛㄥ§", @@ -2474,8 +2526,13 @@ "gtceu.gui.machinemode.tab_tooltip": "ǝpoW ǝuıɥɔɐW ǝʌıʇɔɐ ǝbuɐɥƆ", "gtceu.gui.machinemode.title": "ǝpoW ǝuıɥɔɐW ǝʌıʇɔⱯ", "gtceu.gui.me_bus.auto_pull_button": "ƎW ɯoɹɟ buıןןnd ɯǝʇı ɔıʇɐɯoʇnɐ ǝןbboʇ oʇ ʞɔıןƆ", + "gtceu.gui.me_network.auto_pull_toggle": "ןןnԀ-oʇnⱯ ǝןbbo⟘", + "gtceu.gui.me_network.empty": "ʎʇdɯƎ", + "gtceu.gui.me_network.min_stack_size": ":ǝzıS ʞɔɐʇS uıW", "gtceu.gui.me_network.offline": "ɹ§ǝuıןɟɟOㄣ§ :snʇɐʇS ʞɹoʍʇǝN", "gtceu.gui.me_network.online": "ɹ§ǝuıןuOᄅ§ :snʇɐʇS ʞɹoʍʇǝN", + "gtceu.gui.me_network.stocking_settings": "sbuıʇʇǝS buıʞɔoʇS", + "gtceu.gui.me_network.ticks_per_cycle": ":ǝןɔʎƆ ɹǝԀ sʞɔı⟘", "gtceu.gui.multiblock.voiding_mode": ":ǝpoW buıpıoΛ", "gtceu.gui.no_voiding": "buıɥʇoN buıpıoΛㄥ§", "gtceu.gui.output_setting.title": "sbuıʇʇǝS ʇndʇnO", @@ -2490,6 +2547,7 @@ "gtceu.gui.overclock.off": "X", "gtceu.gui.overclock.range": "]%s '%s[ sɹǝı⟘ ǝןqɐןıɐʌⱯ", "gtceu.gui.overclock.title": "ɹǝı⟘ ʞɔoןɔɹǝʌO", + "gtceu.gui.pattern_buffer.set_custom_name": " :ǝɯɐN ɯoʇsnƆ ʇǝS", "gtceu.gui.silktouch.disabled.0": "˙ǝןqɐuƎ oʇ ʞɔıןƆ :pǝןqɐsıᗡ ɥɔno⟘ ʞןıS", "gtceu.gui.silktouch.disabled.1": "˙ǝuıɥɔɐɯ ǝןpı uɐ sǝɹınbǝɹ buıɥɔʇıʍSㄥ§", "gtceu.gui.silktouch.enabled.0": "˙ǝןqɐsıᗡ oʇ ʞɔıןƆ :pǝןqɐuƎ ɥɔno⟘ ʞןıS", @@ -2503,11 +2561,13 @@ "gtceu.gui.toggle_view.disabled": ")spınןℲ( ʍǝıΛ ǝןbbo⟘", "gtceu.gui.toggle_view.enabled": ")sɯǝʇI( ʍǝıΛ ǝןbbo⟘", "gtceu.gui.waiting_list": ":ǝnǝnὉ buıpuǝS", + "gtceu.gui.waiting_list_empty": "ʎʇdɯƎᄅ§ :ǝnǝnὉ buıpuǝS", "gtceu.implosion_compressor": "ɹossǝɹdɯoƆ uoısoןdɯI", "gtceu.io.both": "ɥʇoᗺ", "gtceu.io.export": "ʇɹodxƎ", "gtceu.io.import": "ʇɹodɯI", "gtceu.io.none": "ǝuoN", + "gtceu.item.tooltip.image_url": "%s :Ꞁᴚ∩ ǝbɐɯI", "gtceu.item_filter.empty_item": ")ɯǝʇI oN( ʎʇdɯƎ", "gtceu.item_filter.footer": "ǝpıɹɹǝʌo oʇ ɯǝʇı ɥʇıʍ ʞɔıןƆǝ§", "gtceu.item_list.item_stored": "%d :pǝɹoʇSㄥ§", @@ -2757,6 +2817,7 @@ "gtceu.machine.ev_sifter.tooltip": "buıʇɟıs dǝǝʞ puɐ ɯןɐɔ ʎɐʇSㄥ§", "gtceu.machine.ev_thermal_centrifuge.tooltip": "ʎןǝsıɔǝɹd ǝɹoɯ sǝɹO buıʇɐɹɐdǝSㄥ§", "gtceu.machine.ev_wiremill.tooltip": "ʎןʇuǝıɔıɟɟǝ ǝɹoɯ sǝɹıM sǝɔnpoɹԀㄥ§", + "gtceu.machine.exploded": ")%d '%d '%d( ʇɐ pǝpoןdxǝ %s", "gtceu.machine.extreme_combustion_engine.tooltip": "ɹǝsɐǝןǝᴚ ʎbɹǝuƎ ןɐɔıɯǝɥƆ ǝɯǝɹʇxƎ", "gtceu.machine.fisher.requirement": "˙ʍoןǝq ʎןʇɔǝɹıp ɹǝʇɐʍ ɟo ǝɹɐnbs pǝɹǝʇuǝɔ %dx%d ɐ sǝɹınbǝᴚ", "gtceu.machine.fisher.speed": "sʞɔıʇ %d ʎɹǝʌǝ buıɥʇǝɯos sǝɥɔʇɐƆ", @@ -3034,19 +3095,16 @@ "gtceu.machine.me_import_item_hatch.configs.tooltip": "ʞɔoʇs uı sǝdʎʇ ɯǝʇı 9Ɩ sdǝǝʞ", "gtceu.machine.miner.chunkradius": "%d :snıpɐᴚ ʞunɥƆ", "gtceu.machine.miner.fluid_usage": "˙ʞɔoןɔɹǝʌo ɹǝd pǝןqnop 'ㄥ§%sɟ§ ɟoㄥ§ ʇ/ᗺɯ %dɟ§ sǝs∩", - "gtceu.machine.miner.minex": "%d :Xɯ", - "gtceu.machine.miner.miney": "%d :ʎɯ", - "gtceu.machine.miner.minez": "%d :Zɯ", "gtceu.machine.miner.multi.description": "˙ǝɹo ɟo ʎʇıʇuɐnb ǝbnɥ sǝɔnpoɹd puɐ ɐǝɹɐ ǝbɹɐן ɐ sɹǝʌoɔ ʇɐɥʇ ǝuıɥɔɐɯ buıuıɯ ʞɔoןqıʇןnɯ Ɐ", "gtceu.machine.miner.multi.modes": "˙sǝpoW pǝubıןⱯ ʞunɥƆ puɐ ɥɔno⟘ ʞןıS sɐH", "gtceu.machine.miner.multi.production": "˙ㄥ§ɹoʇɐɹǝɔɐWɟ§ ɐ uɐɥʇ ǝɹo pǝɥsnɹɔ ǝɹoɯ ㄥ§xƐɟ§ sǝɔnpoɹԀ", "gtceu.machine.miner.per_block": "ʞɔoןᗺ ɹǝdㄥ§ %dsɟ§ sǝʞɐʇㄥ§", "gtceu.machine.miner.progress": "%d/%d :ssǝɹboɹԀ", "gtceu.machine.miner.radius": "%d :snıpɐᴚ", - "gtceu.machine.miner.startx": "%d :Xs", - "gtceu.machine.miner.starty": "%d :ʎs", - "gtceu.machine.miner.startz": "%d :Zs", "gtceu.machine.miner.tooltip": "ɐǝɹɐㄥ§ %sx%sɟ§ sɐ sʇɹɐʇS ¡ɹǝuıW ǝɥʇ ʍoןǝq sǝɹo sǝuıWㄥ§", + "gtceu.machine.miner.x": "%d :Xɯ '%d :Xs", + "gtceu.machine.miner.y": "%d :ʎɯ '%d :ʎs", + "gtceu.machine.miner.z": "%d :Zɯ '%d :Zs", "gtceu.machine.muffle.off": "pǝןqɐsıᗡ :buıןɟɟnW punoS", "gtceu.machine.muffle.on": "pǝןqɐuƎ :buıןɟɟnW punoS", "gtceu.machine.muffler_hatch.tooltip.0": "sǝuıɥɔɐɯ ɯoɹɟ ǝʇsɐʍ sɹǝʌoɔǝᴚ", @@ -3101,6 +3159,7 @@ "gtceu.machine.opv_gas_collector.tooltip": "uoısuǝɯıp ǝɥʇ uo buıpuǝdǝp ǝsɹǝʌıun ǝɥʇ ɯoɹɟ sɐ⅁ sʇɔǝןןoƆㄥ§", "gtceu.machine.opv_rock_crusher.tooltip": "ɹǝqɯɐɥƆ uoıʇɐɯɹoℲ ɔıuɐɔןoΛㄥ§", "gtceu.machine.parallel_hatch.display": "ʞɔoןqıʇןnɯ ǝɥʇ ɟo ןǝןןɐɹɐd ɯnɯıxɐɯ ǝɥʇ ʇsnظpⱯ", + "gtceu.machine.parallel_hatch.parallel_ui": "sןǝןןɐɹɐԀ", "gtceu.machine.parallel_hatch_mk5.tooltip": "˙ןǝןןɐɹɐd uı sǝdıɔǝɹ ㄣ oʇ dn unɹ oʇ sʍoןןⱯ", "gtceu.machine.parallel_hatch_mk6.tooltip": "˙ןǝןןɐɹɐd uı sǝdıɔǝɹ 9Ɩ oʇ dn unɹ oʇ sʍoןןⱯ", "gtceu.machine.parallel_hatch_mk7.tooltip": "˙ןǝןןɐɹɐd uı sǝdıɔǝɹ ㄣ9 oʇ dn unɹ oʇ sʍoןןⱯ", @@ -3263,6 +3322,36 @@ "gtceu.mode.both": "ɹ§)ɯǝʇI puⱯ pınןℲ( ɥʇoᗺp§", "gtceu.mode.fluid": "ɹ§pınןℲ6§", "gtceu.mode.item": "ɹ§ɯǝʇI9§", + "gtceu.module.advanced_jetpack": ")ǝןnpoɯ ʎɹǝʇʇɐq ʎuɐ sǝɹınbǝɹ( ʞɔɐdʇǝظ pǝɔuɐʌpɐ uɐ ǝʞıן ʞɹoʍ ǝʇɐןdʇsǝɥɔ ǝɥʇ sǝʞɐW", + "gtceu.module.attack_damage": "%s%% ʎq ǝbɐɯɐp ʞɔɐʇʇɐ sǝsɐǝɹɔuI", + "gtceu.module.attack_speed": "%s%% ʎq pǝǝds ʞɔɐʇʇɐ sǝsɐǝɹɔuI", + "gtceu.module.battery": ")s,ʎɹǝʇʇɐq ǝɥʇ oʇ ןɐnbǝ sı ʎʇıɔɐdɐɔ( ʎʇıɔɐdɐɔ sʇı sǝsɐǝɹɔuı ɹo ʎbɹǝuǝ ǝɹoʇs oʇ ɯǝʇı ǝɥʇ sʍoןןⱯ", + "gtceu.module.block_reach": "sʞɔoןq %s ʎq ɥɔɐǝɹ ʞɔoןq sǝsɐǝɹɔuI", + "gtceu.module.block_reach.short": "sʞɔoןq %s ʎq ˙˙˙", + "gtceu.module.creative_flight": ")buıʎןɟ ǝןıɥʍ ʇ/∩Ǝ %s sǝɯnsuoɔ( ʇɥbıןɟ ǝʌıʇɐǝɹɔ sʍoןןⱯ", + "gtceu.module.damage_block": ")ǝןnpoɯ ʎɹǝʇʇɐq ʎuɐ sǝɹınbǝɹ 'ԀH ɹǝd ∩Ǝ %s( ∩Ǝ ɥʇıʍ ǝbɐɯɐp ɟo ʇunoɯɐ ʎuɐ sʞɔoןᗺ", + "gtceu.module.damage_block.short": "ԀH ɹǝd ∩Ǝ %s", + "gtceu.module.fluid_storage": ")s,ʞuɐʇ ǝɥʇ oʇ ןɐnbǝ sı ʎʇıɔɐdɐɔ( ʎʇıɔɐdɐɔ sʇı sǝsɐǝɹɔuı ɹo spınbıן ǝɹoʇs oʇ ɯǝʇı ǝɥʇ sʍoןןⱯ", + "gtceu.module.gui.charge": ":ǝbɹɐɥƆ", + "gtceu.module.gui.enabled": ":pǝןqɐuƎ", + "gtceu.module.gui.jump_boost": ":ʇsooᗺ", + "gtceu.module.gui.power": ":ɹǝʍoԀ", + "gtceu.module.jetpack": ")ǝןnpoɯ ʎɹǝʇʇɐq ʎuɐ sǝɹınbǝɹ( ʞɔɐdʇǝظ ɐ ǝʞıן ʞɹoʍ ǝʇɐןdʇsǝɥɔ ǝɥʇ sǝʞɐW", + "gtceu.module.jump": "sʞɔoןq %s ʎq ʇɥbıǝɥ dɯnظ sǝsɐǝɹɔuI", + "gtceu.module.liquid_fuel_jetpack": ")ǝןnpoɯ ǝbɐɹoʇs pınןɟ ʎuɐ sǝɹınbǝɹ( ʞɔɐdʇǝظ pǝןǝnɟ pınbıן ɐ ǝʞıן ʞɹoʍ ǝʇɐןdʇsǝɥɔ ǝɥʇ sǝʞɐW", + "gtceu.module.movement_speed": "%s%% ʎq pǝǝds ʇuǝɯǝʌoɯ ןןɐ sǝsɐǝɹɔuI", + "gtceu.module.nightvision": ")ǝʌıʇɔɐ ǝןıɥʍ ʇ/∩Ǝ %s sǝɯnsuoɔ( uoısıʌ ʇɥbıu sǝpıʌoɹԀ", + "gtceu.module.ppe": "sǝɔǝıd ɹoɯɹɐ ןןɐ oʇ pǝıןddɐ ɟı spɹɐzɐɥ ןɐʇuǝɯuoɹıʌuǝ ɯoɹɟ uoıʇɔǝʇoɹd sǝpıʌoɹԀ", + "gtceu.module.sensor": ")ɹǝʎɐןd ǝɥʇ ʎq pǝɔɐןd sǝuıɥɔɐɯ ɹoɟ( suoısoןdxǝ ǝuıɥɔɐɯ sʇɹodǝᴚ", + "gtceu.module.short_percentage": "%s%% ʎq ˙˙˙", + "gtceu.module.sneak_speed": "%s%% ʎq pǝǝds buıʞɐǝus sǝsɐǝɹɔuI", + "gtceu.module.speed": "%s%% ʎq pǝǝds ʇuıɹds sǝsɐǝɹɔuI", + "gtceu.module.step_height": "sʞɔoןq %s ʎq ʇɥbıǝɥ dǝʇs sǝsɐǝɹɔuI", + "gtceu.module.swim_speed": "%s%% ʎq pǝǝds ɯıʍs sǝsɐǝɹɔuI", + "gtceu.module.wireless_charging": "ʇı uo buıʞɔıןɔ-ʇɥbıɹ ʎq ɹǝbɹɐɥɔ ɐ oʇ puıq ')xɐɯ %s ⱯƖ( sʞɔoןq %s ɟo ǝbuɐɹ ǝɥʇ uı buıbɹɐɥɔ ssǝןǝɹıʍ sʍoןןⱯ", + "gtceu.module.wireless_charging.interdimensional": "ʇuǝsǝɹd sı ɹoʇɐɹǝuǝb pןǝıɟ %s ʇsɐǝן ʇɐ uɐ ɟı ןɐuoısuǝɯıpɹǝʇuı 'xɐɯ %s ⱯƖ 'sʞɔoןq %s", + "gtceu.module.wireless_charging.short": "xɐɯ %s ⱯƖ 'sʞɔoןq %s", + "gtceu.modules": ":sǝןnpoW", "gtceu.muffler.recovery_tooltip": "%d%%ɟ§ :ǝɔuɐɥƆ ʎɹǝʌoɔǝᴚq§", "gtceu.multiblock.active_transformer.average_in": "ʇ/∩Ǝ %sɟ§ :ʇnduI ˙bʌⱯq§", "gtceu.multiblock.active_transformer.average_out": "ʇ/∩Ǝ %sɟ§ :ʇndʇnO ˙bʌⱯq§", @@ -3324,10 +3413,9 @@ "gtceu.multiblock.hpca.info_bridging_disabled": "pǝןqɐsıᗡ buıbpıɹᗺ", "gtceu.multiblock.hpca.info_bridging_enabled": "pǝןqɐuƎ buıbpıɹᗺ", "gtceu.multiblock.hpca.info_coolant_name": "ʇuɐןooƆ ᗺƆԀ", + "gtceu.multiblock.hpca.info_cooling_demand": "%d / %s :puɐɯǝᗡ buıןooƆ", "gtceu.multiblock.hpca.info_max_computation": "%s :ʇ/∩MƆ xɐW", "gtceu.multiblock.hpca.info_max_coolant_required": "%s :pǝpǝǝN ʇuɐןooƆ", - "gtceu.multiblock.hpca.info_max_cooling_available": "%s :ǝןqɐןıɐʌⱯ buıןooƆ", - "gtceu.multiblock.hpca.info_max_cooling_demand": "%s :puɐɯǝᗡ buıןooƆ", "gtceu.multiblock.hpca.temperature": "%s :ǝɹnʇɐɹǝdɯǝ⟘", "gtceu.multiblock.hpca.warning_low_cooling": "buıןooɔ ɥbnouǝ ʇoN -", "gtceu.multiblock.hpca.warning_multiple_bridges": ")ʇıɟǝuǝq ןɐuoıʇıppɐ ou sǝpıʌoɹd( ǝɹnʇɔnɹʇs uı sǝbpıɹq ǝןdıʇןnW -", @@ -3480,9 +3568,9 @@ "gtceu.multiblock.turbine.rotor_durability": "%s%% :ʎʇıןıqɐɹnᗡ ɹoʇoᴚ", "gtceu.multiblock.turbine.rotor_speed": "WԀᴚ %s/%s :pǝǝdS ɹoʇoᴚ", "gtceu.multiblock.universal.distinct": ":sǝsnᗺ ʇɔuıʇsıᗡ", + "gtceu.multiblock.universal.distinct.disabled": "pǝןqɐsıᗡǝ§ :sǝsnᗺ ʇɔuıʇsıᗡ", + "gtceu.multiblock.universal.distinct.enabled": "pǝןqɐuƎǝ§ :sǝsnᗺ ʇɔuıʇsıᗡ", "gtceu.multiblock.universal.distinct.info": "˙ɔʇǝ 'sǝdɐɥS ɹǝpnɹʇxƎ 'sʇınɔɹıƆ pǝɯɯɐɹboɹԀ ǝʞıן sbuıɥʇ ɹoɟ ןnɟǝs∩ ˙dnʞooן ǝdıɔǝɹ ɹoɟ ɹǝɥʇo ɥɔɐǝ ɯoɹɟ ʇɔuıʇsıp ʎןןnɟ sɐ pǝʇɐǝɹʇ ǝq ןןıʍ snᗺ ʇnduI ɯǝʇI ɥɔɐǝ 'pǝןqɐuǝ ɟI", - "gtceu.multiblock.universal.distinct.no": "oN", - "gtceu.multiblock.universal.distinct.yes": "sǝʎ", "gtceu.multiblock.universal.has_problems": "¡sɯǝןqoɹԀ ǝɔuɐuǝʇuıɐW sɐH", "gtceu.multiblock.universal.has_problems_header": ":ɥɔʇɐH ǝɔuɐuǝʇuıɐW ɐ uı sǝnssı buıʍoןןoɟ ǝɥʇ xıℲ", "gtceu.multiblock.universal.muffler_obstructed": "¡pǝʇɔnɹʇsqO sı ɥɔʇɐH ɹǝןɟɟnW", @@ -3513,6 +3601,14 @@ "gtceu.packer": "ɹǝʞɔɐԀ", "gtceu.part_sharing.disabled": "pǝןqɐsıᗡㄣ§ buıɹɐɥS ʞɔoןqıʇןnW", "gtceu.part_sharing.enabled": "pǝןqɐuƎɐ§ buıɹɐɥS ʞɔoןqıʇןnW", + "gtceu.placeholder_editor.constant_value": "˙ʇuɐʇsuoɔ ɐ ɥʇıʍ ʇı buıɔɐןdǝɹ ɹǝpısuoƆ\n˙ʇןnsǝɹ ǝɯɐs ǝɥʇ oʇ sǝʇɐnןɐʌǝ sʎɐʍןɐ uoıssǝɹdxǝ sıɥ⟘", + "gtceu.placeholder_editor.extra_closing_bracket": "ʇǝʞɔɐɹq buısoןɔ ɐɹʇxƎ", + "gtceu.placeholder_editor.no_placeholder": "ʇsıxǝ ʇou sǝop ,%s, ǝɯɐu ɥʇıʍ ɹǝpןoɥǝɔɐןԀ", + "gtceu.placeholder_editor.unclosed_bracket": ")\"}\"( ʇǝʞɔɐɹq pǝsoןɔu∩", + "gtceu.placeholder_editor.unclosed_brackets": "pǝsoןɔun ǝɹɐ )\"}\"( sʇǝʞɔɐɹq %d", + "gtceu.placeholder_editor.unclosed_escape": ")\"],\"( ǝdɐɔsǝ pǝsoןɔu∩", + "gtceu.placeholder_editor.unclosed_escapes": "pǝsoןɔun ǝɹɐ )\"],\"( sǝdɐɔsǝ %d", + "gtceu.placeholder_editor.write_in_if": "˙\"}}\">ǝpoɔ‾ǝsןǝ<\" \">ǝpoɔ<\" >uoıʇıpuoɔ< ɟı{ ןɐʌǝ{\" ǝsn 'sıɥʇ pıoʌɐ o⟘\n˙ʇndʇno ǝuoʇspǝɹ ǝɔnpoɹd ןןıʍ \"}}ϛƖ ʇǝs ǝuoʇspǝɹ{ 0 ɟı{\" 'ǝןdɯɐxǝ ɹoɟ 'ʇɐɥʇ suɐǝɯ sıɥ⟘\n˙uoıʇıpuoɔ ǝɥʇ ɟo ssǝןpɹɐbǝɹ pǝʇnɔǝxǝ ǝɹɐ }ɟı{ ǝpısuı sɹǝpןoɥǝɔɐןԀ", "gtceu.placeholder_info.active.0": "˙ǝsıʍɹǝɥʇo 0 'ǝdıɔǝɹ ɐ buıuunɹ ʎןʇuǝɹɹnɔ sı oʇ pǝɥɔɐʇʇɐ sı ɹǝʌoɔ ǝɥʇ ʞɔoןq ǝɥʇ ɟı Ɩ ɐ suɹnʇǝᴚ", "gtceu.placeholder_info.active.1": ":ǝbɐs∩", "gtceu.placeholder_info.active.2": "ǝdıɔǝɹ buıuunɹ ʎןʇuǝɹɹnɔ ɐ s,ǝɹǝɥʇ ɹǝɥʇǝɥʍ >- }ǝʌıʇɔɐ{ ", @@ -4126,6 +4222,7 @@ "item.gtceu.cpu_chip.tooltip": "ʇıu∩ buıssǝɔoɹԀ ןɐɹʇuǝƆㄥ§", "item.gtceu.cpu_wafer": "ɹǝɟɐM ∩ԀƆ", "item.gtceu.cpu_wafer.tooltip": "ʇıu∩ buıssǝɔoɹԀ ʍɐᴚㄥ§", + "item.gtceu.creative_flight_module": "ǝןnpoW uoıʇɐʇıʌɐɹ⅁", "item.gtceu.crushed_bentonite_ore": "ǝʇıuoʇuǝᗺ punoɹ⅁", "item.gtceu.crushed_cassiterite_sand_ore": "puɐS ǝʇıɹǝʇıssɐƆ punoɹ⅁", "item.gtceu.crushed_pitchblende_ore": "ǝpuǝןqɥɔʇıԀ punoɹ⅁", @@ -4271,6 +4368,7 @@ "item.gtceu.gray_glass_lens": ")ʎɐɹ⅁( suǝꞀ ssɐן⅁", "item.gtceu.green_dye_spray_can": ")uǝǝɹ⅁( uɐƆ ʎɐɹdS", "item.gtceu.green_glass_lens": ")uǝǝɹ⅁( suǝꞀ ssɐן⅁", + "item.gtceu.gui_module": "ǝןnpoW ın⅁", "item.gtceu.hammer_extruder_mold.tooltip": "sɹǝɯɯɐH buıʞɐɯ ɹoɟ ǝdɐɥS ɹǝpnɹʇxƎㄥ§", "item.gtceu.hazmat_boots": "sʇooᗺ ʇınS sןɐıɹǝʇɐW snopɹɐzɐH", "item.gtceu.hazmat_chestpiece": "ǝɔǝıdʇsǝɥƆ ʇınS sןɐıɹǝʇɐW snopɹɐzɐH", @@ -5764,6 +5862,33 @@ "metaarmor.tooltip.falldamage": "ǝbɐɯɐᗡ ןןɐℲ sǝıɟıןןnN", "metaarmor.tooltip.freezing": "buızǝǝɹℲ sʇuǝʌǝɹԀ", "metaarmor.tooltip.jump": "ǝɔuɐʇsıᗡ puɐ ʇɥbıǝH dɯnſ sǝsɐǝɹɔuI", + "metaarmor.tooltip.modifier": "%s :%s - ", + "metaarmor.tooltip.modifier.attack_damage": ")%s( ǝןnpoW ǝbɐɯɐᗡ ʞɔɐʇʇⱯ", + "metaarmor.tooltip.modifier.attack_speed": ")%s( ǝןnpoW pǝǝdS ʞɔɐʇʇⱯ", + "metaarmor.tooltip.modifier.battery": ")%s( ǝןnpoW ʎɹǝʇʇɐᗺ", + "metaarmor.tooltip.modifier.battery.hud.boots": "%s :ʎɹǝʇʇɐq sʇooᗺ", + "metaarmor.tooltip.modifier.battery.hud.chestplate": "%s :ʎɹǝʇʇɐq ǝʇɐןdʇsǝɥƆ", + "metaarmor.tooltip.modifier.battery.hud.helmet": "%s :ʎɹǝʇʇɐq ʇǝɯןǝH", + "metaarmor.tooltip.modifier.battery.hud.info": "∩Ǝ %s/%s buıɹoʇS", + "metaarmor.tooltip.modifier.battery.hud.leggings": "%s :ʎɹǝʇʇɐq sbuıbbǝꞀ", + "metaarmor.tooltip.modifier.block_reach": ")%s( ǝןnpoW ɥɔɐǝᴚ", + "metaarmor.tooltip.modifier.creative_flight": "ǝןnpoW ʇɥbıןℲ ǝʌıʇɐǝɹƆ", + "metaarmor.tooltip.modifier.damage_block": ")%s( ǝןnpoW pןǝıɥS ʎbɹǝuƎ", + "metaarmor.tooltip.modifier.empty": "ʎʇdɯƎ", + "metaarmor.tooltip.modifier.fluid_storage": ")%s( ǝbɐɹoʇs pınןɟ ןɐuoıʇıppⱯ", + "metaarmor.tooltip.modifier.fluid_storage.tooltip": "%s ɟo ᗺɯ %s/%s buıɹoʇS", + "metaarmor.tooltip.modifier.jetpack": ")%s( ǝןnpoW ʞɔɐdʇǝſ", + "metaarmor.tooltip.modifier.jump": ")%s( ǝןnpoW dɯnſ", + "metaarmor.tooltip.modifier.movement_speed": ")%s( ǝןnpoW pǝǝdS ʇuǝɯǝʌoW", + "metaarmor.tooltip.modifier.sensor": ")%s( ǝןnpoW buıʇɹodǝᴚ uoısoןdxƎ", + "metaarmor.tooltip.modifier.sneak_speed": ")%s( ǝןnpoW pǝǝdS ʞɐǝuS", + "metaarmor.tooltip.modifier.speed": ")%s( ǝןnpoW pǝǝdS buıuunᴚ", + "metaarmor.tooltip.modifier.step_height": ")%s( ǝןnpoW ʇɥbıǝH dǝʇS", + "metaarmor.tooltip.modifier.swim_speed": ")%s( ǝןnpoW pǝǝdS ɯıʍS", + "metaarmor.tooltip.modifier.wireless_charging": ")%s( ǝןnpoW buıbɹɐɥƆ ssǝןǝɹıM", + "metaarmor.tooltip.modifier_slot.tiered": ")%s( pǝɹǝı⟘", + "metaarmor.tooltip.modifier_slot.universal": "ןɐsɹǝʌıu∩", + "metaarmor.tooltip.modifiers": ":sʇoןs ǝןnpoW", "metaarmor.tooltip.potions": "sʇɔǝɟɟƎ ןnɟɯɹɐH sǝıɟıןןnN", "metaarmor.tooltip.speed": "pǝǝdS buıuunᴚ sǝsɐǝɹɔuI", "metaarmor.tooltip.stepassist": "ʇsıssⱯ-dǝʇS sǝpıʌoɹԀ", diff --git a/src/generated/resources/assets/gtceu/lang/en_us.json b/src/generated/resources/assets/gtceu/lang/en_us.json index c9d6d18f758..18edb1dd561 100644 --- a/src/generated/resources/assets/gtceu/lang/en_us.json +++ b/src/generated/resources/assets/gtceu/lang/en_us.json @@ -58,6 +58,7 @@ "behavior.prospector.not_enough_energy": "Not Enough Energy!", "behavior.toggle_energy_consumer.tooltip": "Use to toggle mode", "behaviour.boor.by": "by %s", + "behaviour.charger_linked": "Linked charger", "behaviour.hammer": "Turns on and off Muffling for Machines (by hitting them)", "behaviour.hoe": "Can till dirt", "behaviour.lighter.fluid.tooltip": "Can light things on fire with Butane or Propane", @@ -211,6 +212,7 @@ "block.gtceu.empty_tier_ii_battery": "Empty Tier II Capacitor", "block.gtceu.empty_tier_iii_battery": "Empty Tier III Capacitor", "block.gtceu.engine_intake_casing": "Engine Intake Casing", + "block.gtceu.equipment_foundry": "Equipment Foundry", "block.gtceu.ev_16a_energy_converter": "§5EV§r 16§eA§r Energy Converter", "block.gtceu.ev_1a_energy_converter": "§5EV§r 1§eA§r Energy Converter", "block.gtceu.ev_4a_energy_converter": "§5EV§r 4§eA§r Energy Converter", @@ -1133,6 +1135,8 @@ "block.gtceu.substation_capacitor.tooltip_filled": "§cEnergy Capacity: §f%d EU", "block.gtceu.superconducting_coil": "Superconducting Coil Block", "block.gtceu.tempered_glass": "Tempered Glass", + "block.gtceu.test_mui": "Test Mui", + "block.gtceu.test_mui_new": "Test Mui New", "block.gtceu.the_end_marker": "The End", "block.gtceu.the_nether_marker": "The Nether", "block.gtceu.titanium_crate": "Titanium Crate", @@ -1777,7 +1781,9 @@ "config.gtceu.option.coloredWireOutline": "coloredWireOutline", "config.gtceu.option.compat": "compat", "config.gtceu.option.createCompat": "createCompat", + "config.gtceu.option.cursorColor": "cursorColor", "config.gtceu.option.debug": "debug", + "config.gtceu.option.debugUI": "debugUI", "config.gtceu.option.debugWorldgen": "debugWorldgen", "config.gtceu.option.defaultPaintingColor": "defaultPaintingColor", "config.gtceu.option.defaultUIColor": "defaultUIColor", @@ -1805,6 +1811,7 @@ "config.gtceu.option.energyUsageMultiplier": "energyUsageMultiplier", "config.gtceu.option.environmentalHazardDecayRate": "environmentalHazardDecayRate", "config.gtceu.option.environmentalHazards": "environmentalHazards", + "config.gtceu.option.escRestoresLastText": "escRestoresLastText", "config.gtceu.option.euToFeRatio": "euToFeRatio", "config.gtceu.option.extractorRecyclingYield": "extractorRecyclingYield", "config.gtceu.option.feToEuRatio": "feToEuRatio", @@ -1856,6 +1863,7 @@ "config.gtceu.option.meHatchEnergyUsage": "meHatchEnergyUsage", "config.gtceu.option.minerSpeed": "minerSpeed", "config.gtceu.option.minimap": "minimap", + "config.gtceu.option.mui": "mui", "config.gtceu.option.nanoSaber": "nanoSaber", "config.gtceu.option.nanoSaberBaseDamage": "nanoSaberBaseDamage", "config.gtceu.option.nanoSaberDamageBoost": "nanoSaberDamageBoost", @@ -1876,6 +1884,7 @@ "config.gtceu.option.oreVeinGridSize": "oreVeinGridSize", "config.gtceu.option.oreVeinRandomOffset": "oreVeinRandomOffset", "config.gtceu.option.oreVeins": "oreVeins", + "config.gtceu.option.outlineColor": "outlineColor", "config.gtceu.option.ownerOPBypass": "ownerOPBypass", "config.gtceu.option.prospectorEnergyUseMultiplier": "prospectorEnergyUseMultiplier", "config.gtceu.option.quantumTank": "quantumTank", @@ -1889,14 +1898,28 @@ "config.gtceu.option.renderGrowingPlants": "renderGrowingPlants", "config.gtceu.option.renderer": "renderer", "config.gtceu.option.replaceMinedBlocksWith": "replaceMinedBlocksWith", + "config.gtceu.option.replaceVanillaTooltips": "replaceVanillaTooltips", "config.gtceu.option.replaceWithCobbleVersion": "replaceWithCobbleVersion", "config.gtceu.option.requireGTToolsForBlocks": "requireGTToolsForBlocks", "config.gtceu.option.rngDamageElectricTools": "rngDamageElectricTools", "config.gtceu.option.rubberTreeSpawnChance": "rubberTreeSpawnChance", "config.gtceu.option.sandOresFall": "sandOresFall", + "config.gtceu.option.scale": "scale", "config.gtceu.option.shouldWeatherOrTerrainExplosion": "shouldWeatherOrTerrainExplosion", "config.gtceu.option.showDimensionTier": "showDimensionTier", + "config.gtceu.option.showExtra": "showExtra", + "config.gtceu.option.showHovered": "showHovered", + "config.gtceu.option.showOutline": "showOutline", + "config.gtceu.option.showParent": "showParent", + "config.gtceu.option.showParentOutline": "showParentOutline", + "config.gtceu.option.showParentPos": "showParentPos", + "config.gtceu.option.showParentSize": "showParentSize", + "config.gtceu.option.showParentWidgetTheme": "showParentWidgetTheme", + "config.gtceu.option.showPos": "showPos", + "config.gtceu.option.showSize": "showSize", + "config.gtceu.option.showWidgetTheme": "showWidgetTheme", "config.gtceu.option.smallBoilers": "smallBoilers", + "config.gtceu.option.smoothProgressBar": "smoothProgressBar", "config.gtceu.option.solarBoilerBaseOutput": "solarBoilerBaseOutput", "config.gtceu.option.solidBoilerBaseOutput": "solidBoilerBaseOutput", "config.gtceu.option.sprayCanChainLength": "sprayCanChainLength", @@ -1908,17 +1931,21 @@ "config.gtceu.option.surfaceRockProspectRange": "surfaceRockProspectRange", "config.gtceu.option.tankItemFluidPreview": "tankItemFluidPreview", "config.gtceu.option.temperaturesInCelsius": "temperaturesInCelsius", + "config.gtceu.option.textColor": "textColor", "config.gtceu.option.titaniumBoilerHeatSpeed": "titaniumBoilerHeatSpeed", "config.gtceu.option.titaniumBoilerMaxTemperature": "titaniumBoilerMaxTemperature", "config.gtceu.option.toggle": "toggle", "config.gtceu.option.toolCraftingSounds": "toolCraftingSounds", "config.gtceu.option.toolUseSounds": "toolUseSounds", "config.gtceu.option.tools": "tools", + "config.gtceu.option.tooltipPos": "tooltipPos", "config.gtceu.option.treeFellingDelay": "treeFellingDelay", "config.gtceu.option.tungstensteelBoilerHeatSpeed": "tungstensteelBoilerHeatSpeed", "config.gtceu.option.tungstensteelBoilerMaxTemperature": "tungstensteelBoilerMaxTemperature", + "config.gtceu.option.ui": "ui", "config.gtceu.option.universalHazards": "universalHazards", "config.gtceu.option.updateIntervals": "updateIntervals", + "config.gtceu.option.useDarkThemeByDefault": "useDarkThemeByDefault", "config.gtceu.option.useVBO": "useVBO", "config.gtceu.option.voltageTierAdvImpeller": "voltageTierAdvImpeller", "config.gtceu.option.voltageTierAdvNanoSuit": "voltageTierAdvNanoSuit", @@ -2029,20 +2056,18 @@ "cover.conveyor.transfer_rate": "§7items/sec", "cover.detector_base.message_inverted_state": "Monitoring Status: Inverted", "cover.detector_base.message_normal_state": "Monitoring Status: Normal", - "cover.ender_fluid_link.incomplete_hex.0": "Inputted color is incomplete!", - "cover.ender_fluid_link.incomplete_hex.1": "It will be applied once complete (all 8 hex digits)", - "cover.ender_fluid_link.incomplete_hex.2": "Closing the gui will lose edits!", "cover.ender_fluid_link.iomode.disabled": "I/O Disabled", "cover.ender_fluid_link.iomode.enabled": "I/O Enabled", - "cover.ender_fluid_link.private.tooltip.disabled.0": "Switch to private tank mode", - "cover.ender_fluid_link.private.tooltip.disabled.1": "Private mode uses the player who originally placed the cover", - "cover.ender_fluid_link.private.tooltip.enabled": "Switch to public tank mode", "cover.ender_fluid_link.title": "Ender Fluid Link", - "cover.ender_fluid_link.tooltip.channel_description": "Set channel description with input text", - "cover.ender_fluid_link.tooltip.channel_name": "Set channel name with input text", - "cover.ender_fluid_link.tooltip.clear_button": "Clear channel description", - "cover.ender_fluid_link.tooltip.list_button": "Show channel list", "cover.ender_item_link.title": "Ender Item Link", + "cover.ender_link.description_empty": "Empty Description", + "cover.ender_link.private.tooltip": "Private mode: Only accessible to the player who placed this cover", + "cover.ender_link.protected.tooltip": "Protected Mode: Accessible to players on the same team.", + "cover.ender_link.public.tooltip": "Public mode: Accessible to all players", + "cover.ender_link.tooltip.channel_description": "Channel description", + "cover.ender_link.tooltip.channel_name": "Channel ID (32-bit hexadecimal value)", + "cover.ender_link.tooltip.clear_button": "Clear channel description", + "cover.ender_link.tooltip.list_button": "Show channel list", "cover.ender_redstone_link.title": "Ender Redstone Link", "cover.filter.blacklist.disabled": "Whitelist", "cover.filter.blacklist.enabled": "Blacklist", @@ -2080,6 +2105,7 @@ "cover.item_smart_filter.filtering_mode.electrolyzer": "Electrolyzer", "cover.item_smart_filter.filtering_mode.sifter": "Sifter", "cover.item_smart_filter.title": "Smart Item Filter", + "cover.machine_controller.control": "Controller Target", "cover.machine_controller.invert.disabled.0": "§eNormal§r - in this mode, the cover will require a signal weaker than the set redstone level to run", "cover.machine_controller.invert.enabled.0": "§eInverted§r - in this mode, the cover will require a signal stronger than the set redstone level to run", "cover.machine_controller.inverted": "Inverted", @@ -2192,6 +2218,7 @@ "death.attack.gtceu.wrench_iv": "%s had a wrench thrown into their plans by %s", "death.attack.gtceu.wrench_lv": "%s's pipes were loosened by %s", "effect.gtceu.weak_poison": "Weak Poison", + "emi.category.gtceu.equipment_foundry": "Equipment Foundry", "enchantment.damage.disjunction": "Disjunction", "enchantment.disjunction": "Disjunction", "enchantment.gtceu.disjunction.description": "Applies Weakness and Slowness to Ender-related mobs.", @@ -2235,6 +2262,10 @@ "gtceu.canner": "Canner", "gtceu.central_monitor.gui.create_group": "Create group", "gtceu.central_monitor.gui.currently_editing": "Currently editing: %s", + "gtceu.central_monitor.gui.data_slot": "Set slot number of data stick", + "gtceu.central_monitor.gui.group_editor": "Editing monitor group", + "gtceu.central_monitor.gui.group_name": "Name:", + "gtceu.central_monitor.gui.monitor_groups": "Monitor groups", "gtceu.central_monitor.gui.remove_from_group": "Remove from group", "gtceu.central_monitor.gui.set_target": "Set target", "gtceu.central_monitor.info_tooltip.0": "In order to use monitors, you have to split them into groups first. A group may only have 1 module in it.", @@ -2291,7 +2322,8 @@ "gtceu.creative.chest.ipc": "Items per Cycle", "gtceu.creative.chest.item": "Item", "gtceu.creative.chest.tpc": "Ticks per Cycle", - "gtceu.creative.computation.average": "Average Requested CWUt", + "gtceu.creative.computation.average": "Average CWU/tick: %d", + "gtceu.creative.computation.max_usage": "Max CWU/tick:", "gtceu.creative.energy.amperage": "Amperage", "gtceu.creative.energy.sink": "Sink", "gtceu.creative.energy.source": "Source", @@ -2327,6 +2359,12 @@ "gtceu.ender_redstone_link_cover.label": "Redstone power: %d", "gtceu.ender_redstone_link_cover.title": "Ender Redstone Link", "gtceu.ender_redstone_link_cover.tooltip": "§7Transmits §fRedstone signals§7 with a §fWireless §dEnder§f Connection§7 as §fCover§7.", + "gtceu.equipment_foundry.gui.applied_to": "Applied to:", + "gtceu.equipment_foundry.gui.module_item": "Module item:", + "gtceu.equipment_foundry.gui.supports_tiers": "Module tiers: %s-%s", + "gtceu.equipment_foundry.gui.tier": "Viewing stats for tier: %s", + "gtceu.equipment_foundry.gui.tier_too_high": "No module item exists for this tier", + "gtceu.equipment_foundry.gui.tooltip.tier_switch": "Left-click to increase tier by 1\nRight-click to decrease tier by 1", "gtceu.extractor": "Extractor", "gtceu.extruder": "Extruder", "gtceu.fermenter": "Fermenter", @@ -2371,10 +2409,24 @@ "gtceu.gui.adv_stocking_config.title": "Configure Automatic Stocking", "gtceu.gui.all_voiding": "§7Voiding §cAll", "gtceu.gui.auto_output.name": "auto", + "gtceu.gui.central_monitor.data_hatch_target": "If you select a data hatch as a target, you will be prompted to enter a slot number. Then the block that the data stick in the specified slot is linked to (via right-clicking a wireless transmitter cover) will be considered the target instead.", "gtceu.gui.central_monitor.group": "Group: %s", "gtceu.gui.central_monitor.group_default_name": "Group #%d", - "gtceu.gui.central_monitor.none": "none", + "gtceu.gui.central_monitor.gui_module_info": "To select a block to get the GUI from, select a target in the monitor group editor.", + "gtceu.gui.central_monitor.help": "A monitor group is a collection of any amount of monitors in the multiblock.\nFor a group to display anything, it needs 2 things:\n - you to select the monitors that you want to display something on\n - an inserted and configured monitor module\nA module must be inserted in the slot to the right of the group name textbox.\nWhen you insert it, a button will appear to configure the module (for example just enter the text to display)\nThen you have to select at least 1 monitor in the grid below the group name textbox, here are types of selections:", + "gtceu.gui.central_monitor.in_group": "Monitors selected this way are added to the group, and will be used to display stuff", + "gtceu.gui.central_monitor.in_group_and_target": "The monitor selected this way is used for displaying and as a target at the same time.", + "gtceu.gui.central_monitor.left_click": "Select/unselect a monitor by left-clicking it", + "gtceu.gui.central_monitor.module_editor_button": "Edit module", + "gtceu.gui.central_monitor.module_editor_disabled": "You recently changed the module, please re-open this GUI to edit it", + "gtceu.gui.central_monitor.pause": "Pause placeholder execution.\nText won't be updated, and code won't be run.", + "gtceu.gui.central_monitor.resume": "Unpause placeholder execution.", + "gtceu.gui.central_monitor.right_click": "Select a block by right-clicking it. Only 1 block can be a target.", + "gtceu.gui.central_monitor.target": "The block selected this way is considered a target, to be used with placeholders in a text module.", + "gtceu.gui.central_monitor.text_module_help": "This module displays text that can have placeholders.\nPlaceholders are strings like \"{energy}\" that when displayed, will display their value instead (in this case the amount of energy).\nThey can also do some other things, such as set a redstone output/read redstone input, run calculations, etc.\nSome placeholders, like {energy} must have a target to function. A target is basically any block that can accept covers or is part of the\ncentral monitor multiblock. For example {energy} displays the amount of energy in its target block, usually a battery buffer or a PSS.\nSelect a target in the monitor group editing window, check out the help page there for more info.\nHere's an example usage of placeholders, that displays some energy info and sends a redstone signal when energy is <50%:\n", "gtceu.gui.central_monitor.text_scale": "Text scale", + "gtceu.gui.central_monitor.update_once": "Update text and run all placeholders in it exactly once.", + "gtceu.gui.central_monitor.url": "Input image URL:", "gtceu.gui.charger_slot.tooltip.0": "§fCharger Slot§r", "gtceu.gui.charger_slot.tooltip.1": "§7Draws power from %s batteries§r", "gtceu.gui.charger_slot.tooltip.2": "§7Charges %s tools and batteries", @@ -2392,8 +2444,7 @@ "gtceu.gui.computer_monitor_cover.placeholder_reference.1": "(hover for more info)", "gtceu.gui.computer_monitor_cover.second_page_textbox_tooltip.0": "Input placeholder to be used in place of %s '{}' here.", "gtceu.gui.computer_monitor_cover.second_page_textbox_tooltip.1": "For example, you can have a string 'Energy: {}/{} EU' and 'energy' and 'energyCapacity' in these text boxes.", - "gtceu.gui.computer_monitor_cover.slot_tooltip.0": "A slot for items that some placeholders can reference", - "gtceu.gui.computer_monitor_cover.slot_tooltip.1": "Slot number: %d", + "gtceu.gui.computer_monitor_cover.slot_tooltip": "A slot for items that some placeholders can reference\nSlot number: %d\n", "gtceu.gui.computer_monitor_cover.update_interval": "Update interval (in ticks)", "gtceu.gui.config_slot": "§fConfig Slot§r", "gtceu.gui.config_slot.auto_pull_managed": "§4Disabled:§7 Managed by Auto-Pull", @@ -2435,8 +2486,6 @@ "gtceu.gui.fluid_amount": "Fluid Amount:", "gtceu.gui.fluid_auto_input.tooltip.disabled": "Fluid Auto-Input Disabled", "gtceu.gui.fluid_auto_input.tooltip.enabled": "Fluid Auto-Input Enabled", - "gtceu.gui.fluid_auto_output.allow_input.disabled": "disable fluids input from the output side", - "gtceu.gui.fluid_auto_output.allow_input.enabled": "allow fluids input from the output side", "gtceu.gui.fluid_auto_output.disabled": "Fluid Auto Output: §cDisabled", "gtceu.gui.fluid_auto_output.enabled": "Fluid Auto Output: §aEnabled", "gtceu.gui.fluid_auto_output.other_direction.0": "Fluid Auto Output: §6Other Direction", @@ -2446,6 +2495,8 @@ "gtceu.gui.fluid_auto_output.tooltip.enabled": "Fluid Auto-Output Enabled", "gtceu.gui.fluid_auto_output.unselected.0": "Fluid Auto Output", "gtceu.gui.fluid_auto_output.unselected.1": "§7Select a side of the machine to configure its output.", + "gtceu.gui.fluid_input_from_output.disabled": "Allow Fluid Input from Output Side: §cDisabled", + "gtceu.gui.fluid_input_from_output.enabled": "Allow Fluid Input from Output Side: §aEnabled", "gtceu.gui.fluid_lock.tooltip.disabled": "Fluid Locking Disabled", "gtceu.gui.fluid_lock.tooltip.enabled": "Fluid Locking Enabled", "gtceu.gui.fluid_voiding": "§7Voiding §9Fluids", @@ -2454,8 +2505,6 @@ "gtceu.gui.fuel_amount": "Fuel Amount:", "gtceu.gui.item_auto_input.tooltip.disabled": "Item Auto-Input Disabled", "gtceu.gui.item_auto_input.tooltip.enabled": "Item Auto-Input Enabled", - "gtceu.gui.item_auto_output.allow_input.disabled": "disable items input from the output side", - "gtceu.gui.item_auto_output.allow_input.enabled": "allow items input from the output side", "gtceu.gui.item_auto_output.disabled": "Item Auto Output: §cDisabled", "gtceu.gui.item_auto_output.enabled": "Item Auto Output: §aEnabled", "gtceu.gui.item_auto_output.other_direction.0": "Item Auto Output: §6Other Direction", @@ -2465,6 +2514,9 @@ "gtceu.gui.item_auto_output.tooltip.enabled": "Item Auto-Output Enabled", "gtceu.gui.item_auto_output.unselected.0": "Item Auto Output", "gtceu.gui.item_auto_output.unselected.1": "§7Select a side of the machine to configure its output.", + "gtceu.gui.item_collector.range": "Range: ", + "gtceu.gui.item_input_from_output.disabled": "Allow Item Input from Output Side: §cDisabled", + "gtceu.gui.item_input_from_output.enabled": "Allow Item Input from Output Side: §aEnabled", "gtceu.gui.item_lock.tooltip.disabled": "Item Locking Disabled", "gtceu.gui.item_lock.tooltip.enabled": "Item Locking Enabled", "gtceu.gui.item_voiding": "§7Voiding §6Items", @@ -2474,8 +2526,13 @@ "gtceu.gui.machinemode.tab_tooltip": "Change active Machine Mode", "gtceu.gui.machinemode.title": "Active Machine Mode", "gtceu.gui.me_bus.auto_pull_button": "Click to toggle automatic item pulling from ME", + "gtceu.gui.me_network.auto_pull_toggle": "Toggle Auto-Pull", + "gtceu.gui.me_network.empty": "Empty", + "gtceu.gui.me_network.min_stack_size": "Min Stack Size:", "gtceu.gui.me_network.offline": "Network Status: §4Offline§r", "gtceu.gui.me_network.online": "Network Status: §2Online§r", + "gtceu.gui.me_network.stocking_settings": "Stocking Settings", + "gtceu.gui.me_network.ticks_per_cycle": "Ticks Per Cycle:", "gtceu.gui.multiblock.voiding_mode": "Voiding Mode:", "gtceu.gui.no_voiding": "§7Voiding Nothing", "gtceu.gui.output_setting.title": "Output Settings", @@ -2490,6 +2547,7 @@ "gtceu.gui.overclock.off": "X", "gtceu.gui.overclock.range": "Available Tiers [%s, %s]", "gtceu.gui.overclock.title": "Overclock Tier", + "gtceu.gui.pattern_buffer.set_custom_name": "Set Custom Name: ", "gtceu.gui.silktouch.disabled.0": "Silk Touch Disabled: Click to Enable.", "gtceu.gui.silktouch.disabled.1": "§7Switching requires an idle machine.", "gtceu.gui.silktouch.enabled.0": "Silk Touch Enabled: Click to Disable.", @@ -2503,11 +2561,13 @@ "gtceu.gui.toggle_view.disabled": "Toggle View (Fluids)", "gtceu.gui.toggle_view.enabled": "Toggle View (Items)", "gtceu.gui.waiting_list": "Sending Queue:", + "gtceu.gui.waiting_list_empty": "Sending Queue: §2Empty", "gtceu.implosion_compressor": "Implosion Compressor", "gtceu.io.both": "Both", "gtceu.io.export": "Export", "gtceu.io.import": "Import", "gtceu.io.none": "None", + "gtceu.item.tooltip.image_url": "Image URL: %s", "gtceu.item_filter.empty_item": "Empty (No Item)", "gtceu.item_filter.footer": "§eClick with item to override", "gtceu.item_list.item_stored": "§7Stored: %d", @@ -2757,6 +2817,7 @@ "gtceu.machine.ev_sifter.tooltip": "§7Stay calm and keep sifting", "gtceu.machine.ev_thermal_centrifuge.tooltip": "§7Separating Ores more precisely", "gtceu.machine.ev_wiremill.tooltip": "§7Produces Wires more efficiently", + "gtceu.machine.exploded": "%s exploded at (%d, %d, %d)", "gtceu.machine.extreme_combustion_engine.tooltip": "Extreme Chemical Energy Releaser", "gtceu.machine.fisher.requirement": "Requires a %dx%d centered square of water directly below.", "gtceu.machine.fisher.speed": "Catches something every %d ticks", @@ -3034,19 +3095,16 @@ "gtceu.machine.me_import_item_hatch.configs.tooltip": "Keeps 16 item types in stock", "gtceu.machine.miner.chunkradius": "Chunk Radius: %d", "gtceu.machine.miner.fluid_usage": "Uses §f%d mB/t §7of §f%s§7, doubled per overclock.", - "gtceu.machine.miner.minex": "mX: %d", - "gtceu.machine.miner.miney": "mY: %d", - "gtceu.machine.miner.minez": "mZ: %d", "gtceu.machine.miner.multi.description": "A multiblock mining machine that covers a large area and produces huge quantity of ore.", "gtceu.machine.miner.multi.modes": "Has Silk Touch and Chunk Aligned Modes.", "gtceu.machine.miner.multi.production": "Produces §f3x§7 more crushed ore than a §fMacerator§7.", "gtceu.machine.miner.per_block": "§7takes §f%ds §7per Block", "gtceu.machine.miner.progress": "Progress: %d/%d", "gtceu.machine.miner.radius": "Radius: %d", - "gtceu.machine.miner.startx": "sX: %d", - "gtceu.machine.miner.starty": "sY: %d", - "gtceu.machine.miner.startz": "sZ: %d", "gtceu.machine.miner.tooltip": "§7Mines ores below the Miner! Starts as §f%sx%s §7area", + "gtceu.machine.miner.x": "sX: %d, mX: %d", + "gtceu.machine.miner.y": "sY: %d, mY: %d", + "gtceu.machine.miner.z": "sZ: %d, mZ: %d", "gtceu.machine.muffle.off": "Sound Muffling: Disabled", "gtceu.machine.muffle.on": "Sound Muffling: Enabled", "gtceu.machine.muffler_hatch.tooltip.0": "Recovers waste from machines", @@ -3101,6 +3159,7 @@ "gtceu.machine.opv_gas_collector.tooltip": "§7Collects Gas from the universe depending on the dimension", "gtceu.machine.opv_rock_crusher.tooltip": "§7Volcanic Formation Chamber", "gtceu.machine.parallel_hatch.display": "Adjust the maximum parallel of the multiblock", + "gtceu.machine.parallel_hatch.parallel_ui": "Parallels", "gtceu.machine.parallel_hatch_mk5.tooltip": "Allows to run up to 4 recipes in parallel.", "gtceu.machine.parallel_hatch_mk6.tooltip": "Allows to run up to 16 recipes in parallel.", "gtceu.machine.parallel_hatch_mk7.tooltip": "Allows to run up to 64 recipes in parallel.", @@ -3263,6 +3322,36 @@ "gtceu.mode.both": "§dBoth (Fluid And Item)§r", "gtceu.mode.fluid": "§9Fluid§r", "gtceu.mode.item": "§6Item§r", + "gtceu.module.advanced_jetpack": "Makes the chestplate work like an advanced jetpack (requires any battery module)", + "gtceu.module.attack_damage": "Increases attack damage by %s%%", + "gtceu.module.attack_speed": "Increases attack speed by %s%%", + "gtceu.module.battery": "Allows the item to store energy or increases its capacity (capacity is equal to the battery's)", + "gtceu.module.block_reach": "Increases block reach by %s blocks", + "gtceu.module.block_reach.short": "... by %s blocks", + "gtceu.module.creative_flight": "Allows creative flight (consumes %s EU/t while flying)", + "gtceu.module.damage_block": "Blocks any amount of damage with EU (%s EU per HP, requires any battery module)", + "gtceu.module.damage_block.short": "%s EU per HP", + "gtceu.module.fluid_storage": "Allows the item to store liquids or increases its capacity (capacity is equal to the tank's)", + "gtceu.module.gui.charge": "Charge:", + "gtceu.module.gui.enabled": "Enabled:", + "gtceu.module.gui.jump_boost": "Boost:", + "gtceu.module.gui.power": "Power:", + "gtceu.module.jetpack": "Makes the chestplate work like a jetpack (requires any battery module)", + "gtceu.module.jump": "Increases jump height by %s blocks", + "gtceu.module.liquid_fuel_jetpack": "Makes the chestplate work like a liquid fueled jetpack (requires any fluid storage module)", + "gtceu.module.movement_speed": "Increases all movement speed by %s%%", + "gtceu.module.nightvision": "Provides night vision (consumes %s EU/t while active)", + "gtceu.module.ppe": "Provides protection from environmental hazards if applied to all armor pieces", + "gtceu.module.sensor": "Reports machine explosions (for machines placed by the player)", + "gtceu.module.short_percentage": "... by %s%%", + "gtceu.module.sneak_speed": "Increases sneaking speed by %s%%", + "gtceu.module.speed": "Increases sprint speed by %s%%", + "gtceu.module.step_height": "Increases step height by %s blocks", + "gtceu.module.swim_speed": "Increases swim speed by %s%%", + "gtceu.module.wireless_charging": "Allows wireless charging in the range of %s blocks (1A %s max), bind to a charger by right-clicking on it", + "gtceu.module.wireless_charging.interdimensional": "%s blocks, 1A %s max, interdimensional if an at least %s field generator is present", + "gtceu.module.wireless_charging.short": "%s blocks, 1A %s max", + "gtceu.modules": "Modules:", "gtceu.muffler.recovery_tooltip": "§bRecovery Chance: §f%d%%", "gtceu.multiblock.active_transformer.average_in": "§bAvg. Input: §f%s EU/t", "gtceu.multiblock.active_transformer.average_out": "§bAvg. Output: §f%s EU/t", @@ -3324,10 +3413,9 @@ "gtceu.multiblock.hpca.info_bridging_disabled": "Bridging Disabled", "gtceu.multiblock.hpca.info_bridging_enabled": "Bridging Enabled", "gtceu.multiblock.hpca.info_coolant_name": "PCB Coolant", + "gtceu.multiblock.hpca.info_cooling_demand": "Cooling Demand: %s / %d", "gtceu.multiblock.hpca.info_max_computation": "Max CWU/t: %s", "gtceu.multiblock.hpca.info_max_coolant_required": "Coolant Needed: %s", - "gtceu.multiblock.hpca.info_max_cooling_available": "Cooling Available: %s", - "gtceu.multiblock.hpca.info_max_cooling_demand": "Cooling Demand: %s", "gtceu.multiblock.hpca.temperature": "Temperature: %s", "gtceu.multiblock.hpca.warning_low_cooling": "- Not enough cooling", "gtceu.multiblock.hpca.warning_multiple_bridges": "- Multiple bridges in structure (provides no additional benefit)", @@ -3480,9 +3568,9 @@ "gtceu.multiblock.turbine.rotor_durability": "Rotor Durability: %s%%", "gtceu.multiblock.turbine.rotor_speed": "Rotor Speed: %s/%s RPM", "gtceu.multiblock.universal.distinct": "Distinct Buses:", + "gtceu.multiblock.universal.distinct.disabled": "Distinct Buses: §eDisabled", + "gtceu.multiblock.universal.distinct.enabled": "Distinct Buses: §eEnabled", "gtceu.multiblock.universal.distinct.info": "If enabled, each Item Input Bus will be treated as fully distinct from each other for recipe lookup. Useful for things like Programmed Circuits, Extruder Shapes, etc.", - "gtceu.multiblock.universal.distinct.no": "No", - "gtceu.multiblock.universal.distinct.yes": "Yes", "gtceu.multiblock.universal.has_problems": "Has Maintenance Problems!", "gtceu.multiblock.universal.has_problems_header": "Fix the following issues in a Maintenance Hatch:", "gtceu.multiblock.universal.muffler_obstructed": "Muffler Hatch is Obstructed!", @@ -3513,6 +3601,14 @@ "gtceu.packer": "Packer", "gtceu.part_sharing.disabled": "Multiblock Sharing §4Disabled", "gtceu.part_sharing.enabled": "Multiblock Sharing §aEnabled", + "gtceu.placeholder_editor.constant_value": "This expression always evaluates to the same result.\nConsider replacing it with a constant.", + "gtceu.placeholder_editor.extra_closing_bracket": "Extra closing bracket", + "gtceu.placeholder_editor.no_placeholder": "Placeholder with name '%s' does not exist", + "gtceu.placeholder_editor.unclosed_bracket": "Unclosed bracket (\"}\")", + "gtceu.placeholder_editor.unclosed_brackets": "%d brackets (\"}\") are unclosed", + "gtceu.placeholder_editor.unclosed_escape": "Unclosed escape (\"']\")", + "gtceu.placeholder_editor.unclosed_escapes": "%d escapes (\"']\") are unclosed", + "gtceu.placeholder_editor.write_in_if": "Placeholders inside {if} are executed regardless of the condition.\nThis means that, for example, \"{if 0 {redstone set 15}}\" will produce redstone output.\nTo avoid this, use \"{eval {if \"\" \"\"}}\".", "gtceu.placeholder_info.active.0": "Returns a 1 if the block the cover is attached to is currently running a recipe, 0 otherwise.", "gtceu.placeholder_info.active.1": "Usage:", "gtceu.placeholder_info.active.2": " {active} -> whether there's a currently running recipe", @@ -4126,6 +4222,7 @@ "item.gtceu.cpu_chip.tooltip": "§7Central Processing Unit", "item.gtceu.cpu_wafer": "CPU Wafer", "item.gtceu.cpu_wafer.tooltip": "§7Raw Processing Unit", + "item.gtceu.creative_flight_module": "Gravitation Module", "item.gtceu.crushed_bentonite_ore": "Ground Bentonite", "item.gtceu.crushed_cassiterite_sand_ore": "Ground Cassiterite Sand", "item.gtceu.crushed_pitchblende_ore": "Ground Pitchblende", @@ -4271,6 +4368,7 @@ "item.gtceu.gray_glass_lens": "Glass Lens (Gray)", "item.gtceu.green_dye_spray_can": "Spray Can (Green)", "item.gtceu.green_glass_lens": "Glass Lens (Green)", + "item.gtceu.gui_module": "Gui Module", "item.gtceu.hammer_extruder_mold.tooltip": "§7Extruder Shape for making Hammers", "item.gtceu.hazmat_boots": "Hazardous Materials Suit Boots", "item.gtceu.hazmat_chestpiece": "Hazardous Materials Suit Chestpiece", @@ -5764,6 +5862,33 @@ "metaarmor.tooltip.falldamage": "Nullifies Fall Damage", "metaarmor.tooltip.freezing": "Prevents Freezing", "metaarmor.tooltip.jump": "Increases Jump Height and Distance", + "metaarmor.tooltip.modifier": " - %s: %s", + "metaarmor.tooltip.modifier.attack_damage": "Attack Damage Module (%s)", + "metaarmor.tooltip.modifier.attack_speed": "Attack Speed Module (%s)", + "metaarmor.tooltip.modifier.battery": "Battery Module (%s)", + "metaarmor.tooltip.modifier.battery.hud.boots": "Boots battery: %s", + "metaarmor.tooltip.modifier.battery.hud.chestplate": "Chestplate battery: %s", + "metaarmor.tooltip.modifier.battery.hud.helmet": "Helmet battery: %s", + "metaarmor.tooltip.modifier.battery.hud.info": "Storing %s/%s EU", + "metaarmor.tooltip.modifier.battery.hud.leggings": "Leggings battery: %s", + "metaarmor.tooltip.modifier.block_reach": "Reach Module (%s)", + "metaarmor.tooltip.modifier.creative_flight": "Creative Flight Module", + "metaarmor.tooltip.modifier.damage_block": "Energy Shield Module (%s)", + "metaarmor.tooltip.modifier.empty": "Empty", + "metaarmor.tooltip.modifier.fluid_storage": "Additional fluid storage (%s)", + "metaarmor.tooltip.modifier.fluid_storage.tooltip": "Storing %s/%s mB of %s", + "metaarmor.tooltip.modifier.jetpack": "Jetpack Module (%s)", + "metaarmor.tooltip.modifier.jump": "Jump Module (%s)", + "metaarmor.tooltip.modifier.movement_speed": "Movement Speed Module (%s)", + "metaarmor.tooltip.modifier.sensor": "Explosion Reporting Module (%s)", + "metaarmor.tooltip.modifier.sneak_speed": "Sneak Speed Module (%s)", + "metaarmor.tooltip.modifier.speed": "Running Speed Module (%s)", + "metaarmor.tooltip.modifier.step_height": "Step Height Module (%s)", + "metaarmor.tooltip.modifier.swim_speed": "Swim Speed Module (%s)", + "metaarmor.tooltip.modifier.wireless_charging": "Wireless Charging Module (%s)", + "metaarmor.tooltip.modifier_slot.tiered": "Tiered (%s)", + "metaarmor.tooltip.modifier_slot.universal": "Universal", + "metaarmor.tooltip.modifiers": "Module slots:", "metaarmor.tooltip.potions": "Nullifies Harmful Effects", "metaarmor.tooltip.speed": "Increases Running Speed", "metaarmor.tooltip.stepassist": "Provides Step-Assist", diff --git a/src/generated/resources/assets/gtceu/models/block/equipment_foundry.json b/src/generated/resources/assets/gtceu/models/block/equipment_foundry.json new file mode 100644 index 00000000000..77b8bf7bbc7 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/equipment_foundry.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "gtceu:block/equipment_foundry" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/machine/test_mui.json b/src/generated/resources/assets/gtceu/models/block/machine/test_mui.json new file mode 100644 index 00000000000..f86f60d96f9 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/machine/test_mui.json @@ -0,0 +1,18 @@ +{ + "parent": "minecraft:block/block", + "loader": "gtceu:machine", + "machine": "gtceu:test_mui", + "replaceable_textures": [ + "all" + ], + "variants": { + "": { + "model": { + "parent": "gtceu:block/machine/part/computer_monitor", + "textures": { + "all": "gtceu:block/casings/solid/machine_casing_clean_stainless_steel" + } + } + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/machine/test_mui_new.json b/src/generated/resources/assets/gtceu/models/block/machine/test_mui_new.json new file mode 100644 index 00000000000..12fd1d59a84 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/machine/test_mui_new.json @@ -0,0 +1,42 @@ +{ + "parent": "minecraft:block/block", + "loader": "gtceu:machine", + "machine": "gtceu:test_mui_new", + "replaceable_textures": [ + "all" + ], + "variants": { + "recipe_logic_status=idle": { + "model": { + "parent": "gtceu:block/machine/part/computer_monitor", + "textures": { + "all": "gtceu:block/casings/solid/machine_casing_clean_stainless_steel" + } + } + }, + "recipe_logic_status=suspend": { + "model": { + "parent": "gtceu:block/machine/part/computer_monitor", + "textures": { + "all": "gtceu:block/casings/solid/machine_casing_clean_stainless_steel" + } + } + }, + "recipe_logic_status=waiting": { + "model": { + "parent": "gtceu:block/machine/part/computer_monitor", + "textures": { + "all": "gtceu:block/casings/solid/machine_casing_clean_stainless_steel" + } + } + }, + "recipe_logic_status=working": { + "model": { + "parent": "gtceu:block/machine/part/computer_monitor", + "textures": { + "all": "gtceu:block/casings/solid/machine_casing_clean_stainless_steel" + } + } + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/creative_flight_module.json b/src/generated/resources/assets/gtceu/models/item/creative_flight_module.json new file mode 100644 index 00000000000..cda3d565098 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/creative_flight_module.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "gtceu:item/creative_flight_module" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/equipment_foundry.json b/src/generated/resources/assets/gtceu/models/item/equipment_foundry.json new file mode 100644 index 00000000000..4de77ddab56 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/equipment_foundry.json @@ -0,0 +1,3 @@ +{ + "parent": "gtceu:block/equipment_foundry" +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/gui_module.json b/src/generated/resources/assets/gtceu/models/item/gui_module.json new file mode 100644 index 00000000000..5c1152837c4 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/gui_module.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "gtceu:item/gui_module" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/test_mui.json b/src/generated/resources/assets/gtceu/models/item/test_mui.json new file mode 100644 index 00000000000..9ae958ad11c --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/test_mui.json @@ -0,0 +1,3 @@ +{ + "parent": "gtceu:block/machine/test_mui" +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/test_mui_new.json b/src/generated/resources/assets/gtceu/models/item/test_mui_new.json new file mode 100644 index 00000000000..e741c72dc8d --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/test_mui_new.json @@ -0,0 +1,3 @@ +{ + "parent": "gtceu:block/machine/test_mui_new" +} \ No newline at end of file diff --git a/src/generated/resources/data/gtceu/loot_tables/blocks/equipment_foundry.json b/src/generated/resources/data/gtceu/loot_tables/blocks/equipment_foundry.json new file mode 100644 index 00000000000..6298ba16691 --- /dev/null +++ b/src/generated/resources/data/gtceu/loot_tables/blocks/equipment_foundry.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "gtceu:equipment_foundry" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "gtceu:blocks/equipment_foundry" +} \ No newline at end of file diff --git a/src/generated/resources/data/gtceu/tags/items/electric_motors.json b/src/generated/resources/data/gtceu/tags/items/electric_motors.json index 05904c9c33a..fb43bbca08d 100644 --- a/src/generated/resources/data/gtceu/tags/items/electric_motors.json +++ b/src/generated/resources/data/gtceu/tags/items/electric_motors.json @@ -8,6 +8,11 @@ "gtceu:luv_electric_motor", "gtceu:zpm_electric_motor", "gtceu:uv_electric_motor", + "gtceu:uhv_electric_motor", + "gtceu:uev_electric_motor", + "gtceu:uiv_electric_motor", + "gtceu:uxv_electric_motor", + "gtceu:opv_electric_motor", { "id": "gtceu:uhv_electric_motor", "required": false diff --git a/src/generated/resources/data/gtceu/tags/items/electric_pumps.json b/src/generated/resources/data/gtceu/tags/items/electric_pumps.json index 2fb3023fbd4..8db38c02bc2 100644 --- a/src/generated/resources/data/gtceu/tags/items/electric_pumps.json +++ b/src/generated/resources/data/gtceu/tags/items/electric_pumps.json @@ -8,6 +8,11 @@ "gtceu:luv_electric_pump", "gtceu:zpm_electric_pump", "gtceu:uv_electric_pump", + "gtceu:uhv_electric_pump", + "gtceu:uev_electric_pump", + "gtceu:uiv_electric_pump", + "gtceu:uxv_electric_pump", + "gtceu:opv_electric_pump", { "id": "gtceu:uhv_electric_pump", "required": false diff --git a/src/generated/resources/data/gtceu/tags/items/fluid_containers.json b/src/generated/resources/data/gtceu/tags/items/fluid_containers.json new file mode 100644 index 00000000000..519fd22af7c --- /dev/null +++ b/src/generated/resources/data/gtceu/tags/items/fluid_containers.json @@ -0,0 +1,30 @@ +{ + "values": [ + "gtceu:lv_super_tank", + "gtceu:mv_super_tank", + "gtceu:hv_super_tank", + "gtceu:ev_super_tank", + "gtceu:iv_quantum_tank", + "gtceu:luv_quantum_tank", + "gtceu:zpm_quantum_tank", + "gtceu:uv_quantum_tank", + "gtceu:uhv_quantum_tank", + "gtceu:uev_quantum_tank", + "gtceu:uiv_quantum_tank", + "gtceu:uxv_quantum_tank", + "gtceu:opv_quantum_tank", + "gtceu:wood_drum", + "gtceu:bronze_drum", + "gtceu:steel_drum", + "gtceu:aluminium_drum", + "gtceu:stainless_steel_drum", + "gtceu:gold_drum", + "gtceu:titanium_drum", + "gtceu:tungsten_steel_drum", + "gtceu:steel_fluid_cell", + "gtceu:aluminium_fluid_cell", + "gtceu:stainless_steel_fluid_cell", + "gtceu:titanium_fluid_cell", + "gtceu:tungsten_steel_fluid_cell" + ] +} \ No newline at end of file diff --git a/src/main/java/com/gregtechceu/gtceu/api/GTValues.java b/src/main/java/com/gregtechceu/gtceu/api/GTValues.java index 7f2da34899c..d75000693d6 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/GTValues.java +++ b/src/main/java/com/gregtechceu/gtceu/api/GTValues.java @@ -140,8 +140,8 @@ public static int[] tiersBetween(int minInclusive, int maxInclusive) { MODID_FTB_QUEST = "ftbquests", MODID_CCTWEAKED = "computercraft", MODID_ENDERIO = "enderio", - MODID_ENSORCELLATION = "ensorcellation"; - + MODID_ENSORCELLATION = "ensorcellation", + MODID_ATTRIBUTEFIX = "attributefix"; /** * Spray painting compat modids */ diff --git a/src/main/java/com/gregtechceu/gtceu/api/block/MetaMachineBlock.java b/src/main/java/com/gregtechceu/gtceu/api/block/MetaMachineBlock.java index 93c4037f202..b52a2a787dc 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/block/MetaMachineBlock.java +++ b/src/main/java/com/gregtechceu/gtceu/api/block/MetaMachineBlock.java @@ -295,9 +295,12 @@ public InteractionResult use(BlockState state, Level world, BlockPos pos, Player shouldOpenUi = gtToolItem.definition$shouldOpenUIAfterUse(new UseOnContext(player, hand, hit)); } - if (shouldOpenUi && machine instanceof IUIMachine uiMachine && - MachineOwner.canOpenOwnerMachine(player, machine)) { - return uiMachine.tryToOpenUI(player, hand, hit); + if (shouldOpenUi && MachineOwner.canOpenOwnerMachine(player, machine)) { + if (machine.getDefinition().getUI() != null) { + return machine.getDefinition().getUI().tryToOpenUI(player, hand, hit); + } else if (machine instanceof IMuiMachine muiMachine) { + return muiMachine.tryToOpenUI(player, hand, hit); + } } return shouldOpenUi ? InteractionResult.PASS : InteractionResult.CONSUME; } diff --git a/src/main/java/com/gregtechceu/gtceu/api/block/RendererMaterialBlock.java b/src/main/java/com/gregtechceu/gtceu/api/block/RendererMaterialBlock.java deleted file mode 100644 index ddd25dd4e5c..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/block/RendererMaterialBlock.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.gregtechceu.gtceu.api.block; - -import com.gregtechceu.gtceu.api.data.chemical.material.Material; -import com.gregtechceu.gtceu.api.data.tag.TagPrefix; - -import com.lowdragmc.lowdraglib.client.renderer.IBlockRendererProvider; -import com.lowdragmc.lowdraglib.client.renderer.IRenderer; - -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import org.jetbrains.annotations.Nullable; - -public class RendererMaterialBlock extends MaterialBlock implements IBlockRendererProvider { - - public final IRenderer renderer; - - public RendererMaterialBlock(Properties properties, TagPrefix tagPrefix, Material material, - @Nullable IRenderer renderer) { - super(properties, tagPrefix, material, false); - this.renderer = renderer; - } - - @Nullable - @Override - @OnlyIn(Dist.CLIENT) - public IRenderer getRenderer(BlockState state) { - return renderer; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/blockentity/PipeBlockEntity.java b/src/main/java/com/gregtechceu/gtceu/api/blockentity/PipeBlockEntity.java index 85160932110..d0d0a1babe8 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/blockentity/PipeBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/api/blockentity/PipeBlockEntity.java @@ -5,7 +5,6 @@ import com.gregtechceu.gtceu.api.cover.CoverBehavior; import com.gregtechceu.gtceu.api.data.chemical.material.Material; import com.gregtechceu.gtceu.api.data.tag.TagPrefix; -import com.gregtechceu.gtceu.api.gui.GuiTextures; import com.gregtechceu.gtceu.api.item.tool.GTToolType; import com.gregtechceu.gtceu.api.item.tool.IToolGridHighlight; import com.gregtechceu.gtceu.api.machine.TickableSubscription; @@ -16,11 +15,10 @@ import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; import com.gregtechceu.gtceu.common.data.GTMaterialBlocks; import com.gregtechceu.gtceu.common.data.GTMaterials; +import com.gregtechceu.gtceu.common.mui.GTGuiTextures; import com.gregtechceu.gtceu.utils.ExtendedUseOnContext; import com.gregtechceu.gtceu.utils.GTUtil; -import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; - import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -37,6 +35,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import brachy.modularui.drawable.UITexture; import com.mojang.datafixers.util.Pair; import lombok.Getter; import org.jetbrains.annotations.NotNull; @@ -329,13 +328,13 @@ public boolean shouldRenderGrid(Player player, BlockPos pos, BlockState state, I return false; } - public ResourceTexture getPipeTexture(boolean isBlock) { - return isBlock ? GuiTextures.TOOL_PIPE_CONNECT : GuiTextures.TOOL_PIPE_BLOCK; + public UITexture getPipeTexture(boolean isBlock) { + return isBlock ? GTGuiTextures.TOOL_PIPE_CONNECT : GTGuiTextures.TOOL_PIPE_BLOCK; } @Override - public @Nullable ResourceTexture sideTips(Player player, BlockPos pos, BlockState state, Set toolTypes, - Direction side) { + public @Nullable UITexture sideTips(Player player, BlockPos pos, BlockState state, Set toolTypes, + Direction side) { if (toolTypes.contains(getPipeTuneTool())) { if (player.isShiftKeyDown() && this.canHaveBlockedFaces()) { return getPipeTexture(isBlocked(side)); diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapability.java b/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapability.java index fc3b3a420d2..303dea2c73c 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapability.java +++ b/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapability.java @@ -1,5 +1,6 @@ package com.gregtechceu.gtceu.api.capability; +import com.gregtechceu.gtceu.api.item.module.IModularItem; import com.gregtechceu.gtceu.api.machine.feature.multiblock.IMaintenanceMachine; import com.gregtechceu.gtceu.common.capability.MedicalConditionTracker; @@ -36,6 +37,9 @@ public class GTCapability { public static final Capability CAPABILITY_MEDICAL_CONDITION_TRACKER = CapabilityManager .get(new CapabilityToken<>() {}); + public static final Capability CAPABILITY_MODULAR_ITEM = CapabilityManager + .get(new CapabilityToken<>() {}); + public static void register(RegisterCapabilitiesEvent event) { event.register(IEnergyContainer.class); event.register(IEnergyInfoProvider.class); @@ -50,5 +54,6 @@ public static void register(RegisterCapabilitiesEvent event) { event.register(MedicalConditionTracker.class); event.register(IHazardParticleContainer.class); event.register(IMonitorComponent.class); + event.register(IModularItem.class); } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapabilityHelper.java b/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapabilityHelper.java index b8b78742232..0f69f802e1d 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapabilityHelper.java +++ b/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapabilityHelper.java @@ -1,5 +1,6 @@ package com.gregtechceu.gtceu.api.capability; +import com.gregtechceu.gtceu.api.item.module.IModularItem; import com.gregtechceu.gtceu.api.machine.feature.multiblock.IMaintenanceMachine; import com.gregtechceu.gtceu.common.capability.MedicalConditionTracker; @@ -106,6 +107,11 @@ public static IMonitorComponent getMonitorComponent(Level level, BlockPos pos, @ return getBlockEntityCapability(GTCapability.CAPABILITY_MONITOR_COMPONENT, level, pos, side); } + @Nullable + public static IModularItem getModularItem(ItemStack stack) { + return stack.getCapability(GTCapability.CAPABILITY_MODULAR_ITEM).resolve().orElse(null); + } + @Nullable private static T getBlockEntityCapability(Capability capability, Level level, BlockPos pos, @Nullable Direction side) { diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/IMonitorComponent.java b/src/main/java/com/gregtechceu/gtceu/api/capability/IMonitorComponent.java index 002c650a187..b956dd6933f 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/capability/IMonitorComponent.java +++ b/src/main/java/com/gregtechceu/gtceu/api/capability/IMonitorComponent.java @@ -1,10 +1,9 @@ package com.gregtechceu.gtceu.api.capability; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; - import net.minecraft.core.BlockPos; import net.minecraftforge.items.IItemHandler; +import brachy.modularui.api.drawable.IDrawable; import org.jetbrains.annotations.Nullable; public interface IMonitorComponent { @@ -13,7 +12,7 @@ default boolean isMonitor() { return false; } - IGuiTexture getComponentIcon(); + IDrawable getIcon(); BlockPos getBlockPos(); diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/FluidRecipeCapability.java b/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/FluidRecipeCapability.java index 8f2e15d80e7..755a9c88955 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/FluidRecipeCapability.java +++ b/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/FluidRecipeCapability.java @@ -17,11 +17,11 @@ import com.gregtechceu.gtceu.api.recipe.ui.GTRecipeTypeUI; import com.gregtechceu.gtceu.client.TooltipsHandler; import com.gregtechceu.gtceu.common.valueprovider.*; -import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidEntryList; -import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidStackList; -import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidTagList; -import com.gregtechceu.gtceu.integration.xei.handlers.fluid.CycleFluidEntryHandler; -import com.gregtechceu.gtceu.integration.xei.widgets.GTRecipeWidget; +import com.gregtechceu.gtceu.integration.recipeviewer.entry.fluid.FluidEntryList; +import com.gregtechceu.gtceu.integration.recipeviewer.entry.fluid.FluidStackList; +import com.gregtechceu.gtceu.integration.recipeviewer.entry.fluid.FluidTagList; +import com.gregtechceu.gtceu.integration.recipeviewer.handlers.fluid.CycleFluidEntryHandler; +import com.gregtechceu.gtceu.integration.recipeviewer.widgets.GTRecipeWidget; import com.gregtechceu.gtceu.utils.GTMath; import com.lowdragmc.lowdraglib.gui.texture.ProgressTexture; diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/IO.java b/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/IO.java index 40a905e48e0..ba6ef3a0ca1 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/IO.java +++ b/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/IO.java @@ -1,16 +1,12 @@ package com.gregtechceu.gtceu.api.capability.recipe; -import com.gregtechceu.gtceu.api.gui.widget.EnumSelectorWidget; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; - +import brachy.modularui.drawable.UITexture; import lombok.Getter; /** * The capability can be input or output or both */ -public enum IO implements EnumSelectorWidget.SelectableEnum { +public enum IO { IN("gtceu.io.import", "import"), OUT("gtceu.io.export", "export"), @@ -20,11 +16,11 @@ public enum IO implements EnumSelectorWidget.SelectableEnum { @Getter public final String tooltip; @Getter - public final IGuiTexture icon; + public final UITexture uiTexture; IO(String tooltip, String textureName) { this.tooltip = tooltip; - this.icon = new ResourceTexture("gtceu:textures/gui/icon/io_mode/" + textureName + ".png"); + this.uiTexture = UITexture.fullImage("gtceu:textures/gui/icon/io_mode/" + textureName + ".png"); } public boolean support(IO io) { diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/ItemRecipeCapability.java b/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/ItemRecipeCapability.java index 239d8a9377b..e38611320d5 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/ItemRecipeCapability.java +++ b/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/ItemRecipeCapability.java @@ -23,11 +23,11 @@ import com.gregtechceu.gtceu.core.mixins.IngredientAccessor; import com.gregtechceu.gtceu.core.mixins.TagValueAccessor; import com.gregtechceu.gtceu.core.mixins.forge.IntersectionIngredientAccessor; -import com.gregtechceu.gtceu.integration.xei.entry.item.ItemEntryList; -import com.gregtechceu.gtceu.integration.xei.entry.item.ItemStackList; -import com.gregtechceu.gtceu.integration.xei.entry.item.ItemTagList; -import com.gregtechceu.gtceu.integration.xei.handlers.item.CycleItemEntryHandler; -import com.gregtechceu.gtceu.integration.xei.widgets.GTRecipeWidget; +import com.gregtechceu.gtceu.integration.recipeviewer.entry.item.ItemEntryList; +import com.gregtechceu.gtceu.integration.recipeviewer.entry.item.ItemStackList; +import com.gregtechceu.gtceu.integration.recipeviewer.entry.item.ItemTagList; +import com.gregtechceu.gtceu.integration.recipeviewer.handlers.item.CycleItemEntryHandler; +import com.gregtechceu.gtceu.integration.recipeviewer.widgets.GTRecipeWidget; import com.gregtechceu.gtceu.utils.*; import com.lowdragmc.lowdraglib.gui.widget.Widget; diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/CoverBehavior.java b/src/main/java/com/gregtechceu/gtceu/api/cover/CoverBehavior.java index 24ce428669d..8b948e23b28 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/cover/CoverBehavior.java +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/CoverBehavior.java @@ -2,24 +2,20 @@ import com.gregtechceu.gtceu.api.blockentity.ICopyable; import com.gregtechceu.gtceu.api.capability.ICoverable; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.factory.CoverUIFactory; -import com.gregtechceu.gtceu.api.gui.fancy.IFancyConfigurator; import com.gregtechceu.gtceu.api.item.tool.GTToolType; import com.gregtechceu.gtceu.api.item.tool.IToolGridHighlight; import com.gregtechceu.gtceu.api.machine.MetaMachine; +import com.gregtechceu.gtceu.api.mui.factory.CoverUIFactory; import com.gregtechceu.gtceu.api.sync_system.ISyncManaged; -import com.gregtechceu.gtceu.api.sync_system.ManagedSyncBlockEntity; import com.gregtechceu.gtceu.api.sync_system.SyncDataHolder; import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField; import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; import com.gregtechceu.gtceu.api.transfer.fluid.IFluidHandlerModifiable; import com.gregtechceu.gtceu.client.renderer.cover.ICoverRenderer; import com.gregtechceu.gtceu.client.renderer.cover.IDynamicCoverRenderer; +import com.gregtechceu.gtceu.common.mui.GTGuiTextures; import com.gregtechceu.gtceu.utils.ExtendedUseOnContext; -import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; - import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -31,6 +27,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.items.IItemHandlerModifiable; +import brachy.modularui.drawable.UITexture; import com.mojang.datafixers.util.Pair; import lombok.Getter; import org.jetbrains.annotations.MustBeInvokedByOverriders; @@ -79,9 +76,7 @@ public void scheduleRenderUpdate() { @Override public void markAsChanged() { - if (coverHolder instanceof ManagedSyncBlockEntity syncEntity) { - syncEntity.markAsChanged(); - } + coverHolder.markAsChanged(); } /** @@ -108,6 +103,7 @@ public void onAttached(ItemStack itemStack, @Nullable ServerPlayer player) { attachItem = itemStack.copy(); attachItem.setCount(1); syncDataHolder.markClientSyncFieldDirty("attachItem"); + markAsChanged(); } public void onLoad() {} @@ -161,9 +157,9 @@ public boolean canConnectRedstone() { } public InteractionResult onScrewdriverClick(ExtendedUseOnContext context) { - if (this instanceof IUICover) { + if (this instanceof IMuiCover muiCover) { if (context.getPlayer() instanceof ServerPlayer serverPlayer) { - CoverUIFactory.INSTANCE.openUI(this, serverPlayer); + CoverUIFactory.INSTANCE.open(serverPlayer, muiCover); } return InteractionResult.sidedSuccess(coverHolder.isRemote()); } @@ -192,25 +188,21 @@ public boolean shouldRenderPlate() { return coverDefinition.getCoverRenderer(); } - public @Nullable IFancyConfigurator getConfigurator() { - return null; - } - @Override public boolean shouldRenderGrid(Player player, BlockPos pos, BlockState state, ItemStack held, Set toolTypes) { return toolTypes.contains(GTToolType.CROWBAR) || - ((toolTypes.isEmpty() || toolTypes.contains(GTToolType.SCREWDRIVER)) && this instanceof IUICover); + ((toolTypes.isEmpty() || toolTypes.contains(GTToolType.SCREWDRIVER)) && this instanceof IMuiCover); } @Override - public @Nullable ResourceTexture sideTips(Player player, BlockPos pos, BlockState state, Set toolTypes, - Direction side) { + public @Nullable UITexture sideTips(Player player, BlockPos pos, BlockState state, Set toolTypes, + Direction side) { if (toolTypes.contains(GTToolType.CROWBAR)) { - return GuiTextures.TOOL_REMOVE_COVER; + return GTGuiTextures.TOOL_REMOVE_COVER; } - if ((toolTypes.isEmpty() || toolTypes.contains(GTToolType.SCREWDRIVER)) && this instanceof IUICover) { - return GuiTextures.TOOL_COVER_SETTINGS; + if ((toolTypes.isEmpty() || toolTypes.contains(GTToolType.SCREWDRIVER)) && this instanceof IMuiCover) { + return GTGuiTextures.TOOL_COVER_SETTINGS; } return null; } @@ -223,7 +215,7 @@ public BlockState getAppearance(BlockState sourceState, BlockPos sourcePos) { return null; } - public Supplier getDynamicRenderer() { + public Supplier<@Nullable IDynamicCoverRenderer> getDynamicRenderer() { return () -> null; } diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/IMuiCover.java b/src/main/java/com/gregtechceu/gtceu/api/cover/IMuiCover.java new file mode 100644 index 00000000000..e1eae3187b0 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/IMuiCover.java @@ -0,0 +1,90 @@ +package com.gregtechceu.gtceu.api.cover; + +import com.gregtechceu.gtceu.api.mui.GTGuiScreen; +import com.gregtechceu.gtceu.common.mui.GTGuiTextures; +import com.gregtechceu.gtceu.common.mui.GTGuiTheme; +import com.gregtechceu.gtceu.common.mui.GTMuiWidgets; + +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import brachy.modularui.api.IUIHolder; +import brachy.modularui.factory.SidedPosGuiData; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.ModularScreen; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.BoolValue; +import brachy.modularui.value.sync.EnumSyncValue; +import brachy.modularui.value.sync.PanelSyncManager; +import brachy.modularui.widgets.SlotGroupWidget; +import brachy.modularui.widgets.layout.Flow; + +public interface IMuiCover extends IUIHolder { + + default CoverBehavior self() { + return (CoverBehavior) this; + } + + default boolean isRemote() { + return self().coverHolder.isRemote(); + } + + default boolean isRemoved() { + return self().coverHolder.isRemoved() || self().coverHolder.getCoverAtSide(self().attachedSide) != self(); + } + + default GTGuiTheme getUITheme() { + return GTGuiTheme.COVER; + } + + @Override + @OnlyIn(Dist.CLIENT) + default ModularScreen createScreen(SidedPosGuiData data, ModularPanel mainPanel) { + return new GTGuiScreen(mainPanel); + } + + @Override + default ModularPanel buildUI(SidedPosGuiData data, PanelSyncManager syncManager, UISettings settings) { + ModularPanel panel = ModularPanel.defaultPanel(this.self().coverDefinition.getId().getPath(), 176, 192 + 18); + + panel.child(GTMuiWidgets.createTitleBar(this.self().getAttachItem(), 176, GTGuiTextures.BACKGROUND)); + + Flow column = Flow.column() + .top(7).margin(7, 0) + .childPadding(2) + .widthRel(1.0f).coverChildrenHeight(); + + createCoverUIRows(column, data, syncManager, settings); + return panel.child(column) + .child(SlotGroupWidget.playerInventory(false).left(7).bottom(7)); + } + + /** + * The default cover UI panel builds a single column with rows added by each cover. + */ + default void createCoverUIRows(Flow column, SidedPosGuiData data, PanelSyncManager syncManager, + UISettings settings) {} + + /* Helper methods for UI creation with covers that are commonly used */ + + /** + * The color used for Cover UI text. Available for reference, but is + * handled automatically by the {@link GTGuiTheme#COVER} theme. + */ + int UI_TEXT_COLOR = 0xFF555555; + + default Flow coverUIRow() { + return Flow.row() + .coverChildrenHeight() + .widthRel(1f) + .childPadding(2); + } + + /** + * Get a BoolValue for use with toggle buttons which are "linked together," + * meaning only one of them can be pressed at a time. + */ + default > BoolValue.Dynamic boolValueOf(EnumSyncValue syncValue, T value) { + return new BoolValue.Dynamic(() -> syncValue.getValue() == value, $ -> syncValue.setValue(value)); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/IUICover.java b/src/main/java/com/gregtechceu/gtceu/api/cover/IUICover.java deleted file mode 100644 index 93d85bd74f5..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/cover/IUICover.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.gregtechceu.gtceu.api.cover; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.UITemplate; - -import com.lowdragmc.lowdraglib.gui.modular.IUIHolder; -import com.lowdragmc.lowdraglib.gui.modular.ModularUI; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.utils.Position; - -import net.minecraft.world.entity.player.Player; - -public interface IUICover extends IUIHolder { - - default CoverBehavior self() { - return (CoverBehavior) this; - } - - @Override - default boolean isInvalid() { - return self().coverHolder.isRemoved() || self().coverHolder.getCoverAtSide(self().attachedSide) != self(); - } - - @Override - default boolean isRemote() { - return self().coverHolder.isRemote(); - } - - @Override - default ModularUI createUI(Player entityPlayer) { - var widget = createUIWidget(); - var size = widget.getSize(); - widget.setSelfPosition(new Position((176 - size.width) / 2, 0)); - var modularUI = new ModularUI(176, size.height + 82, this, entityPlayer) - .background(GuiTextures.BACKGROUND) - .widget(widget) - .widget(UITemplate.bindPlayerInventory(entityPlayer.getInventory(), GuiTextures.SLOT, 7, size.height, - true)); - modularUI.registerCloseListener(this::onUIClosed); - return modularUI; - } - - default void onUIClosed() {} - - Widget createUIWidget(); - - @Override - default void markAsDirty() {} -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/Filter.java b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/Filter.java index 304aef62395..cdb011c12c0 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/Filter.java +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/Filter.java @@ -1,15 +1,21 @@ package com.gregtechceu.gtceu.api.cover.filter; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - import net.minecraft.nbt.CompoundTag; +import brachy.modularui.factory.GuiData; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.sync.PanelSyncManager; + import java.util.function.Consumer; import java.util.function.Predicate; public interface Filter> extends Predicate { - WidgetGroup openConfigurator(int x, int y); + /** + * @return Filter panel when opened by itself (including the player inventory) + */ + ModularPanel getPanel(GuiData data, PanelSyncManager syncManager, UISettings settings); CompoundTag saveFilter(); diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/FilterHandler.java b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/FilterHandler.java index ea051ee971f..ac2f13b4d4f 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/FilterHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/FilterHandler.java @@ -2,8 +2,6 @@ import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.api.cover.CoverBehavior; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.widget.SlotWidget; import com.gregtechceu.gtceu.api.machine.MachineCoverContainer; import com.gregtechceu.gtceu.api.machine.MetaMachine; import com.gregtechceu.gtceu.api.sync_system.ISyncManaged; @@ -12,10 +10,6 @@ import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; import com.gregtechceu.gtceu.api.transfer.item.CustomItemStackHandler; -import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.world.item.ItemStack; @@ -43,40 +37,24 @@ public abstract class FilterHandler> implements ISyncM private @Nullable F filter; private @Nullable CustomItemStackHandler filterSlot; - private @Nullable WidgetGroup filterGroup; private @NotNull Consumer onFilterLoaded = (filter) -> {}; - private @NotNull Consumer onFilterRemoved = (filter) -> {}; + private @NotNull Runnable onFilterRemoved = () -> {}; private @NotNull Consumer onFilterUpdated = (filter) -> {}; public FilterHandler(ISyncManaged container) { this.container = container; } - protected abstract F loadFilter(ItemStack filterItem); + public abstract F loadFilter(ItemStack filterItem); protected abstract F getEmptyFilter(); - protected abstract boolean canInsertFilterItem(ItemStack itemStack); - ////////////////////////////////// // ***** PUBLIC API ******// ////////////////////////////////// - public Widget createFilterSlotUI(int xPos, int yPos) { - return new SlotWidget(getFilterSlot(), 0, xPos, yPos) - .setChangeListener(this::updateFilter) - .setBackgroundTexture(new GuiTextureGroup(GuiTextures.SLOT, GuiTextures.FILTER_SLOT_OVERLAY)); - } - - public Widget createFilterConfigUI(int xPos, int yPos, int width, int height) { - this.filterGroup = new WidgetGroup(xPos, yPos, width, height); - if (!this.filterItem.isEmpty()) { - this.filterGroup.addWidget(getFilter().openConfigurator(0, 0)); - } - - return this.filterGroup; - } + public abstract boolean canInsertFilterItem(ItemStack itemStack); public boolean isFilterPresent() { return filter != null || !filterItem.isEmpty(); @@ -103,7 +81,7 @@ public FilterHandler onFilterLoaded(Consumer onFilterLoaded) { return this; } - public FilterHandler onFilterRemoved(Consumer onFilterRemoved) { + public FilterHandler onFilterRemoved(Runnable onFilterRemoved) { this.onFilterRemoved = onFilterRemoved; return this; } @@ -117,7 +95,7 @@ public FilterHandler onFilterUpdated(Consumer onFilterUpdated) { // ***** FILTER HANDLING ******// /////////////////////////////////////// - private CustomItemStackHandler getFilterSlot() { + public CustomItemStackHandler getFilterSlot() { if (this.filterSlot == null) { this.filterSlot = new CustomItemStackHandler(this.filterItem) { @@ -152,7 +130,7 @@ private void updateFilter() { if (this.filter != null) { this.filter = null; - this.onFilterRemoved.accept(this.filter); + this.onFilterRemoved.run(); } loadFilterFromItem(); @@ -172,18 +150,6 @@ private void loadFilterFromItem() { } this.onFilterLoaded.accept(this.filter); } - updateFilterGroupUI(); - } - - private void updateFilterGroupUI() { - if (this.filterGroup == null) - return; - - this.filterGroup.clearAllWidgets(); - - if (!this.filterItem.isEmpty() && this.filter != null) { - this.filterGroup.addWidget(this.filter.openConfigurator(0, 0)); - } } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/FilterHandlers.java b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/FilterHandlers.java index cb269e0aa23..c48c9f4d0e8 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/FilterHandlers.java +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/FilterHandlers.java @@ -2,16 +2,21 @@ import com.gregtechceu.gtceu.api.sync_system.ISyncManaged; +import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.world.item.ItemStack; import net.minecraftforge.fluids.FluidStack; +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault public interface FilterHandlers { static FilterHandler item(ISyncManaged container) { return new FilterHandler<>(container) { @Override - protected ItemFilter loadFilter(ItemStack filterItem) { + public ItemFilter loadFilter(ItemStack filterItem) { return ItemFilter.loadFilter(filterItem); } @@ -21,7 +26,7 @@ protected ItemFilter getEmptyFilter() { } @Override - protected boolean canInsertFilterItem(ItemStack itemStack) { + public boolean canInsertFilterItem(ItemStack itemStack) { return ItemFilter.FILTERS.containsKey(itemStack.getItem()); } }; @@ -31,7 +36,7 @@ static FilterHandler fluid(ISyncManaged container) { return new FilterHandler<>(container) { @Override - protected FluidFilter loadFilter(ItemStack filterItem) { + public FluidFilter loadFilter(ItemStack filterItem) { return FluidFilter.loadFilter(filterItem); } @@ -41,7 +46,7 @@ protected FluidFilter getEmptyFilter() { } @Override - protected boolean canInsertFilterItem(ItemStack itemStack) { + public boolean canInsertFilterItem(ItemStack itemStack) { return FluidFilter.FILTERS.containsKey(itemStack.getItem()); } }; diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/FluidFilter.java b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/FluidFilter.java index 9a8a09fb68e..eb2c1191c4e 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/FluidFilter.java +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/FluidFilter.java @@ -1,12 +1,14 @@ package com.gregtechceu.gtceu.api.cover.filter; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.ItemLike; import net.minecraftforge.fluids.FluidStack; +import brachy.modularui.factory.GuiData; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.sync.PanelSyncManager; import org.apache.commons.lang3.NotImplementedException; import java.util.HashMap; @@ -54,8 +56,8 @@ public int testFluidAmount(FluidStack fluidStack) { } @Override - public WidgetGroup openConfigurator(int x, int y) { - throw new NotImplementedException("Not available for empty fluid filter"); + public ModularPanel getPanel(GuiData data, PanelSyncManager syncManager, UISettings settings) { + return null; } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/ItemFilter.java b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/ItemFilter.java index 73e24344dc7..a149cd64ab3 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/ItemFilter.java +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/ItemFilter.java @@ -1,11 +1,13 @@ package com.gregtechceu.gtceu.api.cover.filter; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.ItemLike; +import brachy.modularui.factory.GuiData; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.sync.PanelSyncManager; import org.apache.commons.lang3.NotImplementedException; import java.util.HashMap; @@ -53,8 +55,8 @@ public boolean test(ItemStack itemStack) { } @Override - public WidgetGroup openConfigurator(int x, int y) { - throw new NotImplementedException("Not available for empty item filter"); + public ModularPanel getPanel(GuiData data, PanelSyncManager syncManager, UISettings settings) { + return null; } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SimpleFluidFilter.java b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SimpleFluidFilter.java index d2c6610a644..d32f3afba1e 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SimpleFluidFilter.java +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SimpleFluidFilter.java @@ -1,11 +1,9 @@ package com.gregtechceu.gtceu.api.cover.filter; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.widget.ScrollablePhantomFluidWidget; -import com.gregtechceu.gtceu.api.gui.widget.ToggleButtonWidget; import com.gregtechceu.gtceu.api.transfer.fluid.CustomFluidTank; - -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; +import com.gregtechceu.gtceu.common.data.GTItems; +import com.gregtechceu.gtceu.common.mui.GTGuiTextures; +import com.gregtechceu.gtceu.common.mui.GTMuiWidgets; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.nbt.CompoundTag; @@ -14,6 +12,18 @@ import net.minecraft.world.item.ItemStack; import net.minecraftforge.fluids.FluidStack; +import brachy.modularui.factory.GuiData; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.sync.BooleanSyncValue; +import brachy.modularui.value.sync.FluidSlotSyncHandler; +import brachy.modularui.value.sync.PanelSyncManager; +import brachy.modularui.widgets.Dialog; +import brachy.modularui.widgets.SlotGroupWidget; +import brachy.modularui.widgets.ToggleButton; +import brachy.modularui.widgets.layout.Flow; +import brachy.modularui.widgets.layout.Grid; +import brachy.modularui.widgets.slot.FluidSlot; import lombok.Getter; import java.util.Arrays; @@ -38,9 +48,17 @@ public class SimpleFluidFilter implements FluidFilter { @Getter protected int maxStackSize = 1; - private CustomFluidTank[] fluidStorageSlots = new CustomFluidTank[9]; + private final CustomFluidTank[] fluidStorageSlots = new CustomFluidTank[9]; protected SimpleFluidFilter() { + for (int i = 0; i < 9; i++) { + int finalI = i; + fluidStorageSlots[i] = new CustomFluidTank(64000); + fluidStorageSlots[i].setOnContentsChanged(() -> { + matches[finalI] = fluidStorageSlots[finalI].getFluid(); + onUpdated.accept(this); + }); + } Arrays.fill(matches, FluidStack.EMPTY); } @@ -56,6 +74,7 @@ private static SimpleFluidFilter loadFilter(CompoundTag tag, Consumer fluidStorageSlots[index].getFluid(), - (fluid) -> fluidStorageSlots[index].setFluid(fluid)) { - - @Override - public void updateScreen() { - super.updateScreen(); - setShowAmount(maxStackSize > 1L); - } - - @Override - public void detectAndSendChanges() { - super.detectAndSendChanges(); - setShowAmount(maxStackSize > 1L); - } - }; - - tank.setChangeListener(() -> { - matches[index] = fluidStorageSlots[index].getFluidInTank(0); - onUpdated.accept(this); - }).setBackground(GuiTextures.SLOT); - - group.addWidget(tank); - } + @Override + public ModularPanel getPanel(GuiData data, PanelSyncManager syncManager, UISettings settings) { + for (int i = 0; i < 9; i++) { + syncManager.syncValue("filter_slot_" + i, + new FluidSlotSyncHandler(fluidStorageSlots[i]).controlsAmount(true).phantom(true)); } - group.addWidget(new ToggleButtonWidget(18 * 3 + 5, 0, 20, 20, - GuiTextures.BUTTON_BLACKLIST, this::isBlackList, this::setBlackList)); - group.addWidget(new ToggleButtonWidget(18 * 3 + 5, 20, 20, 20, - GuiTextures.BUTTON_FILTER_NBT, this::isIgnoreNbt, this::setIgnoreNbt)); - return group; + + Grid filterGrid = new Grid() + .coverChildren() + .mapTo(3, 9, i -> new FluidSlot().syncHandler("filter_slot_" + i)); + + BooleanSyncValue blacklist = new BooleanSyncValue(this::isBlackList, this::setBlackList); + syncManager.syncValue("blacklist", blacklist); + + BooleanSyncValue ignoreNBT = new BooleanSyncValue(this::isIgnoreNbt, this::setIgnoreNbt); + syncManager.syncValue("ignoreNBT", ignoreNBT); + + Flow filterConfigButtons = Flow.col() + .coverChildren() + .child(new ToggleButton().stateBackground(GTGuiTextures.BUTTON_BLACKLIST).syncHandler("blacklist")) + .child(new ToggleButton().stateBackground(GTGuiTextures.BUTTON_IGNORE_NBT).syncHandler("ignoreNBT")); + + return new Dialog<>("simple_fluid_filter") + .disablePanelsBelow(false) + .draggable(true) + .closeOnOutOfBoundsClick(true) + .child(GTMuiWidgets.createTitleBar(GTItems.FLUID_FILTER.asStack(), 176, GTGuiTextures.BACKGROUND)) + .child(Flow.row() + .top(10) + .coverChildrenHeight() + .child(filterGrid.horizontalCenter()) + .child(filterConfigButtons.marginLeft(118))) + .child(SlotGroupWidget.playerInventory(false).left(7).bottom(7)); } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SimpleItemFilter.java b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SimpleItemFilter.java index 408a6656687..b187f36ec1b 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SimpleItemFilter.java +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SimpleItemFilter.java @@ -1,20 +1,32 @@ package com.gregtechceu.gtceu.api.cover.filter; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.widget.PhantomSlotWidget; -import com.gregtechceu.gtceu.api.gui.widget.ToggleButtonWidget; import com.gregtechceu.gtceu.api.transfer.item.CustomItemStackHandler; +import com.gregtechceu.gtceu.common.data.GTItems; +import com.gregtechceu.gtceu.common.mui.GTGuiTextures; +import com.gregtechceu.gtceu.common.mui.GTMuiWidgets; import com.gregtechceu.gtceu.utils.GTUtil; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.world.item.ItemStack; +import brachy.modularui.factory.GuiData; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.sync.BooleanSyncValue; +import brachy.modularui.value.sync.PanelSyncManager; +import brachy.modularui.value.sync.PhantomItemSlotSyncHandler; +import brachy.modularui.widgets.Dialog; +import brachy.modularui.widgets.SlotGroupWidget; +import brachy.modularui.widgets.ToggleButton; +import brachy.modularui.widgets.layout.Flow; +import brachy.modularui.widgets.layout.Grid; +import brachy.modularui.widgets.slot.ModularSlot; +import brachy.modularui.widgets.slot.PhantomItemSlot; import lombok.Getter; +import org.jetbrains.annotations.NotNull; import java.util.Arrays; import java.util.function.Consumer; @@ -97,42 +109,87 @@ public void setIgnoreNbt(boolean ingoreNbt) { onUpdated.accept(this); } - public WidgetGroup openConfigurator(int x, int y) { - WidgetGroup group = new WidgetGroup(x, y, 18 * 3 + 25, 18 * 3); // 80 55 - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - final int index = i * 3 + j; + @Override + public ModularPanel getPanel(GuiData data, PanelSyncManager syncManager, UISettings settings) { + FilterItemStackHandler handler = new FilterItemStackHandler(matches, this); + + Grid filterGrid = new Grid() + .coverChildren() + .mapTo(3, 9, i -> new PhantomItemSlot() + .size(16) + .syncHandler(new PhantomItemSlotSyncHandler(new ModularSlot(handler, i) + .changeListener((stack, amount, client, init) -> { + handler.setStackInSlot(i, stack); + }).ignoreMaxStackSize(true).accessibility(true, false)))); + + BooleanSyncValue blacklist = new BooleanSyncValue(this::isBlackList, this::setBlackList); + syncManager.syncValue("blacklist", blacklist); + + BooleanSyncValue ignoreNBT = new BooleanSyncValue(this::isIgnoreNbt, this::setIgnoreNbt); + syncManager.syncValue("ignoreNBT", ignoreNBT); + + Flow filterConfigButtons = Flow.col() + .coverChildren() + .child(new ToggleButton().stateBackground(GTGuiTextures.BUTTON_BLACKLIST).syncHandler("blacklist")) + .child(new ToggleButton().stateBackground(GTGuiTextures.BUTTON_IGNORE_NBT).syncHandler("ignoreNBT")); + + return new Dialog<>("simple_item_filter") + .disablePanelsBelow(false) + .draggable(true) + .closeOnOutOfBoundsClick(true) + .child(GTMuiWidgets.createTitleBar(GTItems.ITEM_FILTER.asStack(), 176, GTGuiTextures.BACKGROUND)) + .child(Flow.row() + .top(10) + .coverChildrenHeight() + .child(filterGrid.horizontalCenter()) + .child(filterConfigButtons.marginLeft(118))) + .child(SlotGroupWidget.playerInventory(false).left(7).bottom(7)); + } + + public static class FilterItemStackHandler extends CustomItemStackHandler { - var handler = new CustomItemStackHandler(matches[index]); + private final ItemStack[] matches; + private final SimpleItemFilter filter; - var slot = new PhantomSlotWidget(handler, 0, i * 18, j * 18) { + public FilterItemStackHandler(SimpleItemFilter filter) { + this(filter.matches, filter); + } - @Override - public void updateScreen() { - super.updateScreen(); - setMaxStackSize(maxStackSize); - } + public FilterItemStackHandler(ItemStack[] matches, SimpleItemFilter simpleItemFilter) { + super(matches.length); + this.matches = matches; + this.filter = simpleItemFilter; + } - @Override - public void detectAndSendChanges() { - super.detectAndSendChanges(); - setMaxStackSize(maxStackSize); - } - }; + @Override + public @NotNull ItemStack getStackInSlot(int slot) { + return matches[slot]; + } - slot.setChangeListener(() -> { - matches[index] = handler.getStackInSlot(0); - onUpdated.accept(this); - }).setBackground(GuiTextures.SLOT); + @Override + protected int getStackLimit(int slot, @NotNull ItemStack stack) { + return 1; + } - group.addWidget(slot); + @Override + public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) { + if (amount >= matches[slot].getCount()) { + matches[slot] = ItemStack.EMPTY; } + return matches[slot]; + } + + @Override + public @NotNull ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + return stack; + } + + @Override + public void setStackInSlot(int slot, @NotNull ItemStack stack) { + super.setStackInSlot(slot, stack); + matches[slot] = stack.copyWithCount(1); + filter.onUpdated.accept(filter); } - group.addWidget(new ToggleButtonWidget(18 * 3 + 5, 0, 20, 20, - GuiTextures.BUTTON_BLACKLIST, this::isBlackList, this::setBlackList)); - group.addWidget(new ToggleButtonWidget(18 * 3 + 5, 20, 20, 20, - GuiTextures.BUTTON_FILTER_NBT, this::isIgnoreNbt, this::setIgnoreNbt)); - return group; } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SmartItemFilter.java b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SmartItemFilter.java index c26624f1c2d..4fb3ecb820d 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SmartItemFilter.java +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SmartItemFilter.java @@ -1,22 +1,34 @@ package com.gregtechceu.gtceu.api.cover.filter; +import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.api.capability.recipe.ItemRecipeCapability; -import com.gregtechceu.gtceu.api.gui.widget.EnumSelectorWidget; import com.gregtechceu.gtceu.api.recipe.GTRecipeType; import com.gregtechceu.gtceu.api.recipe.content.Content; +import com.gregtechceu.gtceu.common.data.GTItems; import com.gregtechceu.gtceu.common.data.GTRecipeTypes; +import com.gregtechceu.gtceu.common.mui.GTGuiTextures; +import com.gregtechceu.gtceu.common.mui.GTMuiWidgets; import com.gregtechceu.gtceu.utils.ItemStackHashStrategy; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; +import brachy.modularui.api.drawable.IKey; +import brachy.modularui.drawable.ColorType; +import brachy.modularui.drawable.UITexture; +import brachy.modularui.factory.GuiData; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.sync.EnumSyncValue; +import brachy.modularui.value.sync.PanelSyncManager; +import brachy.modularui.widgets.Dialog; +import brachy.modularui.widgets.SlotGroupWidget; import it.unimi.dsi.fastutil.objects.Object2IntOpenCustomHashMap; +import lombok.Getter; +import java.util.Arrays; import java.util.Collections; import java.util.function.Consumer; @@ -25,6 +37,7 @@ public class SmartItemFilter implements ItemFilter { protected Consumer itemWriter = filter -> {}; protected Consumer onUpdated = filter -> itemWriter.accept(filter); + @Getter private SmartFilteringMode filterMode = SmartFilteringMode.ELECTROLYZER; protected SmartItemFilter() {} @@ -69,11 +82,23 @@ private void setFilterMode(SmartFilteringMode filterMode) { } @Override - public WidgetGroup openConfigurator(int x, int y) { - WidgetGroup group = new WidgetGroup(x, y, 18 * 3 + 25, 18 * 3); - group.addWidget(new EnumSelectorWidget<>(16, 8, 32, 32, - SmartFilteringMode.VALUES, filterMode, this::setFilterMode)); - return group; + public ModularPanel getPanel(GuiData data, PanelSyncManager syncManager, UISettings settings) { + EnumSyncValue mode = new EnumSyncValue<>(SmartFilteringMode.class, + this::getFilterMode, this::setFilterMode); + + syncManager.syncValue("mode", mode); + + return new Dialog<>("smart_item_filter") + .disablePanelsBelow(false) + .draggable(true) + .closeOnOutOfBoundsClick(true) + .child(GTMuiWidgets.createTitleBar(GTItems.SMART_ITEM_FILTER.asStack(), 176, GTGuiTextures.BACKGROUND)) + .child(new GTMuiWidgets.EnumRowBuilder<>(SmartFilteringMode.class) + .value(mode) + .overlay(16, SmartFilteringMode.getTextures()) + .lang(IKey.dynamic(() -> Component.translatable(filterMode.localeName))) + .build().margin(7)) + .child(SlotGroupWidget.playerInventory(false).left(7).bottom(7)); } @Override @@ -112,7 +137,7 @@ public void setModeFromMachine(String machineName) { } @MethodsReturnNonnullByDefault - private enum SmartFilteringMode implements EnumSelectorWidget.SelectableEnum { + private enum SmartFilteringMode { ELECTROLYZER("electrolyzer", GTRecipeTypes.ELECTROLYZER_RECIPES), CENTRIFUGE("centrifuge", GTRecipeTypes.CENTRIFUGE_RECIPES), @@ -129,14 +154,15 @@ private enum SmartFilteringMode implements EnumSelectorWidget.SelectableEnum { this.recipeType = type; } - @Override public String getTooltip() { return "cover.item_smart_filter.filtering_mode." + localeName; } - @Override - public IGuiTexture getIcon() { - return new ResourceTexture("gtceu:textures/block/machines/" + localeName + "/overlay_front.png"); + public static UITexture[] getTextures() { + return Arrays.stream(VALUES) + .map(v -> UITexture.fullImage(GTCEu.MOD_ID, + "textures/block/machines/" + v.localeName + "/overlay_front.png", ColorType.DEFAULT)) + .toArray(UITexture[]::new); } } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagFilter.java b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagFilter.java index 712f8be4a57..83aace338fa 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagFilter.java +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagFilter.java @@ -1,32 +1,30 @@ package com.gregtechceu.gtceu.api.cover.filter; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.data.lang.LangHandler; +import com.gregtechceu.gtceu.common.mui.GTGuiTextures; +import com.gregtechceu.gtceu.common.mui.GTMuiWidgets; import com.gregtechceu.gtceu.utils.TagExprFilter; -import com.lowdragmc.lowdraglib.gui.widget.ImageWidget; -import com.lowdragmc.lowdraglib.gui.widget.TextFieldWidget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.MutableComponent; - +import net.minecraft.world.item.ItemStack; + +import brachy.modularui.factory.GuiData; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.RichTooltip; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.sync.PanelSyncManager; +import brachy.modularui.value.sync.StringSyncValue; +import brachy.modularui.widgets.Dialog; +import brachy.modularui.widgets.SlotGroupWidget; +import brachy.modularui.widgets.layout.Flow; +import brachy.modularui.widgets.textfield.TextFieldWidget; import lombok.Getter; import java.util.function.Consumer; -import java.util.regex.Pattern; public abstract class TagFilter> implements Filter { - private static final Pattern DOUBLE_WILDCARD = Pattern.compile("\\*{2,}"); - private static final Pattern DOUBLE_AND = Pattern.compile("&{2,}"); - private static final Pattern DOUBLE_OR = Pattern.compile("\\|{2,}"); - private static final Pattern DOUBLE_NOT = Pattern.compile("!{2,}"); - private static final Pattern DOUBLE_XOR = Pattern.compile("\\^{2,}"); - private static final Pattern DOUBLE_SPACE = Pattern.compile(" {2,}"); - @Getter - protected String oreDictFilterExpression = ""; + protected String filterString = ""; protected Consumer itemWriter = filter -> {}; protected Consumer onUpdated = filter -> itemWriter.accept(filter); @@ -37,7 +35,7 @@ protected TagFilter() {} @Override public boolean isBlank() { - return oreDictFilterExpression.isBlank(); + return filterString.isBlank(); } public CompoundTag saveFilter() { @@ -45,78 +43,34 @@ public CompoundTag saveFilter() { return null; } var tag = new CompoundTag(); - tag.putString("oreDict", oreDictFilterExpression); + tag.putString("oreDict", filterString); return tag; } - public void setOreDict(String oreDict) { - this.oreDictFilterExpression = oreDict; - matchExpr = TagExprFilter.parseExpression(oreDictFilterExpression); + public void setFilterString(String filterString) { + this.filterString = filterString; + matchExpr = TagExprFilter.parseExpression(filterString); onUpdated.accept((S) this); } - public WidgetGroup openConfigurator(int x, int y) { - WidgetGroup group = new WidgetGroup(x, y, 18 * 3 + 25, 18 * 3); // 80 55 - group.addWidget(new ImageWidget(0, 0, 20, 20, GuiTextures.INFO_ICON) - .setHoverTooltips( - LangHandler.getMultiLang("cover.tag_filter.info").toArray(new MutableComponent[0]))); - group.addWidget(new TextFieldWidget(0, 29, 18 * 3 + 25, 12, () -> oreDictFilterExpression, this::setOreDict) - .setMaxStringLength(64) - .setValidator(input -> { - // remove all operators that are double - input = DOUBLE_WILDCARD.matcher(input).replaceAll("*"); - input = DOUBLE_AND.matcher(input).replaceAll("&"); - input = DOUBLE_OR.matcher(input).replaceAll("|"); - input = DOUBLE_NOT.matcher(input).replaceAll("!"); - input = DOUBLE_XOR.matcher(input).replaceAll("^"); - input = DOUBLE_SPACE.matcher(input).replaceAll(" "); - // move ( and ) so it doesn't create invalid expressions f.e. xxx (& yyy) => xxx & (yyy) - // append or prepend ( and ) if the amount is not equal - StringBuilder builder = new StringBuilder(); - int unclosed = 0; - char last = ' '; - for (int i = 0; i < input.length(); i++) { - char c = input.charAt(i); - if (c == ' ') { - if (last != '(') - builder.append(" "); - continue; - } - if (c == '(') - unclosed++; - else if (c == ')') { - unclosed--; - if (last == '&' || last == '|' || last == '^') { - int l = builder.lastIndexOf(" " + last); - int l2 = builder.lastIndexOf(String.valueOf(last)); - builder.insert(l == l2 - 1 ? l : l2, ")"); - continue; - } - if (i > 0 && builder.charAt(builder.length() - 1) == ' ') { - builder.deleteCharAt(builder.length() - 1); - } - } else if ((c == '&' || c == '|' || c == '^') && last == '(') { - builder.deleteCharAt(builder.lastIndexOf("(")); - builder.append(c).append(" ("); - continue; - } - - builder.append(c); - last = c; - } - if (unclosed > 0) { - builder.append(")".repeat(unclosed)); - } else if (unclosed < 0) { - unclosed = -unclosed; - for (int i = 0; i < unclosed; i++) { - builder.insert(0, "("); - } - } - input = builder.toString(); - input = input.replaceAll(" {2,}", " "); - return input; - })); - return group; + protected abstract ItemStack getFilterItem(); + + @Override + public ModularPanel getPanel(GuiData data, PanelSyncManager syncManager, UISettings settings) { + StringSyncValue filterString = new StringSyncValue(this::getFilterString, this::setFilterString); + RichTooltip infoTooltip = new RichTooltip().add("cover.tag_filter.info"); + + var inputRow = Flow.row().margin(7).coverChildren().horizontalCenter() + .child(new TextFieldWidget().width(140).value(filterString)) + .child(GTGuiTextures.INFO.asWidget().tooltip(infoTooltip)); + + return new Dialog<>("tag_filter") + .disablePanelsBelow(false) + .draggable(true) + .closeOnOutOfBoundsClick(true) + .child(GTMuiWidgets.createTitleBar(getFilterItem(), 176, GTGuiTextures.BACKGROUND)) + .child(inputRow) + .child(SlotGroupWidget.playerInventory(false).left(7).bottom(7)); } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagFluidFilter.java b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagFluidFilter.java index ff54bd91eb0..014a14e0898 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagFluidFilter.java +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagFluidFilter.java @@ -1,5 +1,6 @@ package com.gregtechceu.gtceu.api.cover.filter; +import com.gregtechceu.gtceu.common.data.GTItems; import com.gregtechceu.gtceu.utils.TagExprFilter; import net.minecraft.nbt.CompoundTag; @@ -27,21 +28,26 @@ public static TagFluidFilter loadFilter(ItemStack itemStack) { private static TagFluidFilter loadFilter(CompoundTag tag, Consumer itemWriter) { var handler = new TagFluidFilter(); handler.itemWriter = itemWriter; - handler.oreDictFilterExpression = tag.getString("oreDict"); + handler.filterString = tag.getString("oreDict"); handler.matchExpr = null; handler.cache.clear(); - handler.matchExpr = TagExprFilter.parseExpression(handler.oreDictFilterExpression); + handler.matchExpr = TagExprFilter.parseExpression(handler.filterString); return handler; } - public void setOreDict(String oreDict) { + public void setFilterString(String oreDict) { cache.clear(); - super.setOreDict(oreDict); + super.setFilterString(oreDict); + } + + @Override + protected ItemStack getFilterItem() { + return GTItems.TAG_FLUID_FILTER.asStack(); } @Override public boolean test(FluidStack fluidStack) { - if (oreDictFilterExpression.isEmpty()) return false; + if (filterString.isEmpty()) return false; if (cache.containsKey(fluidStack.getFluid())) return cache.getOrDefault(fluidStack.getFluid(), false); if (TagExprFilter.tagsMatch(matchExpr, fluidStack)) { cache.put(fluidStack.getFluid(), true); diff --git a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagItemFilter.java b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagItemFilter.java index 5018590726a..e33eca3e7df 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagItemFilter.java +++ b/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagItemFilter.java @@ -1,5 +1,6 @@ package com.gregtechceu.gtceu.api.cover.filter; +import com.gregtechceu.gtceu.common.data.GTItems; import com.gregtechceu.gtceu.utils.TagExprFilter; import net.minecraft.nbt.CompoundTag; @@ -26,21 +27,26 @@ public static TagItemFilter loadFilter(ItemStack itemStack) { private static TagItemFilter loadFilter(CompoundTag tag, Consumer itemWriter) { var handler = new TagItemFilter(); handler.itemWriter = itemWriter; - handler.oreDictFilterExpression = tag.getString("oreDict"); + handler.filterString = tag.getString("oreDict"); handler.matchExpr = null; handler.cache.clear(); - handler.matchExpr = TagExprFilter.parseExpression(handler.oreDictFilterExpression); + handler.matchExpr = TagExprFilter.parseExpression(handler.filterString); return handler; } - public void setOreDict(String oreDict) { + public void setFilterString(String oreDict) { cache.clear(); - super.setOreDict(oreDict); + super.setFilterString(oreDict); + } + + @Override + protected ItemStack getFilterItem() { + return GTItems.TAG_FILTER.asStack(); } @Override public boolean test(ItemStack itemStack) { - if (oreDictFilterExpression.isEmpty()) return false; + if (filterString.isEmpty()) return false; if (cache.containsKey(itemStack.getItem())) return cache.getOrDefault(itemStack.getItem(), false); if (TagExprFilter.tagsMatch(matchExpr, itemStack)) { cache.put(itemStack.getItem(), true); diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/info/MaterialIconType.java b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/info/MaterialIconType.java index 52d57bac337..9a19269427b 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/info/MaterialIconType.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/info/MaterialIconType.java @@ -3,8 +3,7 @@ import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.common.data.models.GTModels; import com.gregtechceu.gtceu.integration.kjs.GTRegistryInfo; - -import com.lowdragmc.lowdraglib.utils.ResourceHelper; +import com.gregtechceu.gtceu.utils.GTUtil; import net.minecraft.client.Minecraft; import net.minecraft.resources.ResourceLocation; @@ -164,7 +163,7 @@ public ResourceLocation getBlockTexturePath(@NotNull MaterialIconSet materialIco while (!iconSet.isRootIconset) { ResourceLocation location = GTCEu .id(String.format("textures/block/material_sets/%s/%s%s.png", iconSet.name, this.name, suffix)); - if (ResourceHelper.isResourceExist(location) || ResourceHelper.isResourceExistRaw(location)) + if (GTUtil.resourceExists(location)) break; iconSet = iconSet.parentIconset; } @@ -172,8 +171,7 @@ public ResourceLocation getBlockTexturePath(@NotNull MaterialIconSet materialIco ResourceLocation location = GTCEu .id(String.format("textures/block/material_sets/%s/%s%s.png", iconSet.name, this.name, suffix)); - if (!suffix.isEmpty() && !ResourceHelper.isResourceExist(location) && - !ResourceHelper.isResourceExistRaw(location)) { + if (!suffix.isEmpty() && !GTUtil.resourceExists(location)) { return GTModels.BLANK_TEXTURE; } location = GTCEu.id(String.format("block/material_sets/%s/%s%s", iconSet.name, this.name, suffix)); @@ -201,7 +199,7 @@ public ResourceLocation getBlockModelPath(@NotNull MaterialIconSet materialIconS while (!iconSet.isRootIconset) { ResourceLocation location = GTCEu .id(String.format("models/block/material_sets/%s/%s.json", iconSet.name, this.name)); - if (ResourceHelper.isResourceExist(location) || ResourceHelper.isResourceExistRaw(location)) + if (GTUtil.resourceExists(location)) break; iconSet = iconSet.parentIconset; } @@ -228,7 +226,7 @@ public ResourceLocation getItemModelPath(@NotNull MaterialIconSet materialIconSe while (!iconSet.isRootIconset) { ResourceLocation location = GTCEu .id(String.format("models/item/material_sets/%s/%s.json", iconSet.name, this.name)); - if (ResourceHelper.isResourceExist(location) || ResourceHelper.isResourceExistRaw(location)) + if (GTUtil.resourceExists(location)) break; iconSet = iconSet.parentIconset; } @@ -267,7 +265,7 @@ public ResourceLocation getItemTexturePath(@NotNull MaterialIconSet materialIcon while (!iconSet.isRootIconset) { ResourceLocation location = GTCEu .id(String.format("textures/item/material_sets/%s/%s%s.png", iconSet.name, this.name, suffix)); - if (ResourceHelper.isResourceExist(location) || ResourceHelper.isResourceExistRaw(location)) + if (GTUtil.resourceExists(location)) break; iconSet = iconSet.parentIconset; } @@ -275,8 +273,7 @@ public ResourceLocation getItemTexturePath(@NotNull MaterialIconSet materialIcon ResourceLocation location = GTCEu .id(String.format("textures/item/material_sets/%s/%s%s.png", iconSet.name, this.name, suffix)); - if (!suffix.isEmpty() && !ResourceHelper.isResourceExist(location) && - !ResourceHelper.isResourceExistRaw(location)) { + if (!suffix.isEmpty() && !GTUtil.resourceExists(location)) { return null; } location = GTCEu.id(String.format("item/material_sets/%s/%s%s", iconSet.name, this.name, suffix)); diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/properties/HazardProperty.java b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/properties/HazardProperty.java index 2e7a12f3bb7..8d9e8e5e8ce 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/properties/HazardProperty.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/properties/HazardProperty.java @@ -116,7 +116,7 @@ public boolean isProtected(LivingEntity livingEntity) { for (ArmorItem.Type equipmentType : equipmentTypes) { ItemStack armor = livingEntity.getItemBySlot(equipmentType.getSlot()); if (!armor.isEmpty() && ((armor.getItem() instanceof ArmorComponentItem armorItem && - armorItem.getArmorLogic().isPPE()) || + armorItem.getArmorLogic().isPPE(armor)) || armor.getTags().anyMatch(tag -> tag.equals(CustomTags.PPE_ARMOR)))) { correctArmorItems.add(equipmentType); } @@ -135,7 +135,7 @@ public boolean isProtected(LivingEntity livingEntity) { for (SlotResult result : results) { ItemStack armor = result.stack(); if (!armor.isEmpty() && ((armor.getItem() instanceof ArmorComponentItem armorItem && - armorItem.getArmorLogic().isPPE()) || + armorItem.getArmorLogic().isPPE(armor)) || armor.getTags().anyMatch(tag -> tag.equals(CustomTags.PPE_ARMOR)))) { correctCurios.add(result.slotContext().identifier()); } @@ -149,7 +149,7 @@ public void damageEquipment(Player player, int amount) { for (ArmorItem.Type type : this.getEquipmentTypes()) { ItemStack armor = player.getItemBySlot(type.getSlot()); if (!armor.isEmpty() && ((armor.getItem() instanceof ArmorComponentItem armorItem && - armorItem.getArmorLogic().isPPE()) || + armorItem.getArmorLogic().isPPE(armor)) || armor.getTags().anyMatch(tag -> tag.equals(CustomTags.PPE_ARMOR)))) { armor.hurtAndBreak(amount, player, p -> p.broadcastBreakEvent(type.getSlot())); } @@ -165,7 +165,7 @@ public void damageEquipment(Player player, int amount) { for (int i = 0; i < handler.getSlots(); ++i) { ItemStack armor = stackHandler.getStackInSlot(i); if (!armor.isEmpty() && ((armor.getItem() instanceof ArmorComponentItem armorItem && - armorItem.getArmorLogic().isPPE()) || + armorItem.getArmorLogic().isPPE(armor)) || armor.getTags().anyMatch(tag -> tag.equals(CustomTags.PPE_ARMOR)))) { armor.hurtAndBreak(amount, player, p -> {}); } diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java index c438c7e0167..eccb723b760 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/tag/TagPrefix.java @@ -23,7 +23,7 @@ import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.data.recipe.CustomTags; import com.gregtechceu.gtceu.integration.kjs.GTRegistryInfo; -import com.gregtechceu.gtceu.integration.xei.widgets.GTOreByProduct; +import com.gregtechceu.gtceu.integration.recipeviewer.widgets.GTOreByProduct; import com.gregtechceu.gtceu.utils.FormattingUtil; import com.gregtechceu.gtceu.utils.memoization.GTMemoizer; diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/GuiTextures.java b/src/main/java/com/gregtechceu/gtceu/api/gui/GuiTextures.java index 2b1e3eecbd2..9e3b0948a63 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/GuiTextures.java +++ b/src/main/java/com/gregtechceu/gtceu/api/gui/GuiTextures.java @@ -1,5 +1,7 @@ package com.gregtechceu.gtceu.api.gui; +import com.gregtechceu.gtceu.GTCEu; + import com.lowdragmc.lowdraglib.gui.texture.ResourceBorderTexture; import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; @@ -194,6 +196,8 @@ public class GuiTextures { "gtceu:textures/item/storage_cover.png"); public static final ResourceTexture BUTTON_MINER_MODES = new ResourceTexture( "gtceu:textures/gui/widget/button_miner_modes.png"); + public static final ResourceTexture EQUIPMENT_FOUNDRY_BACKGROUND = new ResourceTexture( + GTCEu.id("textures/gui/widget/equipment_foundry_background.png")); // ORE PROCESSING public static final ResourceTexture OREBY_BASE = new ResourceTexture("gtceu:textures/gui/arrows/oreby-base.png"); diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/UITemplate.java b/src/main/java/com/gregtechceu/gtceu/api/gui/UITemplate.java deleted file mode 100644 index 46bb179cbeb..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/UITemplate.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.gregtechceu.gtceu.api.gui; - -import com.gregtechceu.gtceu.api.gui.widget.SlotWidget; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - -import net.minecraft.world.entity.player.Inventory; - -public class UITemplate { - - public static WidgetGroup bindPlayerInventory(Inventory inventoryPlayer, IGuiTexture imageLocation, int x, int y, - boolean addHotbar) { - WidgetGroup group = new WidgetGroup(x, y, 162, 54 + (addHotbar ? 22 : 0)); - for (int row = 0; row < 3; row++) { - for (int col = 0; col < 9; col++) { - group.addWidget(new SlotWidget(inventoryPlayer, col + (row + 1) * 9, col * 18, row * 18) - .setBackgroundTexture(imageLocation) - .setLocationInfo(true, false)); - } - } - if (addHotbar) { - for (int slot = 0; slot < 9; slot++) { - group.addWidget(new SlotWidget(inventoryPlayer, slot, slot * 18, 58) - .setBackgroundTexture(imageLocation) - .setLocationInfo(true, true)); - } - } - return group; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/editor/EditableMachineUI.java b/src/main/java/com/gregtechceu/gtceu/api/gui/editor/EditableMachineUI.java deleted file mode 100644 index 56798f4bace..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/editor/EditableMachineUI.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.editor; - -import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.api.machine.MetaMachine; - -import com.lowdragmc.lowdraglib.gui.editor.configurator.IConfigurableWidget; -import com.lowdragmc.lowdraglib.gui.editor.data.Resources; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.utils.Position; - -import net.minecraft.client.Minecraft; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtAccounter; -import net.minecraft.nbt.NbtIo; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.ResourceManager; - -import lombok.Getter; -import org.jetbrains.annotations.Nullable; - -import java.io.DataInputStream; -import java.io.InputStream; -import java.util.function.BiConsumer; -import java.util.function.Supplier; - -public class EditableMachineUI implements IEditableUI { - - @Getter - final String groupName; - @Getter - final ResourceLocation uiPath; - final Supplier widgetSupplier; - final BiConsumer binder; - @Nullable - private CompoundTag customUICache; - - public EditableMachineUI(String groupName, ResourceLocation uiPath, Supplier widgetSupplier, - BiConsumer binder) { - this.groupName = groupName; - this.uiPath = uiPath; - this.widgetSupplier = widgetSupplier; - this.binder = binder; - } - - public WidgetGroup createDefault() { - return widgetSupplier.get(); - } - - public void setupUI(WidgetGroup template, MetaMachine machine) { - binder.accept(template, machine); - } - - ////////////////////////////////////// - // ******** GUI *********// - ////////////////////////////////////// - - @Nullable - public WidgetGroup createCustomUI() { - if (hasCustomUI()) { - var nbt = getCustomUI(); - var group = new WidgetGroup(); - IConfigurableWidget.deserializeNBT(group, nbt.getCompound("root"), - Resources.fromNBT(nbt.getCompound("resources")), false); - group.setSelfPosition(new Position(0, 0)); - return group; - } - return null; - } - - public CompoundTag getCustomUI() { - if (this.customUICache == null) { - ResourceManager resourceManager = null; - if (GTCEu.isClientSide()) { - resourceManager = Minecraft.getInstance().getResourceManager(); - } else if (GTCEu.getMinecraftServer() != null) { - resourceManager = GTCEu.getMinecraftServer().getResourceManager(); - } - if (resourceManager == null) { - this.customUICache = new CompoundTag(); - } else { - try { - var resource = resourceManager.getResourceOrThrow(new ResourceLocation(uiPath.getNamespace(), - "ui/machine/%s.mui".formatted(uiPath.getPath()))); - try (InputStream inputStream = resource.open()) { - try (DataInputStream dataInputStream = new DataInputStream(inputStream);) { - this.customUICache = NbtIo.read(dataInputStream, NbtAccounter.UNLIMITED); - } - } - } catch (Exception e) { - this.customUICache = new CompoundTag(); - } - if (this.customUICache == null) { - this.customUICache = new CompoundTag(); - } - } - } - return this.customUICache; - } - - public boolean hasCustomUI() { - return !getCustomUI().isEmpty(); - } - - public void reloadCustomUI() { - this.customUICache = null; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/editor/EditableUI.java b/src/main/java/com/gregtechceu/gtceu/api/gui/editor/EditableUI.java deleted file mode 100644 index 3020d5f7676..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/editor/EditableUI.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.editor; - -import com.gregtechceu.gtceu.api.gui.WidgetUtils; - -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - -import lombok.Getter; - -import java.util.function.BiConsumer; -import java.util.function.Supplier; - -public class EditableUI implements IEditableUI { - - @Getter - final String id; - final Class clazz; - @Getter - final Supplier widgetSupplier; - @Getter - final BiConsumer binder; - - public EditableUI(String id, Class clazz, Supplier widgetSupplier, BiConsumer binder) { - this.id = id; - this.clazz = clazz; - this.widgetSupplier = widgetSupplier; - this.binder = binder; - } - - public W createDefault() { - var widget = widgetSupplier.get(); - widget.setId(id); - return widget; - } - - public void setupUI(WidgetGroup template, T instance) { - WidgetUtils.widgetByIdForEach(template, "^" + id + "$", clazz, w -> binder.accept(w, instance)); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/editor/GTUIEditor.java b/src/main/java/com/gregtechceu/gtceu/api/gui/editor/GTUIEditor.java deleted file mode 100644 index 9f372444007..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/editor/GTUIEditor.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.editor; - -import com.lowdragmc.lowdraglib.LDLib; -import com.lowdragmc.lowdraglib.gui.editor.Icons; -import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; -import com.lowdragmc.lowdraglib.gui.editor.ui.UIEditor; -import com.lowdragmc.lowdraglib.gui.editor.ui.tool.WidgetToolBox; - -import static com.lowdragmc.lowdraglib.gui.editor.ui.tool.WidgetToolBox.Default.registerTab; - -@LDLRegister(name = "editor.gtceu", group = "editor") -public class GTUIEditor extends UIEditor { - - public static final WidgetToolBox.Default GT_CONTAINER = registerTab("widget.gtm_container", - Icons.WIDGET_CONTAINER); - - public GTUIEditor() { - super(LDLib.location); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/editor/MachineUIProject.java b/src/main/java/com/gregtechceu/gtceu/api/gui/editor/MachineUIProject.java deleted file mode 100644 index ef0cf9410a0..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/editor/MachineUIProject.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.editor; - -import com.gregtechceu.gtceu.api.machine.MachineDefinition; -import com.gregtechceu.gtceu.api.registry.GTRegistries; - -import com.lowdragmc.lowdraglib.LDLib; -import com.lowdragmc.lowdraglib.gui.editor.ColorPattern; -import com.lowdragmc.lowdraglib.gui.editor.Icons; -import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; -import com.lowdragmc.lowdraglib.gui.editor.data.Resources; -import com.lowdragmc.lowdraglib.gui.editor.data.UIProject; -import com.lowdragmc.lowdraglib.gui.editor.ui.Editor; -import com.lowdragmc.lowdraglib.gui.editor.ui.tool.WidgetToolBox; -import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; -import com.lowdragmc.lowdraglib.gui.texture.ItemStackTexture; -import com.lowdragmc.lowdraglib.gui.texture.TextTexture; -import com.lowdragmc.lowdraglib.gui.util.TreeBuilder; -import com.lowdragmc.lowdraglib.gui.widget.TabButton; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.utils.Position; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtIo; -import net.minecraft.resources.ResourceLocation; - -import lombok.Getter; -import org.jetbrains.annotations.Nullable; - -import java.io.File; -import java.io.IOException; -import java.util.*; - -@LDLRegister(name = "mui", group = "editor.gtceu") -public class MachineUIProject extends UIProject { - - @Nullable - @Getter - protected MachineDefinition machineDefinition; - - private MachineUIProject() { - this(null, null); - } - - public MachineUIProject(Resources resources, WidgetGroup root) { - super(resources, root); - } - - public MachineUIProject(CompoundTag tag) { - super(tag); - } - - public void setMachine(@Nullable MachineDefinition machineDefinition) { - this.machineDefinition = machineDefinition; - } - - public MachineUIProject newEmptyProject() { - return new MachineUIProject(Resources.defaultResource(), new WidgetGroup(30, 30, 200, 150)); - } - - @Override - public UIProject loadProject(File file) { - try { - var tag = NbtIo.read(file); - if (tag != null) { - return new MachineUIProject(tag); - } - } catch (IOException ignored) {} - return null; - } - - @Override - public CompoundTag serializeNBT() { - var tag = super.serializeNBT(); - if (machineDefinition != null) { - tag.putString("machine", machineDefinition.getId().toString()); - } - return tag; - } - - @Override - public void deserializeNBT(CompoundTag tag) { - super.deserializeNBT(tag); - if (tag.contains("machine")) { - machineDefinition = GTRegistries.MACHINES.get(new ResourceLocation(tag.getString("machine"))); - } - } - - @Override - public void onLoad(Editor editor) { - editor.getResourcePanel().loadResource(getResources(), false); - editor.getTabPages().addTab(new TabButton(50, 16, 60, 14).setTexture( - new GuiTextureGroup(ColorPattern.T_GREEN.rectTexture().setBottomRadius(10).transform(0, 0.4f), - new TextTexture("Main")), - new GuiTextureGroup(ColorPattern.T_RED.rectTexture().setBottomRadius(10).transform(0, 0.4f), - new TextTexture("Main"))), - new UIMainPanel(editor, root, machineDefinition == null ? null : machineDefinition.getDescriptionId())); - - for (WidgetToolBox.Default tab : WidgetToolBox.Default.TABS) { - if (tab == WidgetToolBox.Default.CONTAINER) { - continue; - } - editor.getToolPanel().addNewToolBox("ldlib.gui.editor.group." + tab.groupName, tab.icon, - tab.createToolBox()); - } - } - - @Override - public void attachMenu(Editor editor, String name, TreeBuilder.Menu menu) { - if (name.equals("file")) { - if (machineDefinition == null || machineDefinition.getEditableUI() == null) { - menu.remove("ldlib.gui.editor.menu.save"); - } else { - menu.remove("ldlib.gui.editor.menu.save"); - menu.leaf(Icons.SAVE, "ldlib.gui.editor.menu.save", () -> { - var editableUI = machineDefinition.getEditableUI(); - var path = new File(LDLib.location, - "assets/%s/ui/machine".formatted(editableUI.getUiPath().getNamespace())); - path.mkdirs(); - saveProject(new File(path, editableUI.getUiPath().getPath() + "." + this.getRegisterUI().name())); - editableUI.reloadCustomUI(); - }); - } - } else if (name.equals("template_tab")) { - Map> categories = new LinkedHashMap<>(); - for (var definition : GTRegistries.MACHINES) { - final var editableUI = definition.getEditableUI(); - if (editableUI != null) { - // has editable UI - categories.computeIfAbsent(editableUI.getGroupName(), group -> new ArrayList<>()).add(definition); - } - } - categories.forEach((groupName, definitions) -> menu.branch(groupName, m -> { - Set addedSet = new HashSet<>(); - for (var definition : definitions) { - var editableUI = definition.getEditableUI(); - if (editableUI != null && addedSet.add(editableUI)) { - m.leaf(new ItemStackTexture(definition.asStack()), definition.getDescriptionId(), () -> { - root.clearAllWidgets(); - if (editableUI.hasCustomUI()) { - deserializeNBT(editableUI.getCustomUI()); - } else { - var template = editableUI.createDefault(); - template.setSelfPosition( - new Position(root.getSelfPosition().x, root.getSelfPosition().y)); - this.root = template; - } - setMachine(definition); - editor.loadProject(this); - }); - } - } - })); - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/editor/RecipeTypeUIProject.java b/src/main/java/com/gregtechceu/gtceu/api/gui/editor/RecipeTypeUIProject.java deleted file mode 100644 index 5927dedaea1..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/editor/RecipeTypeUIProject.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.editor; - -import com.gregtechceu.gtceu.api.recipe.GTRecipeType; -import com.gregtechceu.gtceu.api.registry.GTRegistries; - -import com.lowdragmc.lowdraglib.LDLib; -import com.lowdragmc.lowdraglib.gui.editor.ColorPattern; -import com.lowdragmc.lowdraglib.gui.editor.Icons; -import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; -import com.lowdragmc.lowdraglib.gui.editor.configurator.IConfigurableWidget; -import com.lowdragmc.lowdraglib.gui.editor.data.Resources; -import com.lowdragmc.lowdraglib.gui.editor.data.UIProject; -import com.lowdragmc.lowdraglib.gui.editor.ui.Editor; -import com.lowdragmc.lowdraglib.gui.editor.ui.tool.WidgetToolBox; -import com.lowdragmc.lowdraglib.gui.texture.*; -import com.lowdragmc.lowdraglib.gui.util.TreeBuilder; -import com.lowdragmc.lowdraglib.gui.widget.*; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtIo; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Items; - -import lombok.Getter; -import lombok.Setter; -import org.jetbrains.annotations.Nullable; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -@LDLRegister(name = "rtui", group = "editor.gtceu") -public class RecipeTypeUIProject extends UIProject { - - @Nullable - @Getter - @Setter - protected GTRecipeType recipeType; - - private RecipeTypeUIProject() { - this(null, null); - } - - public RecipeTypeUIProject(Resources resources, WidgetGroup root) { - super(resources, root); - } - - public RecipeTypeUIProject(CompoundTag tag) { - super(tag); - } - - @Override - public RecipeTypeUIProject newEmptyProject() { - return new RecipeTypeUIProject(Resources.defaultResource(), new WidgetGroup(30, 30, 200, 200)); - } - - @Override - public UIProject loadProject(File file) { - try { - var tag = NbtIo.read(file); - if (tag != null) { - return new RecipeTypeUIProject(tag); - } - } catch (IOException ignored) {} - return null; - } - - @Override - public CompoundTag serializeNBT() { - var tag = super.serializeNBT(); - if (recipeType != null) { - tag.putString("recipe_type", recipeType.registryName.toString()); - } - return tag; - } - - @Override - public void deserializeNBT(CompoundTag tag) { - super.deserializeNBT(tag); - if (tag.contains("recipe_type")) { - recipeType = GTRegistries.RECIPE_TYPES.get(new ResourceLocation(tag.getString("recipe_type"))); - } - } - - @Override - public void onLoad(Editor editor) { - editor.getResourcePanel().loadResource(getResources(), false); - editor.getTabPages().addTab(new TabButton(50, 16, 60, 14).setTexture( - new GuiTextureGroup(ColorPattern.T_GREEN.rectTexture().setBottomRadius(10).transform(0, 0.4f), - new TextTexture("Main")), - new GuiTextureGroup(ColorPattern.T_RED.rectTexture().setBottomRadius(10).transform(0, 0.4f), - new TextTexture("Main"))), - new UIMainPanel(editor, root, recipeType == null ? null : recipeType.registryName.toLanguageKey())); - for (WidgetToolBox.Default tab : WidgetToolBox.Default.TABS) { - if (tab == WidgetToolBox.Default.CONTAINER) { - continue; - } - editor.getToolPanel().addNewToolBox("ldlib.gui.editor.group." + tab.groupName, tab.icon, - tab.createToolBox()); - } - } - - @Override - public void attachMenu(Editor editor, String name, TreeBuilder.Menu menu) { - if (name.equals("file")) { - if (recipeType == null) { - menu.remove("ldlib.gui.editor.menu.save"); - } else { - menu.remove("ldlib.gui.editor.menu.save"); - menu.leaf(Icons.SAVE, "ldlib.gui.editor.menu.save", () -> { - var path = new File(LDLib.getLDLibDir(), - "assets/%s/ui/recipe_type".formatted(recipeType.registryName.getNamespace())); - path.mkdirs(); - saveProject(new File(path, recipeType.registryName.getPath() + "." + this.getRegisterUI().name())); - recipeType.getRecipeUI().reloadCustomUI(); - }); - } - } else if (name.equals("template_tab")) { - Map> categories = new LinkedHashMap<>(); - for (GTRecipeType recipeType : GTRegistries.RECIPE_TYPES) { - categories.computeIfAbsent(recipeType.group, group -> new ArrayList<>()).add(recipeType); - } - categories.forEach((groupName, recipeTypes) -> menu.branch(groupName, m -> { - for (GTRecipeType recipeType : recipeTypes) { - IGuiTexture icon; - if (recipeType.getIconSupplier() != null) { - icon = new ItemStackTexture(recipeType.getIconSupplier().get()); - } else { - icon = new ItemStackTexture(Items.BARRIER); - } - m.leaf(icon, recipeType.registryName.toLanguageKey(), () -> { - root.clearAllWidgets(); - if (recipeType.getRecipeUI().hasCustomUI()) { - var nbt = recipeType.getRecipeUI().getCustomUI(); - IConfigurableWidget.deserializeNBT(root, nbt.getCompound("root"), - Resources.fromNBT(nbt.getCompound("resources")), false); - } else { - var widget = recipeType.getRecipeUI().createEditableUITemplate(false, false) - .createDefault(); - root.setSize(widget.getSize()); - for (Widget children : widget.widgets) { - root.addWidget(children); - } - } - setRecipeType(recipeType); - }); - } - })); - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/editor/TemplateTab.java b/src/main/java/com/gregtechceu/gtceu/api/gui/editor/TemplateTab.java deleted file mode 100644 index 717d9e662b6..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/editor/TemplateTab.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.editor; - -import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; -import com.lowdragmc.lowdraglib.gui.editor.ui.menu.MenuTab; -import com.lowdragmc.lowdraglib.gui.util.TreeBuilder; - -@LDLRegister(name = "template_tab", group = "editor.gtceu") -public class TemplateTab extends MenuTab { - - protected TreeBuilder.Menu createMenu() { - return TreeBuilder.Menu.start(); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/editor/UIMainPanel.java b/src/main/java/com/gregtechceu/gtceu/api/gui/editor/UIMainPanel.java deleted file mode 100644 index 430266b226a..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/editor/UIMainPanel.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.editor; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; - -import com.lowdragmc.lowdraglib.gui.editor.ui.Editor; -import com.lowdragmc.lowdraglib.gui.editor.ui.MainPanel; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.TextTexture; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public class UIMainPanel extends MainPanel { - - final String description; - - public UIMainPanel(Editor editor, WidgetGroup root, String description) { - super(editor, root); - this.setBackground(new IGuiTexture() { - - @Override - @OnlyIn(Dist.CLIENT) - public void draw(GuiGraphics graphics, int mouseX, int mouseY, float x, float y, int width, int height) { - if (description != null) { - new TextTexture(description).scale(2.0f).draw(graphics, mouseX, mouseY, x, y, - width - editor.getConfigPanel().getSize().getWidth(), height); - } - var border = 4; - var background = GuiTextures.BACKGROUND; - var position = root.getPosition(); - var size = root.getSize(); - var w = Math.max(size.width + border * 2, 172); - var h = Math.max(size.height + border * 2, 86); - background.draw(graphics, mouseX, mouseY, - position.x - (w - size.width) / 2f, - position.y - (h - size.height) / 2f, - w, h); - } - }); - this.description = description; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/factory/CoverUIFactory.java b/src/main/java/com/gregtechceu/gtceu/api/gui/factory/CoverUIFactory.java deleted file mode 100644 index 62bdd2601ad..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/factory/CoverUIFactory.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.factory; - -import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; -import com.gregtechceu.gtceu.api.cover.CoverBehavior; -import com.gregtechceu.gtceu.api.cover.IUICover; - -import com.lowdragmc.lowdraglib.gui.factory.UIFactory; -import com.lowdragmc.lowdraglib.gui.modular.ModularUI; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.Direction; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public class CoverUIFactory extends UIFactory { - - public static final CoverUIFactory INSTANCE = new CoverUIFactory(); - - public CoverUIFactory() { - super(GTCEu.id("cover")); - } - - @Override - protected ModularUI createUITemplate(CoverBehavior holder, Player entityPlayer) { - if (holder instanceof IUICover cover) { - return cover.createUI(entityPlayer); - } - return null; - } - - @OnlyIn(Dist.CLIENT) - @Override - protected CoverBehavior readHolderFromSyncData(FriendlyByteBuf syncData) { - Level world = Minecraft.getInstance().level; - if (world == null) return null; - var pos = syncData.readBlockPos(); - var side = syncData.readEnum(Direction.class); - var coverable = GTCapabilityHelper.getCoverable(world, pos, side); - if (coverable != null) { - return coverable.getCoverAtSide(side); - } - return null; - } - - @Override - protected void writeHolderToSyncData(FriendlyByteBuf syncData, CoverBehavior holder) { - syncData.writeBlockPos(holder.coverHolder.getBlockPos()); - syncData.writeEnum(holder.attachedSide); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/factory/GTUIEditorFactory.java b/src/main/java/com/gregtechceu/gtceu/api/gui/factory/GTUIEditorFactory.java deleted file mode 100644 index 814491d6e60..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/factory/GTUIEditorFactory.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.factory; - -import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.api.gui.editor.GTUIEditor; - -import com.lowdragmc.lowdraglib.LDLib; -import com.lowdragmc.lowdraglib.gui.factory.UIFactory; -import com.lowdragmc.lowdraglib.gui.modular.IUIHolder; -import com.lowdragmc.lowdraglib.gui.modular.ModularUI; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.player.Player; - -public class GTUIEditorFactory extends UIFactory implements IUIHolder { - - public static final GTUIEditorFactory INSTANCE = new GTUIEditorFactory(); - - private GTUIEditorFactory() { - super(LDLib.location("gt_ui_editor")); - } - - @Override - protected ModularUI createUITemplate(GTUIEditorFactory holder, Player entityPlayer) { - return createUI(entityPlayer); - } - - @Override - protected GTUIEditorFactory readHolderFromSyncData(FriendlyByteBuf syncData) { - return this; - } - - @Override - protected void writeHolderToSyncData(FriendlyByteBuf syncData, GTUIEditorFactory holder) {} - - @Override - public ModularUI createUI(Player entityPlayer) { - return new ModularUI(this, entityPlayer).widget(new GTUIEditor()); - } - - @Override - public boolean isInvalid() { - return false; - } - - @Override - public boolean isRemote() { - return GTCEu.isClientThread(); - } - - @Override - public void markAsDirty() {} -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/factory/MachineUIFactory.java b/src/main/java/com/gregtechceu/gtceu/api/gui/factory/MachineUIFactory.java deleted file mode 100644 index 220c3a9c4d0..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/factory/MachineUIFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.factory; - -import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.api.machine.MetaMachine; -import com.gregtechceu.gtceu.api.machine.feature.IUIMachine; - -import com.lowdragmc.lowdraglib.gui.factory.UIFactory; -import com.lowdragmc.lowdraglib.gui.modular.ModularUI; - -import net.minecraft.client.Minecraft; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public class MachineUIFactory extends UIFactory { - - public static final MachineUIFactory INSTANCE = new MachineUIFactory(); - - public MachineUIFactory() { - super(GTCEu.id("machine")); - } - - @Override - protected ModularUI createUITemplate(MetaMachine holder, Player entityPlayer) { - if (holder instanceof IUIMachine machine) { - return machine.createUI(entityPlayer); - } - return null; - } - - @OnlyIn(Dist.CLIENT) - @Override - protected MetaMachine readHolderFromSyncData(FriendlyByteBuf syncData) { - Level world = Minecraft.getInstance().level; - if (world == null) return null; - if (world.getBlockEntity(syncData.readBlockPos()) instanceof MetaMachine holder) { - return holder; - } - return null; - } - - @Override - protected void writeHolderToSyncData(FriendlyByteBuf syncData, MetaMachine holder) { - syncData.writeBlockPos(holder.getBlockPos()); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/ConfiguratorPanel.java b/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/ConfiguratorPanel.java deleted file mode 100644 index 6ab93be46bc..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/ConfiguratorPanel.java +++ /dev/null @@ -1,449 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.fancy; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.config.ConfigHolder; - -import com.lowdragmc.lowdraglib.gui.animation.Animation; -import com.lowdragmc.lowdraglib.gui.animation.Transform; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.TextTexture; -import com.lowdragmc.lowdraglib.gui.util.ClickData; -import com.lowdragmc.lowdraglib.gui.widget.ButtonWidget; -import com.lowdragmc.lowdraglib.gui.widget.ImageWidget; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.utils.Position; -import com.lowdragmc.lowdraglib.utils.Size; -import com.lowdragmc.lowdraglib.utils.interpolate.Eases; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import com.mojang.blaze3d.systems.RenderSystem; -import lombok.Getter; -import lombok.Setter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class ConfiguratorPanel extends WidgetGroup { - - @Getter - protected List tabs = new ArrayList<>(); - @Getter - @Nullable - protected Tab expanded; - @Setter - protected int border = 4; - @Setter - protected IGuiTexture texture = GuiTextures.BACKGROUND; - - public ConfiguratorPanel(int x, int y) { - super(x, y, 24, 0); - } - - public void clear() { - clearAllWidgets(); - tabs.clear(); - expanded = null; - } - - public int getTabSize() { - return getSize().width; - } - - public void attachConfigurators(IFancyConfigurator... fancyConfigurators) { - for (IFancyConfigurator fancyConfigurator : fancyConfigurators) { - var tab = new Tab(fancyConfigurator); - tab.setBackground(texture); - tabs.add(tab); - addWidgetAnima(tab, new Transform() - .scale(0) - .duration(getAnimationTime()) - .ease(Eases.EaseQuadOut)); - } - setSize(new Size(getSize().width, Math.max(0, tabs.size() * (getTabSize() + 2) - 2))); - } - - public void expandTab(Tab tab) { - tab.expand(); - int i = 0; - for (Tab otherTab : tabs) { - if (otherTab != tab) { - otherTab.collapseTo(0, i++ * (getTabSize() + 2)); - } - } - expanded = tab; - } - - public void collapseTab() { - if (expanded != null) { - for (int i = 0; i < tabs.size(); i++) { - tabs.get(i).collapseTo(0, i * (getTabSize() + 2)); - } - if (expanded instanceof FloatingTab) { - expanded.collapseTo(0, 0); - } - } - expanded = null; - } - - @Override - @OnlyIn(Dist.CLIENT) - protected void drawWidgetsBackground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - for (Widget widget : widgets) { - if (widget.isVisible() && widget != expanded) { - RenderSystem.setShaderColor(1, 1, 1, 1); - RenderSystem.enableBlend(); - if (widget.inAnimate()) { - widget.getAnimation().drawInBackground(graphics, mouseX, mouseY, partialTicks); - } else { - widget.drawInBackground(graphics, mouseX, mouseY, partialTicks); - } - } - } - if (expanded != null && expanded.isVisible()) { - graphics.pose().pushPose(); - graphics.pose().translate(0, 0, 300); - RenderSystem.setShaderColor(1, 1, 1, 1); - RenderSystem.enableBlend(); - if (expanded.inAnimate()) { - expanded.getAnimation().drawInBackground(graphics, mouseX, mouseY, partialTicks); - } else { - expanded.drawInBackground(graphics, mouseX, mouseY, partialTicks); - } - graphics.pose().popPose(); - } - } - - @Override - @OnlyIn(Dist.CLIENT) - - protected void drawWidgetsForeground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - // remove previous tooltip - if (isMouseOverElement(mouseX, mouseY)) { - gui.getModularUIGui().setHoverTooltip(Collections.emptyList(), ItemStack.EMPTY, null, null); - } - for (Widget widget : widgets) { - if (widget.isVisible() && widget != expanded) { - RenderSystem.setShaderColor(1, 1, 1, 1); - RenderSystem.enableBlend(); - if (widget.inAnimate()) { - widget.getAnimation().drawInForeground(graphics, mouseX, mouseY, partialTicks); - } else { - widget.drawInForeground(graphics, mouseX, mouseY, partialTicks); - } - } - } - if (expanded != null && expanded.isVisible()) { - RenderSystem.setShaderColor(1, 1, 1, 1); - RenderSystem.enableBlend(); - if (expanded.inAnimate()) { - expanded.getAnimation().drawInForeground(graphics, mouseX, mouseY, partialTicks); - } else { - expanded.drawInForeground(graphics, mouseX, mouseY, partialTicks); - } - } - } - - @Override - @OnlyIn(Dist.CLIENT) - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (expanded != null && expanded.isVisible() && expanded.isActive() && - expanded.mouseClicked(mouseX, mouseY, button)) { - return true; - } - return super.mouseClicked(mouseX, mouseY, button); - } - - public FloatingTab createFloatingTab(IFancyConfigurator configurator) { - return new FloatingTab(configurator); - } - - public class Tab extends WidgetGroup { - - protected final IFancyConfigurator configurator; - protected final ButtonWidget button; - @Nullable - protected final WidgetGroup view; - // dragging - protected double lastDeltaX, lastDeltaY; - protected int dragOffsetX, dragOffsetY; - protected boolean isDragging; - - public Tab(IFancyConfigurator configurator) { - super(0, tabs.size() * (getTabSize() + 2), getTabSize(), getTabSize()); - this.configurator = configurator; - this.button = new ButtonWidget(0, 0, getTabSize(), getTabSize(), null, this::onClick) { - - @Override - public boolean mouseWheelMove(double mouseX, double mouseY, double wheelDelta) { - if (!(configurator instanceof IFancyCustomMouseWheelAction hasActions)) return false; - if (isMouseOverElement(mouseX, mouseY)) - return hasActions.mouseWheelMove(this::writeClientAction, mouseX, mouseY, wheelDelta); - return false; - } - - @Override - public void handleClientAction(int id, FriendlyByteBuf buffer) { - if (configurator instanceof IFancyCustomClientActionHandler handler && id > 1) - handler.handleClientAction(id, buffer); - else - super.handleClientAction(id, buffer); - } - }; - if (configurator instanceof IFancyConfiguratorButton) { - this.view = null; - this.addWidget(button); - } else { - var widget = configurator.createConfigurator(); - widget.setSelfPosition(new Position(border, getTabSize())); - - this.view = new WidgetGroup(0, 0, 0, 0) { - - @Override - protected void onChildSizeUpdate(Widget child) { - super.onChildSizeUpdate(child); - if (widget == child) { - this.setSize(new Size(widget.getSize().width + border * 2, - widget.getSize().height + getTabSize() + border)); - } - } - }; - - this.view.setVisible(false); - this.view.setActive(false); - this.view.setSize(new Size(widget.getSize().width + border * 2, - widget.getSize().height + button.getSize().height + border)); - this.view.addWidget(widget); - this.view.addWidget(new ImageWidget(border + 5, border, widget.getSize().width - getTabSize() - 5, - getTabSize() - border, - new TextTexture(configurator.getTitle().getString()) - .setType(TextTexture.TextType.LEFT_HIDE) - .setWidth(widget.getSize().width - getTabSize()))); - this.addWidget(button); - this.addWidget(view); - } - } - - @Override - public void writeInitialData(FriendlyByteBuf buffer) { - super.writeInitialData(buffer); - configurator.writeInitialData(buffer); - } - - @Override - public void readInitialData(FriendlyByteBuf buffer) { - super.readInitialData(buffer); - configurator.readInitialData(buffer); - } - - @Override - public void detectAndSendChanges() { - super.detectAndSendChanges(); - configurator.detectAndSendChange((id, sender) -> writeUpdateInfo(0, buf -> { - buf.writeVarInt(id); - sender.accept(buf); - })); - } - - @Override - public void readUpdateInfo(int id, FriendlyByteBuf buffer) { - if (id == 0) { - configurator.readUpdateInfo(buffer.readVarInt(), buffer); - } else { - super.readUpdateInfo(id, buffer); - } - } - - @Override - protected void onChildSizeUpdate(Widget child) { - if (this.view != null && this.view == child) { - if (expanded == this) { - var size = view.getSize(); - animation(new Animation() - .duration(getAnimationTime()) - .position(new Position(dragOffsetX + (-size.width + (tabs.size() > 1 ? -2 : getTabSize())), - dragOffsetY)) - .size(size) - .ease(Eases.EaseQuadOut) - .onFinish(() -> { - view.setVisible(true); - view.setActive(true); - })); - } - } - } - - private void onClick(ClickData clickData) { - if (clickData.button == 2 && configurator instanceof IFancyCustomMiddleClickAction middleAction) { - middleAction.onMiddleClick(this::writeClientAction); - } else if (configurator instanceof IFancyConfiguratorButton fancyButton) { - fancyButton.onClick(clickData); - } else { - if (expanded == this) { - collapseTab(); - } else { - expandTab(this); - } - } - } - - @Override - public void setSize(Size size) { - super.setSize(size); - button.setSelfPosition(new Position(size.width - getTabSize(), 0)); - } - - private void expand() { - if (view == null) return; - var size = view.getSize(); - this.dragOffsetX = 0; - this.dragOffsetY = 0; - if (isRemote()) { - if (getParentPosition().x - size.width + (tabs.size() > 1 ? -2 : getTabSize()) < 0) { - this.dragOffsetX -= (view.getParentPosition().x - size.width + - (tabs.size() > 1 ? -2 : getTabSize())); - } - if (getParentPosition().y + size.height > gui.getScreenHeight()) { - this.dragOffsetY -= view.getParentPosition().y + size.height - gui.getScreenHeight(); - } - } - Position position = new Position(dragOffsetX - size.width + (tabs.size() > 1 ? -2 : getTabSize()), - dragOffsetY); - - animation(new Animation() - .duration(getAnimationTime()) - .position(position) - .size(size) - .ease(Eases.EaseQuadOut) - .onFinish(() -> { - view.setVisible(true); - view.setActive(true); - })); - } - - protected void collapseTo(int x, int y) { - if (view != null) { - view.setVisible(false); - view.setActive(false); - } - animation(new Animation() - .duration(getAnimationTime()) - .position(new Position(x, y)) - .size(new Size(getTabSize(), getTabSize())) - .ease(Eases.EaseQuadOut)); - } - - @Override - @OnlyIn(Dist.CLIENT) - public void drawInBackground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - drawBackgroundTexture(graphics, mouseX, mouseY); - var position = getPosition(); - var size = getSize(); - if (inAnimate()) { - graphics.enableScissor(position.x + border - 1, position.y + border - 1, - position.x + border - 1 + size.width - (border - 1) * 2, - position.y + border - 1 + size.height - (border - 1) * 2); - drawWidgetsBackground(graphics, mouseX, mouseY, partialTicks); - graphics.disableScissor(); - } else { - drawWidgetsBackground(graphics, mouseX, mouseY, partialTicks); - } - configurator.getIcon().draw(graphics, mouseX, mouseY, position.x + size.width - 20, position.y + 4, 16, 16); - } - - @Override - @OnlyIn(Dist.CLIENT) - public void drawInForeground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - super.drawInForeground(graphics, mouseX, mouseY, partialTicks); - if (isMouseOver(getPosition().x + getSize().width - 20, getPosition().y + 4, 16, 16, mouseX, mouseY) && - gui != null && gui.getModularUIGui() != null) { - gui.getModularUIGui().setHoverTooltip(configurator.getTooltips(), ItemStack.EMPTY, null, null); - } - } - - @Override - @OnlyIn(Dist.CLIENT) - public boolean mouseClicked(double mouseX, double mouseY, int button) { - this.lastDeltaX = 0; - this.lastDeltaY = 0; - this.isDragging = false; - if (expanded == this && isMouseOver(getPosition().x, getPosition().y, getSize().width - getTabSize(), - getTabSize(), mouseX, mouseY)) { - isDragging = true; - return true; - } - return super.mouseClicked(mouseX, mouseY, button) || isMouseOverElement(mouseX, mouseY); - } - - @Override - @OnlyIn(Dist.CLIENT) - public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) { - double dx = dragX + lastDeltaX; - double dy = dragY + lastDeltaY; - dragX = (int) dx; - dragY = (int) dy; - lastDeltaX = dx - dragX; - lastDeltaY = dy - dragY; - if (isDragging) { - this.dragOffsetX += (int) dragX; - this.dragOffsetY += (int) dragY; - this.addSelfPosition((int) dragX, (int) dragY); - } - return super.mouseDragged(mouseX, mouseY, button, dragX, dragY) || isMouseOverElement(mouseX, mouseY); - } - - @Override - @OnlyIn(Dist.CLIENT) - public boolean mouseReleased(double mouseX, double mouseY, int button) { - this.lastDeltaX = 0; - this.lastDeltaY = 0; - this.isDragging = false; - return super.mouseReleased(mouseX, mouseY, button) || isMouseOverElement(mouseX, mouseY); - } - - @Override - @OnlyIn(Dist.CLIENT) - public boolean mouseWheelMove(double mouseX, double mouseY, double wheelDelta) { - return super.mouseWheelMove(mouseX, mouseY, wheelDelta) || isMouseOverElement(mouseX, mouseY); - } - - @Override - @OnlyIn(Dist.CLIENT) - public boolean mouseMoved(double mouseX, double mouseY) { - return super.mouseMoved(mouseX, mouseY) || isMouseOverElement(mouseX, mouseY); - } - } - - public class FloatingTab extends Tab { - - protected Runnable closeCallback = () -> {}; - - public FloatingTab(IFancyConfigurator configurator) { - super(configurator); - this.view.setBackground(GuiTextures.BACKGROUND); - } - - @Override - public void collapseTo(int x, int y) { - super.collapseTo(x, y); - ConfiguratorPanel.this.removeWidget(this); - closeCallback.run(); - } - - public void onClose(Runnable closeCallback) { - this.closeCallback = closeCallback; - } - } - - private static int getAnimationTime() { - return ConfigHolder.INSTANCE.client.animationTime; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/FancyMachineUIWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/FancyMachineUIWidget.java deleted file mode 100644 index 5e62d3bf958..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/FancyMachineUIWidget.java +++ /dev/null @@ -1,242 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.fancy; - -import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.config.ConfigHolder; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.util.ClickData; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.gui.widget.custom.PlayerInventoryWidget; -import com.lowdragmc.lowdraglib.utils.Position; -import com.lowdragmc.lowdraglib.utils.Size; - -import lombok.Getter; -import lombok.Setter; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.List; -import java.util.stream.Stream; - -@Getter -public class FancyMachineUIWidget extends WidgetGroup { - - protected final TitleBarWidget titleBar; - protected final VerticalTabsWidget sideTabsWidget; - protected final WidgetGroup pageContainer; - protected final PageSwitcher pageSwitcher; - protected final ConfiguratorPanel configuratorPanel; - protected final TooltipsPanel tooltipsPanel; - - @Nullable - protected final PlayerInventoryWidget playerInventory; - @Setter - protected int border = 4; - - protected final IFancyUIProvider mainPage; - - /* - * Current Page: The page visible in the UI - * Current Home Page: The currently selected multiblock part's home page. - */ - protected IFancyUIProvider currentPage; - protected IFancyUIProvider currentHomePage; - - protected List allPages; - - protected Deque previousPages = new ArrayDeque<>(); - - protected record NavigationEntry(IFancyUIProvider page, IFancyUIProvider homePage, Runnable onNavigation) {} - - public FancyMachineUIWidget(IFancyUIProvider mainPage, int width, int height) { - super(0, 0, width, height); - this.mainPage = mainPage; - - addWidget(this.pageContainer = new WidgetGroup(0, 0, width, height)); - - if (mainPage.hasPlayerInventory()) { - addWidget(this.playerInventory = new PlayerInventoryWidget()); - this.playerInventory.setSelfPosition(new Position(2, height - 86)); - this.playerInventory.setBackground((IGuiTexture) null); - } else { - playerInventory = null; - } - - addWidget(this.titleBar = new TitleBarWidget(width, this::navigateBack, this::openPageSwitcher)); - addWidget(this.sideTabsWidget = new VerticalTabsWidget(this::navigate, -20, 0, 24, height)); - addWidget(this.tooltipsPanel = new TooltipsPanel()); - addWidget(this.configuratorPanel = new ConfiguratorPanel(-(24 + 2), height)); - this.pageSwitcher = new PageSwitcher(this::switchPage); - - setBackground(GuiTextures.BACKGROUND.copy() - .setColor(Long.decode(ConfigHolder.INSTANCE.client.defaultUIColor).intValue() | 0xFF000000)); - } - - @Override - public void initWidget() { - super.initWidget(); - - if (this.playerInventory != null) { - this.playerInventory.setPlayer(gui.entityPlayer); - } - - this.allPages = Stream.concat(Stream.of(this.mainPage), this.mainPage.getSubTabs().stream()).toList(); - - performNavigation(this.mainPage, this.mainPage); - } - - //////////////////////////////////////// - // ********* NAVIGATION *********// - //////////////////////////////////////// - - protected void navigate(IFancyUIProvider newPage) { - navigate(newPage, this.currentHomePage); - } - - protected void navigate(IFancyUIProvider nextPage, IFancyUIProvider nextHomePage) { - if (nextPage != mainPage) { - if (!this.previousPages.isEmpty() && this.previousPages.peek().page == nextPage) { - // In case the user manually navigates back one step, just remove it from the navigation stack - this.previousPages.pop(); - } else if (this.currentPage != null) { - this.previousPages.push(new NavigationEntry(this.currentPage, this.currentHomePage, () -> {})); - } - } else { - this.previousPages.clear(); - } - - performNavigation(nextPage, nextHomePage); - } - - protected void navigateBack(ClickData clickData) { - NavigationEntry navigationEntry = previousPages.pop(); - - performNavigation(navigationEntry.page, navigationEntry.homePage); - navigationEntry.onNavigation.run(); - } - - protected void performNavigation(IFancyUIProvider nextPage, IFancyUIProvider nextHomePage) { - if (currentHomePage != nextHomePage) - setupSideTabs(nextHomePage); - - this.currentPage = nextPage; - this.currentHomePage = nextHomePage; - - if (currentPage != currentHomePage) { - // Ensure the home page's basic layout is applied before navigating to another page: - setupFancyUI(currentHomePage); - } - - setupFancyUI(nextPage, nextPage.hasPlayerInventory()); - } - - /////////////////////////////////////////////// - // *********** PAGE SWITCHER ***********// - /////////////////////////////////////////////// - - protected void openPageSwitcher(ClickData clickData) { - pageSwitcher.setPageList(allPages, currentHomePage); - - // If we're in another tab of the current page, ensure nav to its main tab when closing the page switcher: - if (currentPage != currentHomePage && !previousPages.isEmpty()) { - previousPages.pop(); - } - - this.sideTabsWidget.setVisible(false); - this.sideTabsWidget.setActive(false); - - this.previousPages.push(new NavigationEntry(currentHomePage, currentHomePage, () -> { - sideTabsWidget.setVisible(true); - sideTabsWidget.setActive(true); - })); - - this.currentPage = this.pageSwitcher; - this.currentHomePage = this.pageSwitcher; - - setupFancyUI(this.pageSwitcher); - } - - protected void switchPage(IFancyUIProvider nextHomePage) { - // Ensure that the back button always leads back to the main page: - this.currentHomePage = mainPage; - this.currentPage = mainPage; - this.previousPages.clear(); - - sideTabsWidget.setVisible(true); - sideTabsWidget.setActive(true); - - setupSideTabs(this.currentHomePage); - navigate(nextHomePage, nextHomePage); - } - - ////////////////////////////////////////////// - // *********** UI RENDERING ***********// - ////////////////////////////////////////////// - - protected void setupFancyUI(IFancyUIProvider fancyUI) { - this.setupFancyUI(fancyUI, fancyUI.hasPlayerInventory()); - } - - protected void setupFancyUI(IFancyUIProvider fancyUI, boolean showInventory) { - clearUI(); - - sideTabsWidget.selectTab(fancyUI); - titleBar.updateState( - fancyUI, - !this.previousPages.isEmpty(), - this.allPages.size() > 1 && this.currentPage != this.pageSwitcher); - - var page = fancyUI.createMainPage(this); - - // layout - var size = new Size(Math.max(172, page.getSize().width + border * 2), - Math.max(86, page.getSize().height + border * 2)); - setSize(new Size(size.width, - size.height + (!showInventory || playerInventory == null ? 0 : playerInventory.getSize().height))); - if (GTCEu.isClientSide() && getGui() != null) { - getGui().setSize(getSize().width, getSize().height); - } - this.sideTabsWidget.setSize(new Size(24, size.height)); - this.pageContainer.setSize(size); - this.tooltipsPanel.setSelfPosition(new Position(size.width + 2, 2)); - - setupInventoryPosition(showInventory, size); - - // setup - this.pageContainer.addWidget(page); - page.setSelfPosition(new Position( - (pageContainer.getSize().width - page.getSize().width) / 2, - (pageContainer.getSize().height - page.getSize().height) / 2)); - fancyUI.attachConfigurators(configuratorPanel); - configuratorPanel - .setSelfPosition(new Position(-24 - 2, getGui().getHeight() - configuratorPanel.getSize().height - 4)); - fancyUI.attachTooltips(tooltipsPanel); - - titleBar.setSize(new Size(this.getSize().width, titleBar.getSize().height)); - } - - private void setupInventoryPosition(boolean showInventory, Size parentSize) { - if (this.playerInventory == null) - return; - - this.playerInventory.setSelfPosition(new Position( - (parentSize.width - playerInventory.getSize().width) / 2, - parentSize.height)); - - this.playerInventory.setActive(showInventory); - this.playerInventory.setVisible(showInventory); - } - - protected void clearUI() { - this.pageContainer.clearAllWidgets(); - this.configuratorPanel.clear(); - this.tooltipsPanel.clear(); - } - - protected void setupSideTabs(IFancyUIProvider currentHomePage) { - this.sideTabsWidget.clearSubTabs(); - currentHomePage.attachSideTabs(sideTabsWidget); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyConfigurator.java b/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyConfigurator.java deleted file mode 100644 index c60ff187844..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyConfigurator.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.fancy; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.widget.Widget; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; - -import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -public interface IFancyConfigurator { - - Component getTitle(); - - IGuiTexture getIcon(); - - Widget createConfigurator(); - - default List getTooltips() { - return List.of(getTitle()); - } - - default void detectAndSendChange(BiConsumer> sender) {} - - default void readUpdateInfo(int id, FriendlyByteBuf buf) {} - - default void writeInitialData(FriendlyByteBuf buffer) {} - - default void readInitialData(FriendlyByteBuf buffer) {} -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyConfiguratorButton.java b/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyConfiguratorButton.java deleted file mode 100644 index 0708b49eccc..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyConfiguratorButton.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.fancy; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.util.ClickData; -import com.lowdragmc.lowdraglib.gui.widget.Widget; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; - -import lombok.Setter; -import lombok.experimental.Accessors; -import org.apache.commons.lang3.NotImplementedException; - -import java.util.Collections; -import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.BooleanSupplier; -import java.util.function.Consumer; -import java.util.function.Function; - -public interface IFancyConfiguratorButton extends IFancyConfigurator { - - void onClick(ClickData clickData); - - @Override - default Component getTitle() { - throw new NotImplementedException(); - } - - @Override - default Widget createConfigurator() { - throw new NotImplementedException(); - } - - @Accessors(chain = true) - class Toggle implements IFancyConfiguratorButton { - - IGuiTexture base; - IGuiTexture pressed; - BiConsumer onClick; - BooleanSupplier booleanSupplier; - boolean isPressed; - @Setter - Function> tooltipsSupplier = isPressed -> Collections.emptyList(); - - public Toggle(IGuiTexture base, IGuiTexture pressed, BooleanSupplier booleanSupplier, - BiConsumer onClick) { - this.base = base; - this.pressed = pressed; - this.booleanSupplier = booleanSupplier; - this.onClick = onClick; - } - - @Override - public List getTooltips() { - return tooltipsSupplier.apply(isPressed); - } - - @Override - public void detectAndSendChange(BiConsumer> sender) { - var newIsPressed = booleanSupplier.getAsBoolean(); - if (newIsPressed != isPressed) { - isPressed = newIsPressed; - sender.accept(0, buf -> buf.writeBoolean(isPressed)); - } - } - - @Override - public void readUpdateInfo(int id, FriendlyByteBuf buf) { - if (id == 0) { - isPressed = buf.readBoolean(); - } - } - - @Override - public void writeInitialData(FriendlyByteBuf buffer) { - this.isPressed = booleanSupplier.getAsBoolean(); - buffer.writeBoolean(this.isPressed); - } - - @Override - public void readInitialData(FriendlyByteBuf buffer) { - this.isPressed = buffer.readBoolean(); - } - - @Override - public IGuiTexture getIcon() { - return isPressed ? pressed : base; - } - - @Override - public void onClick(ClickData clickData) { - onClick.accept(clickData, !isPressed); - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyCustomClientActionHandler.java b/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyCustomClientActionHandler.java deleted file mode 100644 index f9b354cf1f9..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyCustomClientActionHandler.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.fancy; - -import net.minecraft.network.FriendlyByteBuf; - -public interface IFancyCustomClientActionHandler { - - default void handleClientAction(int id, FriendlyByteBuf buffer) {} -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyCustomMiddleClickAction.java b/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyCustomMiddleClickAction.java deleted file mode 100644 index 489f6e091f8..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyCustomMiddleClickAction.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.fancy; - -import net.minecraft.network.FriendlyByteBuf; - -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -public interface IFancyCustomMiddleClickAction extends IFancyCustomClientActionHandler { - - default void onMiddleClick(BiConsumer> writeClientAction) {} -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyCustomMouseWheelAction.java b/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyCustomMouseWheelAction.java deleted file mode 100644 index fb5213912a9..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyCustomMouseWheelAction.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.fancy; - -import net.minecraft.network.FriendlyByteBuf; - -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -public interface IFancyCustomMouseWheelAction extends IFancyCustomClientActionHandler { - - default boolean mouseWheelMove(BiConsumer> writeClientAction, double mouseX, - double mouseY, double wheelDelta) { - return false; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyTooltip.java b/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyTooltip.java deleted file mode 100644 index a0af005a9cf..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyTooltip.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.fancy; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; - -import net.minecraft.network.chat.Component; -import net.minecraft.world.inventory.tooltip.TooltipComponent; - -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.function.BooleanSupplier; -import java.util.function.Supplier; - -public interface IFancyTooltip { - - IGuiTexture getFancyTooltipIcon(); - - List getFancyTooltip(); - - default boolean showFancyTooltip() { - return true; - } - - @Nullable - default TooltipComponent getFancyComponent() { - return null; - } - - record Basic(Supplier icon, Supplier> content, BooleanSupplier predicate, - Supplier componentSupplier) - implements IFancyTooltip { - - @Override - public IGuiTexture getFancyTooltipIcon() { - return icon.get(); - } - - @Override - public List getFancyTooltip() { - return content.get(); - } - - @Override - public @Nullable TooltipComponent getFancyComponent() { - return componentSupplier.get(); - } - - @Override - public boolean showFancyTooltip() { - return predicate.getAsBoolean(); - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyUIProvider.java b/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyUIProvider.java deleted file mode 100644 index b5d878fcdc5..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/IFancyUIProvider.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.fancy; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.widget.Widget; - -import net.minecraft.network.chat.Component; -import net.minecraft.world.inventory.tooltip.TooltipComponent; - -import org.jetbrains.annotations.Nullable; - -import java.util.Collections; -import java.util.List; - -public interface IFancyUIProvider { - - /** - * Create the main page ui. - */ - Widget createMainPage(FancyMachineUIWidget widget); - - /** - * Get the tab icon of this page. - */ - IGuiTexture getTabIcon(); - - /** - * Get the title of this page. - */ - Component getTitle(); - - /** - * Attach configurators to the left subtab list. - */ - default void attachSideTabs(TabsWidget configuratorPanel) {} - - /** - * Attach configurators to the left panel. - */ - default void attachConfigurators(ConfiguratorPanel configuratorPanel) {} - - /** - * Attach tooltips to the right panel - */ - default void attachTooltips(TooltipsPanel tooltipsPanel) {} - - default boolean hasPlayerInventory() { - return true; - } - - /** - * Get sub tabs, for example, multiblock will show all its parts tabs. - */ - default List getSubTabs() { - return Collections.emptyList(); - } - - /** - * Get tab's Tooltips - */ - default List getTabTooltips() { - return Collections.emptyList(); - } - - /** - * Get tab's Tooltips Component - */ - @Nullable - default TooltipComponent getTabTooltipComponent() { - return null; - } - - @Nullable - default PageGroupingData getPageGroupingData() { - return null; - } - - record PageGroupingData(@Nullable String groupKey, int groupPositionWeight) {} -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/PageSwitcher.java b/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/PageSwitcher.java deleted file mode 100644 index 20c76d3945d..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/PageSwitcher.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.fancy; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.TextTexture; -import com.lowdragmc.lowdraglib.gui.widget.*; - -import net.minecraft.ChatFormatting; -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.network.chat.Component; - -import org.apache.commons.lang3.mutable.MutableInt; - -import java.util.Comparator; -import java.util.List; -import java.util.Objects; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import javax.annotation.ParametersAreNonnullByDefault; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class PageSwitcher implements IFancyUIProvider { - - private final Consumer onPageSwitched; - - private List pages = List.of(); - private IFancyUIProvider currentPage = null; - - public PageSwitcher(Consumer onPageSwitched) { - this.onPageSwitched = onPageSwitched; - } - - public void setPageList(List allPages, IFancyUIProvider currentPage) { - this.pages = allPages; - this.currentPage = currentPage; - } - - @Override - public Widget createMainPage(FancyMachineUIWidget widget) { - var container = new WidgetGroup(0, 0, 176, 166); - - var scrollableGroup = new DraggableScrollableWidgetGroup(10, 10, 156, 146); - scrollableGroup.setYScrollBarWidth(8); - scrollableGroup.setYBarStyle(GuiTextures.SLIDER_BACKGROUND_VERTICAL, GuiTextures.BUTTON); - container.addWidget(scrollableGroup); - - var groupedPages = pages.stream().collect(Collectors.groupingBy( - page -> Objects.requireNonNullElse(page.getPageGroupingData(), new PageGroupingData(null, -1)))); - - final MutableInt currentY = new MutableInt(0); - groupedPages.keySet().stream() - .sorted(Comparator.comparingInt(PageGroupingData::groupPositionWeight)) - .forEachOrdered(group -> { - if (group.groupKey() != null) { - scrollableGroup.addWidget( - new LabelWidget(0, currentY.getAndAdd(12), group.groupKey()).setDropShadow(false)); - } - - final var currentPage = new MutableInt(0); - currentY.subtract(30); // To account for adding it back on the first page inside this group - - groupedPages.get(group).forEach(page -> { - var index = currentPage.getAndIncrement(); - var y = currentY.addAndGet(index % 5 == 0 ? 30 : 0); // Jump to the next row every 5 parts - - var pageWidget = new WidgetGroup((index % 5) * 30, y, 25, 25); - pageWidget.addWidget(new ButtonWidget(0, 0, 25, 25, GuiTextures.BACKGROUND, - clickData -> onPageSwitched.accept(page))); - pageWidget.addWidget(new ImageWidget(4, 4, 17, 17, page.getTabIcon())); - // For some reason, this doesn't work in any other way: - pageWidget.widgets.get(0).setHoverTooltips(page.getTitle().getString()); - scrollableGroup.addWidget(pageWidget); - }); - - if (!groupedPages.get(group).isEmpty()) { - currentY.add(30); - } - }); - - return container; - } - - @Override - public IGuiTexture getTabIcon() { - return new TextTexture("+").setDropShadow(false).setColor(ChatFormatting.BLACK.getColor()); - } - - @Override - public Component getTitle() { - return Component.translatable("gtceu.gui.title_bar.page_switcher"); - } - - @Override - public boolean hasPlayerInventory() { - return false; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/TabsWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/TabsWidget.java deleted file mode 100644 index e30d94a8280..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/TabsWidget.java +++ /dev/null @@ -1,261 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.fancy; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; - -import com.lowdragmc.lowdraglib.gui.editor.Icons; -import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; -import com.lowdragmc.lowdraglib.gui.widget.Widget; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.util.Mth; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import lombok.Getter; -import lombok.Setter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -@Getter -public class TabsWidget extends Widget { - - protected final Consumer onTabClick; - protected IFancyUIProvider mainTab; - protected List subTabs; - @Nullable - protected IFancyUIProvider selectedTab; - @Setter - protected IGuiTexture leftButtonTexture = new GuiTextureGroup(GuiTextures.BUTTON, Icons.LEFT.copy().scale(0.7f)), - leftButtonHoverTexture = new GuiTextureGroup(GuiTextures.BUTTON, - Icons.LEFT.copy().setColor(0xffaaaaaa).scale(0.7f)); - @Setter - protected IGuiTexture rightButtonTexture = new GuiTextureGroup(GuiTextures.BUTTON, Icons.RIGHT.copy().scale(0.7f)), - rightButtonHoverTexture = new GuiTextureGroup(GuiTextures.BUTTON, - Icons.RIGHT.copy().setColor(0xffaaaaaa).scale(0.7f)); - @Setter - protected IGuiTexture tabTexture = new ResourceTexture("gtceu:textures/gui/tab/tabs_top.png").getSubTexture(1 / 3f, - 0, 1 / 3f, 0.5f); - @Setter - protected IGuiTexture tabHoverTexture = new ResourceTexture("gtceu:textures/gui/tab/tabs_top.png") - .getSubTexture(1 / 3f, 0.5f, 1 / 3f, 0.5f); - @Setter - protected IGuiTexture tabPressedTexture = tabHoverTexture; - @Getter - protected int offset; - /** - * (old tab, new tab) - */ - @Setter - @Nullable - protected BiConsumer onTabSwitch; - - public TabsWidget(Consumer onTabClick) { - this(onTabClick, 0, -20, 200, 24); - } - - public TabsWidget(Consumer onTabClick, int x, int y, int width, int height) { - super(x, y, width, height); - this.subTabs = new ArrayList<>(); - this.onTabClick = onTabClick; - } - - public void setMainTab(IFancyUIProvider mainTab) { - this.mainTab = mainTab; - if (this.selectedTab == null) { - this.selectedTab = this.mainTab; - } - } - - public void clearSubTabs() { - subTabs.clear(); - } - - public void attachSubTab(IFancyUIProvider subTab) { - subTabs.add(subTab); - } - - public boolean hasButton() { - return (subTabs.size() + 1) * 24 + 16 > getSize().width; - } - - @Override - public void handleClientAction(int id, FriendlyByteBuf buffer) { - super.handleClientAction(id, buffer); - if (id == 0) { - var index = buffer.readVarInt(); - var old = selectedTab; - if (index < 0) { - selectedTab = mainTab; - } else if (index < subTabs.size()) { - selectedTab = subTabs.get(index); - } else { - return; - } - if (onTabSwitch != null) { - onTabSwitch.accept(old, selectedTab); - } - onTabClick.accept(selectedTab); - } - } - - public int getSubTabsWidth() { - return getSize().width - 8 - 24 - 4 - 16 - 8 - 16; - } - - @Override - @OnlyIn(Dist.CLIENT) - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (isMouseOverElement(mouseX, mouseY)) { - var hoveredTab = getHoveredTab(mouseX, mouseY); - // click tab - if (hoveredTab != null && hoveredTab != selectedTab) { - if (onTabSwitch != null) { - onTabSwitch.accept(selectedTab, hoveredTab); - } - selectedTab = hoveredTab; - writeClientAction(0, - buf -> buf.writeVarInt(selectedTab == mainTab ? -1 : subTabs.indexOf(selectedTab))); - onTabClick.accept(selectedTab); - playButtonClickSound(); - } - // click button - if (hasButton()) { - if (isHoverLeftButton(mouseX, mouseY)) { - offset = Mth.clamp(offset - 24, 0, subTabs.size() * 24 - getSubTabsWidth()); - playButtonClickSound(); - } else if (isHoverRightButton(mouseX, mouseY)) { - offset = Mth.clamp(offset + 24, 0, subTabs.size() * 24 - getSubTabsWidth()); - playButtonClickSound(); - } - } - } - return super.mouseClicked(mouseX, mouseY, button); - } - - @Override - @OnlyIn(Dist.CLIENT) - public boolean mouseWheelMove(double mouseX, double mouseY, double wheelDelta) { - var sx = getPosition().x + 8 + 24 + 4 + 16; - if (isMouseOver(sx, getPosition().y, getSubTabsWidth(), 24, mouseX, mouseY)) { - offset = Mth.clamp(offset + 5 * (wheelDelta > 0 ? -1 : 1), 0, subTabs.size() * 24 - getSubTabsWidth()); - } - return super.mouseWheelMove(mouseX, mouseY, wheelDelta); - } - - @Override - @OnlyIn(Dist.CLIENT) - public void drawInBackground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - super.drawInBackground(graphics, mouseX, mouseY, partialTicks); - var position = getPosition(); - var size = getSize(); - var hoveredTab = getHoveredTab(mouseX, mouseY); - // main tab - drawTab(mainTab, graphics, mouseX, mouseY, position.x + 8, position.y, 24, 24, hoveredTab); - // render sub tabs - if (hasButton()) { // need a scrollable bar - // render buttons - if (isHoverLeftButton(mouseX, mouseY)) { - leftButtonHoverTexture.draw(graphics, mouseX, mouseY, position.x + 8 + 24 + 4, position.y, 16, 24); - } else { - leftButtonTexture.draw(graphics, mouseX, mouseY, position.x + 8 + 24 + 4, position.y, 16, 24); - } - if (isHoverRightButton(mouseX, mouseY)) { - rightButtonHoverTexture.draw(graphics, mouseX, mouseY, position.x + size.width - 8 - 16, position.y, 16, - 24); - } else { - rightButtonTexture.draw(graphics, mouseX, mouseY, position.x + size.width - 8 - 16, position.y, 16, 24); - } - // render sub tabs - var sx = position.x + 8 + 24 + 4 + 16; - graphics.enableScissor(sx, position.y - 1, sx + getSubTabsWidth(), position.y - 1 + 24 + 2); - for (int i = 0; i < subTabs.size(); i++) { - drawTab(subTabs.get(i), graphics, mouseX, mouseY, sx + i * 24 - offset, position.y, 24, 24, hoveredTab); - } - graphics.disableScissor(); - } else { - for (int i = subTabs.size() - 1; i >= 0; i--) { - drawTab(subTabs.get(i), graphics, mouseX, mouseY, - position.x + size.width - 8 - 24 * (subTabs.size() - i), position.y, 24, 24, hoveredTab); - } - } - } - - @Override - @OnlyIn(Dist.CLIENT) - public void drawInForeground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - var hoveredTab = getHoveredTab(mouseX, mouseY); - if (hoveredTab != null && gui != null && gui.getModularUIGui() != null) { - gui.getModularUIGui().setHoverTooltip(hoveredTab.getTabTooltips(), ItemStack.EMPTY, null, - hoveredTab.getTabTooltipComponent()); - } - super.drawInForeground(graphics, mouseX, mouseY, partialTicks); - } - - @OnlyIn(Dist.CLIENT) - public boolean isHoverLeftButton(double mouseX, double mouseY) { - return isMouseOver(getPosition().x + 8 + 24 + 4, getPosition().y, 16, 24, mouseX, mouseY); - } - - @OnlyIn(Dist.CLIENT) - public boolean isHoverRightButton(double mouseX, double mouseY) { - return isMouseOver(getPosition().x + getSize().width - 8 - 16, getPosition().y, 16, 24, mouseX, mouseY); - } - - @OnlyIn(Dist.CLIENT) - @Nullable - public IFancyUIProvider getHoveredTab(double mouseX, double mouseY) { - if (isMouseOverElement(mouseX, mouseY)) { - var position = getPosition(); - var size = getSize(); - // main tab - if (isMouseOver(position.x + 8, position.y, 24, 24, mouseX, mouseY)) { - return mainTab; - } - // others - if (hasButton()) { // need a scrollable bar - var sx = position.x + 8 + 24 + 4 + 16; - if (isMouseOver(sx, position.y, getSubTabsWidth(), 24, mouseX, mouseY)) { - var i = ((int) mouseX - sx + getOffset()) / 24; - if (i < subTabs.size()) { - return subTabs.get(i); - } - } - } else { - int i = (position.x + size.width - 8 - (int) mouseX) / 24; - if (i < subTabs.size()) { - return subTabs.get(subTabs.size() - 1 - i); - } - } - } - return null; - } - - @OnlyIn(Dist.CLIENT) - public void drawTab(IFancyUIProvider tab, @NotNull GuiGraphics graphics, int mouseX, int mouseY, int x, int y, - int width, int height, IFancyUIProvider hoveredTab) { - // render background - if (tab == selectedTab) { - tabPressedTexture.draw(graphics, mouseX, mouseY, x, y, width, height); - } else if (tab == hoveredTab) { - tabHoverTexture.draw(graphics, mouseX, mouseY, x, y, width, height); - } else { - tabTexture.draw(graphics, mouseX, mouseY, x, y, width, height); - } - // render icon - tab.getTabIcon().draw(graphics, mouseX, mouseY, x + (width - 16) / 2f, y + (height - 16) / 2f, 16, 16); - } - - public void selectTab(IFancyUIProvider selectedTab) { - this.selectedTab = selectedTab; - this.detectAndSendChanges(); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/TitleBarWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/TitleBarWidget.java deleted file mode 100644 index b40d56fc467..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/TitleBarWidget.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.fancy; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.TextTexture; -import com.lowdragmc.lowdraglib.gui.util.ClickData; -import com.lowdragmc.lowdraglib.gui.widget.ButtonWidget; -import com.lowdragmc.lowdraglib.gui.widget.ImageWidget; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.utils.Position; -import com.lowdragmc.lowdraglib.utils.Size; - -import net.minecraft.ChatFormatting; -import net.minecraft.MethodsReturnNonnullByDefault; - -import java.util.function.Consumer; - -import javax.annotation.ParametersAreNonnullByDefault; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class TitleBarWidget extends WidgetGroup { - - private static final int BORDER_WIDTH = 3; - private static final int HORIZONTAL_MARGIN = 8; - private static final int HEIGHT = 16; - private static final int BTN_WIDTH = 18; - - private static final float ROLL_SPEED = 0.7f; - - private int width; - private boolean showBackButton = false; - private boolean showMenuButton = false; - private final int innerHeight; - - /** - * The button group is rendered behind the main section and contains the back and menu buttons. - *

- * For easier texture reuse, the background is applied to the group itself, instead of the individual buttons.
- * The button group therefore needs to be rendered behind the main section. - */ - private final WidgetGroup buttonGroup; - private final Widget backButton; - private final Widget menuButton; - - /** - * The main section contains the current tab's icon and title text - */ - private final WidgetGroup mainSection; - private final ImageWidget tabIcon; - private final ImageWidget tabTitle; - private TextTexture titleText; - - public TitleBarWidget(int parentWidth, Consumer onBackClicked, Consumer onMenuClicked) { - super(HORIZONTAL_MARGIN, -HEIGHT, parentWidth, HEIGHT); - this.innerHeight = HEIGHT - BORDER_WIDTH; - this.width = parentWidth - (2 * HORIZONTAL_MARGIN); - - addWidget(this.buttonGroup = new WidgetGroup(0, BORDER_WIDTH, width, innerHeight)); - buttonGroup.setBackground(GuiTextures.TITLE_BAR_BACKGROUND); - buttonGroup.addWidget(this.backButton = new ButtonWidget(0, BORDER_WIDTH, BTN_WIDTH, HEIGHT - BORDER_WIDTH, - new TextTexture(" <").setDropShadow(false).setColor(ChatFormatting.BLACK.getColor()), onBackClicked) - .setHoverTooltips("gtceu.gui.title_bar.back")); - buttonGroup.addWidget(this.menuButton = new ButtonWidget(width - BTN_WIDTH, BORDER_WIDTH, BTN_WIDTH, - HEIGHT - BORDER_WIDTH, - new TextTexture("+").setDropShadow(false).setColor(ChatFormatting.BLACK.getColor()), onMenuClicked) - .setHoverTooltips("gtceu.gui.title_bar.page_switcher")); - - addWidget(this.mainSection = new WidgetGroup(BTN_WIDTH, 0, width, HEIGHT)); - mainSection.setBackground(GuiTextures.TITLE_BAR_BACKGROUND); - mainSection.addWidget(this.tabIcon = new ImageWidget( - BORDER_WIDTH + 1, BORDER_WIDTH + 1, - innerHeight - 2, innerHeight - 2, - IGuiTexture.EMPTY)); - mainSection.addWidget(this.tabTitle = new ImageWidget( - BORDER_WIDTH + innerHeight, BORDER_WIDTH, 0, 0, IGuiTexture.EMPTY)); - } - - public void updateState(IFancyUIProvider currentPage, boolean showBackButton, boolean showMenuButton) { - this.showBackButton = showBackButton; - this.showMenuButton = showMenuButton; - - titleText = new TextTexture(ChatFormatting.BLACK.toString() + currentPage.getTitle().copy().getString()) - .setDropShadow(false) - .setType(TextTexture.TextType.ROLL); - titleText.setRollSpeed(ROLL_SPEED); - - tabIcon.setImage(currentPage.getTabIcon()); - tabTitle.setImage(titleText); - - backButton.setVisible(showBackButton); - backButton.setActive(showBackButton); - - menuButton.setVisible(showMenuButton); - menuButton.setActive(showMenuButton); - - onSizeUpdate(); - } - - @Override - protected void onSizeUpdate() { - this.width = getSize().getWidth() - (2 * HORIZONTAL_MARGIN); - - var hiddenButtons = 2; - if (showBackButton) hiddenButtons--; - if (showMenuButton) hiddenButtons--; - - int buttonGroupWidth = this.width - (BTN_WIDTH * hiddenButtons); - buttonGroup.setSize(new Size(buttonGroupWidth, innerHeight)); - buttonGroup.setSelfPosition(new Position(showBackButton ? 0 : BTN_WIDTH, BORDER_WIDTH)); - menuButton.setSelfPosition(new Position(buttonGroupWidth - BTN_WIDTH, BORDER_WIDTH)); - - int mainSectionWidth = this.width - (BTN_WIDTH * 2); - int titleWidth = mainSectionWidth - (2 * BORDER_WIDTH) - innerHeight; - mainSection.setSize(new Size(mainSectionWidth, HEIGHT)); - titleText.setWidth(titleWidth); - tabTitle.setSize(new Size(titleWidth, HEIGHT - BORDER_WIDTH)); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/TooltipsPanel.java b/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/TooltipsPanel.java deleted file mode 100644 index 5e5e01d7975..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/TooltipsPanel.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.fancy; - -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.utils.Size; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import lombok.Getter; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class TooltipsPanel extends Widget { - - @Getter - protected List tooltips = new ArrayList<>(); - - public TooltipsPanel() { - super(202, 2, 20, 0); - } - - public void clear() { - tooltips.clear(); - } - - public void attachTooltips(IFancyTooltip... tooltips) { - this.tooltips.addAll(Arrays.asList(tooltips)); - } - - @Override - @OnlyIn(Dist.CLIENT) - public void drawInBackground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - super.drawInBackground(graphics, mouseX, mouseY, partialTicks); - var position = getPosition(); - var size = getSize(); - int offsetY = 0; - for (IFancyTooltip tooltip : this.tooltips) { - if (tooltip.showFancyTooltip()) { - // draw icon - tooltip.getFancyTooltipIcon().draw(graphics, mouseX, mouseY, position.x, position.y + offsetY, - size.width, size.width); - offsetY += size.getWidth() + 2; - } - } - setSize(new Size(getSize().width, Math.max(0, offsetY))); - } - - @Override - @OnlyIn(Dist.CLIENT) - public void drawInForeground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - if (getHoverElement(mouseX, mouseY) == this && gui != null && gui.getModularUIGui() != null) { - var position = getPosition(); - var size = getSize(); - int offsetY = 0; - for (IFancyTooltip tooltip : this.tooltips) { - if (tooltip.showFancyTooltip()) { - if (isMouseOver(position.x, position.y + offsetY, size.width, size.width, mouseX, mouseY)) { - gui.getModularUIGui().setHoverTooltip(tooltip.getFancyTooltip(), ItemStack.EMPTY, null, - tooltip.getFancyComponent()); - return; - } - offsetY += size.getWidth() + 2; - } - } - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/VerticalTabsWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/VerticalTabsWidget.java deleted file mode 100644 index 0fe2fc77f5f..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/fancy/VerticalTabsWidget.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.fancy; - -import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Consumer; - -public class VerticalTabsWidget extends TabsWidget { - - public VerticalTabsWidget(Consumer onTabClick, int x, int y, int width, int height) { - super(onTabClick, x, y, width, height); - ResourceTexture tabsLeft = new ResourceTexture("gtceu:textures/gui/tab/tabs_left.png"); - setTabTexture(tabsLeft.getSubTexture(0, 1 / 3f, 0.5f, 1 / 3f)); - setTabHoverTexture(tabsLeft.getSubTexture(0.5f, 1 / 3f, 0.5f, 1 / 3f)); - setTabPressedTexture(tabsLeft.getSubTexture(0.5f, 1 / 3f, 0.5f, 1 / 3f)); - } - - @Override - public boolean hasButton() { - return false; - } - - @Override - @OnlyIn(Dist.CLIENT) - public void drawInBackground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - drawBackgroundTexture(graphics, mouseX, mouseY); - var position = getPosition(); - var size = getSize(); - var hoveredTab = getHoveredTab(mouseX, mouseY); - // main tab - drawTab(mainTab, graphics, mouseX, mouseY, position.x, position.y + 8, 24, 24, hoveredTab); - for (int i = 0; i < subTabs.size(); ++i) { - drawTab(subTabs.get(i), graphics, mouseX, mouseY, position.x, position.y + 8 + 24 * (i + 1), 24, 24, - hoveredTab); - } - } - - @OnlyIn(Dist.CLIENT) - @Nullable - public IFancyUIProvider getHoveredTab(double mouseX, double mouseY) { - if (isMouseOverElement(mouseX, mouseY)) { - var position = getPosition(); - var size = getSize(); - // main tab - if (isMouseOver(position.x, position.y + 8, 24, 24, mouseX, mouseY)) { - return mainTab; - } - // others - int i = ((int) mouseY - position.y - 24 - 8) / 24; - if (i >= 0 && i < subTabs.size()) { - return subTabs.get(i); - } - } - return null; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/misc/IGhostFluidTarget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/misc/IGhostFluidTarget.java deleted file mode 100644 index 3324b34e811..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/misc/IGhostFluidTarget.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.misc; - -import com.gregtechceu.gtceu.GTCEu; - -import com.lowdragmc.lowdraglib.gui.ingredient.IGhostIngredientTarget; -import com.lowdragmc.lowdraglib.gui.ingredient.Target; - -import net.minecraft.client.renderer.Rect2i; -import net.minecraft.world.level.material.Fluid; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fluids.FluidStack; - -import com.google.common.collect.Lists; -import dev.emi.emi.api.stack.EmiStack; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -import static com.gregtechceu.gtceu.api.gui.widget.PhantomFluidWidget.drainFrom; - -public interface IGhostFluidTarget extends IGhostIngredientTarget { - - @OnlyIn(Dist.CLIENT) - Rect2i getRectangleBox(); - - @OnlyIn(Dist.CLIENT) - void acceptFluid(FluidStack fluidStack); - - @OnlyIn(Dist.CLIENT) - @Override - default List getPhantomTargets(Object ingredient) { - ingredient = convertIngredient(ingredient); - if (!(ingredient instanceof FluidStack) && drainFrom(ingredient) == null) { - return Collections.emptyList(); - } else { - final Rect2i rectangle = getRectangleBox(); - return Lists.newArrayList(new Target[] { new Target() { - - @NotNull - public Rect2i getArea() { - return rectangle; - } - - public void accept(@NotNull Object ingredient) { - ingredient = convertIngredient(ingredient); - - FluidStack ingredientStack; - if (ingredient instanceof FluidStack fluidStack) { - ingredientStack = fluidStack; - } else { - ingredientStack = drainFrom(ingredient); - } - - if (ingredientStack != null) { - acceptFluid(ingredientStack); - } - } - } }); - } - } - - default Object convertIngredient(Object ingredient) { - if (GTCEu.Mods.isREILoaded() && ingredient instanceof dev.architectury.fluid.FluidStack fluidStack) { - ingredient = new FluidStack(fluidStack.getFluid(), (int) fluidStack.getAmount(), fluidStack.getTag()); - } - - if (GTCEu.Mods.isEMILoaded() && ingredient instanceof EmiStack fluidEmiStack) { - Fluid fluid = fluidEmiStack.getKeyOfType(Fluid.class); - ingredient = fluid == null ? FluidStack.EMPTY : - new FluidStack(fluid, (int) fluidEmiStack.getAmount(), fluidEmiStack.getNbt()); - } - - if (GTCEu.Mods.isJEILoaded() && ingredient instanceof net.minecraftforge.fluids.FluidStack fluidStack) { - ingredient = new FluidStack(fluidStack.getFluid(), fluidStack.getAmount(), fluidStack.getTag()); - } - return ingredient; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/misc/IGhostItemTarget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/misc/IGhostItemTarget.java deleted file mode 100644 index e26f1e30520..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/misc/IGhostItemTarget.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.misc; - -import com.gregtechceu.gtceu.GTCEu; - -import com.lowdragmc.lowdraglib.gui.ingredient.IGhostIngredientTarget; -import com.lowdragmc.lowdraglib.gui.ingredient.Target; - -import net.minecraft.client.renderer.Rect2i; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import com.google.common.collect.Lists; -import dev.emi.emi.api.stack.EmiStack; -import mezz.jei.api.ingredients.ITypedIngredient; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - -public interface IGhostItemTarget extends IGhostIngredientTarget { - - @OnlyIn(Dist.CLIENT) - Rect2i getRectangleBox(); - - @OnlyIn(Dist.CLIENT) - void acceptItem(ItemStack itemStack); - - @OnlyIn(Dist.CLIENT) - @Override - default List getPhantomTargets(Object ingredient) { - if (!(convertIngredient(ingredient) instanceof ItemStack)) { - return Collections.emptyList(); - } else { - final Rect2i rectangle = getRectangleBox(); - return Lists.newArrayList(new Target[] { new Target() { - - @NotNull - public Rect2i getArea() { - return rectangle; - } - - public void accept(@NotNull Object ingredient) { - ingredient = convertIngredient(ingredient); - - if (ingredient instanceof ItemStack stack) { - acceptItem(stack); - } - } - } }); - } - } - - default Object convertIngredient(Object ingredient) { - if (GTCEu.Mods.isEMILoaded() && ingredient instanceof EmiStack itemEmiStack) { - Item item = itemEmiStack.getKeyOfType(Item.class); - ItemStack itemStack = item == null ? ItemStack.EMPTY : new ItemStack(item, (int) itemEmiStack.getAmount()); - if (!itemStack.isEmpty()) { - itemStack.setTag(itemEmiStack.getNbt()); - } - ingredient = itemStack; - } - - if (GTCEu.Mods.isJEILoaded() && ingredient instanceof ITypedIngredient itemJeiStack) { - return itemJeiStack.getItemStack().orElse(ItemStack.EMPTY); - } - return ingredient; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/util/TimedProgressSupplier.java b/src/main/java/com/gregtechceu/gtceu/api/gui/util/TimedProgressSupplier.java deleted file mode 100644 index e958d11e59d..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/util/TimedProgressSupplier.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.util; - -import java.util.function.DoubleSupplier; - -public class TimedProgressSupplier implements DoubleSupplier { - - private final int msPerCycle; - private final int maxValue; - private final boolean countDown; - private long startTime; - - public TimedProgressSupplier(int ticksPerCycle, int maxValue, boolean countDown) { - this.msPerCycle = ticksPerCycle * 50; - this.maxValue = maxValue; - this.countDown = countDown; - this.startTime = System.currentTimeMillis(); - } - - public void resetCountdown() { - startTime = System.currentTimeMillis(); - } - - @Override - public double getAsDouble() { - return calculateTime(); - } - - private double calculateTime() { - long currentTime = System.currentTimeMillis(); - long msPassed = (currentTime - startTime) % msPerCycle; - double currentValue = (1.0 * msPassed * maxValue) / msPerCycle; - if (countDown) { - return (maxValue - currentValue) / maxValue; - } - return currentValue / maxValue; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/BlockableSlotWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/BlockableSlotWidget.java deleted file mode 100644 index a4a2732243b..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/BlockableSlotWidget.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget; - -import com.lowdragmc.lowdraglib.utils.Position; -import com.lowdragmc.lowdraglib.utils.Size; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.world.Container; -import net.minecraftforge.items.IItemHandlerModifiable; - -import com.mojang.blaze3d.systems.RenderSystem; -import org.jetbrains.annotations.NotNull; - -import java.util.function.BooleanSupplier; - -/** Basically just your normal SlotWidget, but can render the slot as "grayed-out" with a Supplier value. */ -public class BlockableSlotWidget extends SlotWidget { - - private static final int OVERLAY_COLOR = 0x80404040; - - private BooleanSupplier isBlocked = () -> false; - - public BlockableSlotWidget(Container inventory, int slotIndex, int xPosition, int yPosition, boolean canTakeItems, - boolean canPutItems) { - super(inventory, slotIndex, xPosition, yPosition, canTakeItems, canPutItems); - } - - public BlockableSlotWidget(IItemHandlerModifiable itemHandler, int slotIndex, int xPosition, int yPosition, - boolean canTakeItems, boolean canPutItems) { - super(itemHandler, slotIndex, xPosition, yPosition, canTakeItems, - canPutItems); - } - - public BlockableSlotWidget(IItemHandlerModifiable itemHandler, int slotIndex, int xPosition, int yPosition) { - super(itemHandler, slotIndex, xPosition, yPosition); - } - - public BlockableSlotWidget(Container inventory, int slotIndex, int xPosition, int yPosition) { - super(inventory, slotIndex, xPosition, yPosition); - } - - public BlockableSlotWidget setIsBlocked(BooleanSupplier isBlocked) { - this.isBlocked = isBlocked; - return this; - } - - @Override - public void drawInBackground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - super.drawInBackground(graphics, mouseX, mouseY, partialTicks); - if (isBlocked.getAsBoolean()) { - Position pos = getPosition(); - Size size = getSize(); - RenderSystem.disableDepthTest(); - RenderSystem.colorMask(true, true, true, false); - graphics.fill(pos.getX() + 1, pos.getY() + 1, pos.getX() + 1 + size.getWidth() - 2, - pos.getY() + 1 + size.getHeight() - 2, OVERLAY_COLOR); - RenderSystem.colorMask(true, true, true, true); - RenderSystem.enableDepthTest(); - RenderSystem.enableBlend(); - } - } - - @Override - public boolean isMouseOverElement(double mouseX, double mouseY) { - // prevent slot removal and hover highlighting when slot is blocked - return super.isMouseOverElement(mouseX, mouseY) && !isBlocked.getAsBoolean(); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/ColorBlockWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/ColorBlockWidget.java deleted file mode 100644 index 5e7bbf3e412..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/ColorBlockWidget.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget; - -import com.lowdragmc.lowdraglib.gui.util.DrawerHelper; -import com.lowdragmc.lowdraglib.gui.widget.Widget; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; -import org.jetbrains.annotations.NotNull; - -import java.util.function.IntSupplier; - -@Setter -@Accessors(chain = true) -public class ColorBlockWidget extends Widget { - - private IntSupplier colorSupplier; - @Getter - private int currentColor; - private static boolean isShowAlpha = false; - - public ColorBlockWidget(int x, int y, int width, int height) { - super(x, y, width, height); - this.currentColor = 0xFFFFFFFF; - } - - @Override - public void updateScreen() { - super.updateScreen(); - if (isClientSideWidget && colorSupplier != null) { - currentColor = colorSupplier.getAsInt(); - } - } - - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (isMouseOverElement(mouseX, mouseY)) { - playButtonClickSound(); - isShowAlpha = !isShowAlpha; - return true; - } - return super.mouseClicked(mouseX, mouseY, button); - } - - @OnlyIn(Dist.CLIENT) - @Override - public void drawInBackground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - int x = getPosition().x + 1; - int y = getPosition().y + 1; - int width = getSize().width - 2; - int height = getSize().height - 2; - - if (colorSupplier != null) { - currentColor = colorSupplier.getAsInt(); - } - final int BORDER_COLOR = 0xFF000000; - int opaqueColor = isShowAlpha ? currentColor : currentColor | 0xFF000000; - graphics.fill(x, y, x + width, y + height, opaqueColor); - DrawerHelper.drawBorder(graphics, x, y, width, height, BORDER_COLOR, 1); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/ConfirmTextInputWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/ConfirmTextInputWidget.java deleted file mode 100644 index 9a77e5e26c1..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/ConfirmTextInputWidget.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; - -import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; -import com.lowdragmc.lowdraglib.gui.widget.ButtonWidget; -import com.lowdragmc.lowdraglib.gui.widget.TextFieldWidget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Consumer; -import java.util.function.Function; - -@Accessors(chain = true) -public class ConfirmTextInputWidget extends WidgetGroup { - - private final Consumer textResponder; - @Nullable - private final Function returnValidator; - private Function validator = (s) -> s; - @Getter(AccessLevel.PRIVATE) - @Setter(AccessLevel.PRIVATE) - private String inputText = ""; - @Setter - private String tooltip = ""; - - public ConfirmTextInputWidget(int x, int y, int width, int height, String text, - Consumer textResponder, - @Nullable Function validator, - @Nullable Function returnValidator) { - super(x, y, width, height); - this.textResponder = textResponder; - this.returnValidator = returnValidator; - if (validator != null) { - this.validator = validator; - } - if (text != null) { - this.inputText = text; - } - } - - @Override - public void initWidget() { - super.initWidget(); - this.addWidget(new ButtonWidget( - getSizeWidth() - getSizeHeight(), - 0, - getSizeHeight(), - getSizeHeight(), - pressed -> { - if (returnValidator != null) { - inputText = returnValidator.apply(inputText); - } - textResponder.accept(inputText); - }) - .setButtonTexture( - new GuiTextureGroup(GuiTextures.VANILLA_BUTTON, GuiTextures.BUTTON_CHECK))); - this.addWidget(new TextFieldWidget( - 1, - 1, - getSizeWidth() - getSizeHeight() - 4, - getSizeHeight() - 2, - this::getInputText, - this::setInputText) - .setValidator(validator) - .setHoverTooltips(tooltip)); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/CoverConfigurator.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/CoverConfigurator.java deleted file mode 100644 index a7253922ede..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/CoverConfigurator.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget; - -import com.gregtechceu.gtceu.api.capability.ICoverable; -import com.gregtechceu.gtceu.api.cover.CoverBehavior; -import com.gregtechceu.gtceu.api.cover.IUICover; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.IFancyConfigurator; -import com.gregtechceu.gtceu.common.data.GTItems; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.ItemStackTexture; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.utils.Position; -import com.lowdragmc.lowdraglib.utils.Size; - -import net.minecraft.core.Direction; -import net.minecraft.network.chat.Component; - -import lombok.AllArgsConstructor; -import org.jetbrains.annotations.Nullable; - -@AllArgsConstructor -public class CoverConfigurator implements IFancyConfigurator { - - protected final ICoverable coverable; - // runtime - @Nullable - protected final Direction side; - @Nullable - protected final CoverBehavior coverBehavior; - - @Override - public Component getTitle() { - return Component.translatable("gtceu.gui.cover_setting.title"); - } - - @Override - public IGuiTexture getIcon() { - return new ItemStackTexture(GTItems.ITEM_FILTER.get()); - } - - @Override - public Widget createConfigurator() { - WidgetGroup group = new WidgetGroup(new Position(0, 0)); - if (side != null) { - if (coverable.getCoverAtSide(side) instanceof IUICover iuiCover) { - Widget coverConfigurator = iuiCover.createUIWidget(); - coverConfigurator.setBackground(GuiTextures.BACKGROUND); - coverConfigurator.setSelfPosition(new Position(4, -4)); - group.addWidget(coverConfigurator); - group.setSize(new Size(Math.max(120, coverConfigurator.getSize().width + 8), - Math.max(80, 80 + coverConfigurator.getSize().height))); - } - } - return group; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/EnumSelectorWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/EnumSelectorWidget.java deleted file mode 100644 index 86d8c1bb2e5..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/EnumSelectorWidget.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget; - -import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.data.lang.LangHandler; - -import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.widget.CycleButtonWidget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; - -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.function.BiFunction; -import java.util.function.Consumer; - -import javax.annotation.ParametersAreNonnullByDefault; - -/** - * A widget for selecting a value from an enum or a subset of its values. - */ -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -public class EnumSelectorWidget & EnumSelectorWidget.SelectableEnum> extends WidgetGroup { - - public interface SelectableEnum { - - String getTooltip(); - - IGuiTexture getIcon(); - } - - public final CycleButtonWidget buttonWidget; - - public final List values; - public final Consumer onChanged; - - public int selected = 0; - - private BiFunction textureSupplier = (value, texture) -> new GuiTextureGroup( - GuiTextures.VANILLA_BUTTON, texture); - - private BiFunction> tooltipSupplier = (value, key) -> List - .copyOf(LangHandler.getSingleOrMultiLang(key)); - - public EnumSelectorWidget(int xPosition, int yPosition, int width, int height, T[] values, T initialValue, - Consumer onChanged) { - this(xPosition, yPosition, width, height, Arrays.asList(values), initialValue, onChanged); - } - - public EnumSelectorWidget(int xPosition, int yPosition, int width, int height, List values, T initialValue, - Consumer onChanged) { - super(xPosition, yPosition, width, height); - - this.values = values; - this.onChanged = onChanged; - - this.buttonWidget = new CycleButtonWidget(0, 0, width, height, values.size(), this::getTexture, - this::onSelected); - this.addWidget(buttonWidget); - - setSelected(initialValue); - } - - @Override - public void writeInitialData(FriendlyByteBuf buffer) { - super.writeInitialData(buffer); - buffer.writeInt(selected); - } - - @Override - public void readInitialData(FriendlyByteBuf buffer) { - super.readInitialData(buffer); - onSelected(buffer.readInt()); - } - - public T getCurrentValue() { - return values.get(selected); - } - - public IGuiTexture getTexture(int selected) { - var selectedValue = values.get(selected); - return textureSupplier.apply(selectedValue, selectedValue.getIcon()); - } - - private void onSelected(int selected) { - T selectedValue = values.get(selected); - setSelected(selectedValue); - } - - public EnumSelectorWidget setTextureSupplier(BiFunction textureSupplier) { - this.textureSupplier = textureSupplier; - - T selectedValue = getCurrentValue(); - buttonWidget.setBackground(textureSupplier.apply(selectedValue, selectedValue.getIcon())); - - return this; - } - - public EnumSelectorWidget setTooltipSupplier(BiFunction> tooltipSupplier) { - this.tooltipSupplier = tooltipSupplier; - - return this; - } - - public void setSelected(@NotNull T value) { - var selectedIndex = values.indexOf(value); - - if (selectedIndex == -1) - throw new NoSuchElementException(value + " is not a possible value for this selector."); - - this.selected = selectedIndex; - this.buttonWidget.setIndex(selectedIndex); - - updateTooltip(); - - onChanged.accept(value); - } - - private void updateTooltip() { - if (!GTCEu.isClientThread()) - return; - - T selectedValue = getCurrentValue(); - buttonWidget.setHoverTooltips(tooltipSupplier.apply(selectedValue, selectedValue.getTooltip())); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/ExtendedProgressWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/ExtendedProgressWidget.java deleted file mode 100644 index 80bbda0ad43..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/ExtendedProgressWidget.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget; - -import com.lowdragmc.lowdraglib.gui.texture.ProgressTexture; -import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; -import com.lowdragmc.lowdraglib.gui.widget.ProgressWidget; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; -import net.minecraft.world.item.ItemStack; - -import lombok.Setter; -import lombok.experimental.Accessors; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.DoubleSupplier; - -@Accessors(chain = true) -public class ExtendedProgressWidget extends ProgressWidget { - - private List serverTooltips = new ArrayList<>(); - @Setter - private Consumer> serverTooltipSupplier; - - public ExtendedProgressWidget() { - super(JEIProgress, 0, 0, 40, 40, new ProgressTexture()); - } - - public ExtendedProgressWidget(DoubleSupplier progressSupplier, int x, int y, int width, int height, - ResourceTexture fullImage) { - super(progressSupplier, x, y, width, height, fullImage); - } - - public ExtendedProgressWidget(DoubleSupplier progressSupplier, int x, int y, int width, int height, - ProgressTexture progressBar) { - super(progressSupplier, x, y, width, height, progressBar); - } - - public ExtendedProgressWidget(DoubleSupplier progressSupplier, int x, int y, int width, int height) { - super(progressSupplier, x, y, width, height); - } - - @Override - public void detectAndSendChanges() { - super.detectAndSendChanges(); - - if (serverTooltipSupplier != null) { - List textBuffer = new ArrayList<>(); - serverTooltipSupplier.accept(textBuffer); - if (!serverTooltips.equals(textBuffer)) { - this.serverTooltips = textBuffer; - writeUpdateInfo(1, buffer -> { - buffer.writeVarInt(serverTooltips.size()); - for (Component component : serverTooltips) { - buffer.writeComponent(component); - } - }); - } - } - } - - @Override - public void readUpdateInfo(int id, FriendlyByteBuf buffer) { - if (id == 1) { - this.serverTooltips.clear(); - int count = buffer.readVarInt(); - for (int i = 0; i < count; i++) { - Component component = buffer.readComponent(); - this.serverTooltips.add(component); - } - } else { - super.readUpdateInfo(id, buffer); - } - } - - @Override - public void drawInForeground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - if ((!tooltipTexts.isEmpty() || !serverTooltips.isEmpty()) && isMouseOverElement(mouseX, mouseY) && - getHoverElement(mouseX, mouseY) == this && gui != null && gui.getModularUIGui() != null) { - var tips = new ArrayList<>(tooltipTexts); - tips.addAll(serverTooltips); - gui.getModularUIGui().setHoverTooltip(tips, ItemStack.EMPTY, null, null); - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/GhostCircuitSlotWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/GhostCircuitSlotWidget.java deleted file mode 100644 index 26a37530d1c..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/GhostCircuitSlotWidget.java +++ /dev/null @@ -1,203 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.common.item.behavior.IntCircuitBehaviour; -import com.gregtechceu.gtceu.config.ConfigHolder; - -import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.ItemStackTexture; -import com.lowdragmc.lowdraglib.gui.widget.ButtonWidget; -import com.lowdragmc.lowdraglib.gui.widget.LabelWidget; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.items.IItemHandlerModifiable; - -import lombok.Getter; -import org.jetbrains.annotations.Nullable; - -/** - * Used for setting a "ghost" IC for a machine - */ -public class GhostCircuitSlotWidget extends SlotWidget { - - private static final int SET_TO_ZERO = 1; - private static final int SET_TO_EMPTY = 2; - private static final int SET_TO_N = 3; - - private static final int NO_CONFIG = -1; - - @Getter - private IItemHandlerModifiable circuitInventory; - @Nullable - private Widget configurator; - - public GhostCircuitSlotWidget() { - super(); - } - - public void setCircuitInventory(IItemHandlerModifiable circuitInventory) { - this.circuitInventory = circuitInventory; - setHandlerSlot(circuitInventory, 0); - } - - public boolean isConfiguratorOpen() { - return configurator != null; - } - - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (isMouseOverElement(mouseX, mouseY) && gui != null) { - if (button == 0 && Screen.hasShiftDown()) { - // open popup on shift-left-click - if (!isConfiguratorOpen()) { - this.gui.widget(configurator = createConfigurator()); - } else { - this.gui.mainGroup.removeWidget(configurator); - configurator = null; - } - } else if (button == 0) { - // increment on left-click - int newValue = getNextValue(true); - setCircuitValue(newValue); - } else if (button == 1 && Screen.hasShiftDown()) { - // clear on shift-right-click - this.circuitInventory.setStackInSlot(0, ItemStack.EMPTY); - writeClientAction(SET_TO_EMPTY, buf -> {}); - } else if (button == 1) { - // decrement on right-click - int newValue = getNextValue(false); - setCircuitValue(newValue); - } - return true; - } - return false; - } - - private int getNextValue(boolean increment) { - int currentValue = IntCircuitBehaviour.getCircuitConfiguration(this.circuitInventory.getStackInSlot(0)); - if (increment) { - // if at max, loop around to no circuit - if (currentValue == IntCircuitBehaviour.CIRCUIT_MAX) { - return 0; - } - // if at no circuit, skip 0 and return 1 - if (this.circuitInventory.getStackInSlot(0).isEmpty()) { - return 1; - } - // normal case: increment by 1 - return currentValue + 1; - } else { - // if at no circuit, loop around to max - if (this.circuitInventory.getStackInSlot(0).isEmpty()) { - return IntCircuitBehaviour.CIRCUIT_MAX; - } - // if at 1, skip 0 and return no circuit - if (currentValue == 1) { - return NO_CONFIG; - } - // normal case: decrement by 1 - return currentValue - 1; - } - } - - @Override - public boolean mouseWheelMove(double mouseX, double mouseY, double wheelDelta) { - if (isConfiguratorOpen()) return true; - if (isMouseOverElement(mouseX, mouseY) && gui != null) { - int newValue = getNextValue(wheelDelta >= 0); - setCircuitValue(newValue); - return true; - } - return false; - } - - @Override - public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) { - return false; - } - - @Override - public boolean canMergeSlot(ItemStack stack) { - return false; - } - - public void setCircuitValue(int newValue) { - if (newValue == NO_CONFIG) { - this.circuitInventory.setStackInSlot(0, ItemStack.EMPTY); - writeClientAction(SET_TO_EMPTY, buf -> {}); - } else { - this.circuitInventory.setStackInSlot(0, IntCircuitBehaviour.stack(newValue)); - writeClientAction(SET_TO_N, buf -> buf.writeVarInt(newValue)); - } - } - - @Override - public void handleClientAction(int id, FriendlyByteBuf buffer) { - switch (id) { - case SET_TO_ZERO -> this.circuitInventory.setStackInSlot(0, IntCircuitBehaviour.stack(0)); - case SET_TO_EMPTY -> this.circuitInventory.setStackInSlot(0, ItemStack.EMPTY); - case SET_TO_N -> this.circuitInventory.setStackInSlot(0, IntCircuitBehaviour.stack(buffer.readVarInt())); - } - } - - public Widget createConfigurator() { - var group = new WidgetGroup(0, 0, 174, 132); - group.addWidget(new LabelWidget(9, 8, "Programmed Circuit Configuration")); - group.addWidget(new SlotWidget(this.circuitInventory, 0, (group.getSize().width - 18) / 2, 20, - !ConfigHolder.INSTANCE.machines.ghostCircuit, !ConfigHolder.INSTANCE.machines.ghostCircuit) - .setBackground(new GuiTextureGroup(GuiTextures.SLOT, GuiTextures.INT_CIRCUIT_OVERLAY))); - if (ConfigHolder.INSTANCE.machines.ghostCircuit) { - group.addWidget(new ButtonWidget((group.getSize().width - 18) / 2, 20, 18, 18, IGuiTexture.EMPTY, - clickData -> { - if (!clickData.isRemote) { - circuitInventory.setStackInSlot(0, ItemStack.EMPTY); - } - })); - } - int idx = 0; - for (int x = 0; x <= 2; x++) { - for (int y = 0; y <= 8; y++) { - int finalIdx = idx; - group.addWidget(new ButtonWidget(5 + (18 * y), 48 + (18 * x), 18, 18, - new GuiTextureGroup(GuiTextures.SLOT, - new ItemStackTexture(IntCircuitBehaviour.stack(finalIdx)).scale(16f / 18)), - clickData -> { - if (!clickData.isRemote) { - ItemStack stack = circuitInventory.getStackInSlot(0).copy(); - if (IntCircuitBehaviour.isIntegratedCircuit(stack)) { - IntCircuitBehaviour.setCircuitConfiguration(stack, finalIdx); - circuitInventory.setStackInSlot(0, stack); - } else if (ConfigHolder.INSTANCE.machines.ghostCircuit) { - circuitInventory.setStackInSlot(0, IntCircuitBehaviour.stack(finalIdx)); - } - } - })); - idx++; - } - } - for (int x = 0; x <= 5; x++) { - int finalIdx = x + 27; - group.addWidget(new ButtonWidget(5 + (18 * x), 102, 18, 18, - new GuiTextureGroup(GuiTextures.SLOT, - new ItemStackTexture(IntCircuitBehaviour.stack(finalIdx)).scale(16f / 18)), - clickData -> { - if (!clickData.isRemote) { - ItemStack stack = circuitInventory.getStackInSlot(0).copy(); - if (IntCircuitBehaviour.isIntegratedCircuit(stack)) { - IntCircuitBehaviour.setCircuitConfiguration(stack, finalIdx); - circuitInventory.setStackInSlot(0, stack); - } else if (ConfigHolder.INSTANCE.machines.ghostCircuit) { - circuitInventory.setStackInSlot(0, IntCircuitBehaviour.stack(finalIdx)); - } - } - })); - } - group.setBackground(GuiTextures.BACKGROUND); - return group; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/IntInputWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/IntInputWidget.java deleted file mode 100644 index 887c9c9f6ae..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/IntInputWidget.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget; - -import com.lowdragmc.lowdraglib.gui.widget.TextFieldWidget; -import com.lowdragmc.lowdraglib.utils.Position; -import com.lowdragmc.lowdraglib.utils.Size; - -import net.minecraft.util.Mth; - -import java.util.function.Consumer; -import java.util.function.Supplier; - -/** - * A widget containing an integer input field, as well as adjacent buttons for increasing or decreasing the value. - * - *

- * The buttons' change amount can be altered with Ctrl, Shift, or both.
- * The input is limited by a minimum and maximum value. - *

- */ -public class IntInputWidget extends NumberInputWidget { - - public IntInputWidget(Supplier valueSupplier, Consumer onChanged) { - super(valueSupplier, onChanged); - } - - public IntInputWidget(Position position, Supplier valueSupplier, Consumer onChanged) { - super(position, valueSupplier, onChanged); - } - - public IntInputWidget(Position position, Size size, Supplier valueSupplier, Consumer onChanged) { - super(position, size, valueSupplier, onChanged); - } - - public IntInputWidget(int x, int y, int width, int height, Supplier valueSupplier, - Consumer onChanged) { - super(x, y, width, height, valueSupplier, onChanged); - } - - @Override - protected Integer defaultMin() { - return 0; - } - - @Override - protected Integer defaultMax() { - return Integer.MAX_VALUE; - } - - @Override - protected String toText(Integer value) { - return String.valueOf(value); - } - - @Override - protected Integer fromText(String value) { - return Integer.parseInt(value); - } - - @Override - protected NumberInputWidget.ChangeValues getChangeValues() { - return new NumberInputWidget.ChangeValues<>(1, 8, 64, 512); - } - - @Override - protected Integer getOne(boolean positive) { - return positive ? 1 : -1; - } - - @Override - protected Integer add(Integer a, Integer b) { - return a + b; - } - - @Override - protected Integer multiply(Integer a, Integer b) { - return a * b; - } - - @Override - protected Integer clamp(Integer value, Integer min, Integer max) { - return Mth.clamp(value, min, max); - } - - @Override - protected void setTextFieldRange(TextFieldWidget textField, Integer min, Integer max) { - textField.setNumbersOnly(min, max); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/LongInputWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/LongInputWidget.java deleted file mode 100644 index e7a761a2775..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/LongInputWidget.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget; - -import com.gregtechceu.gtceu.utils.GTMath; - -import com.lowdragmc.lowdraglib.gui.widget.TextFieldWidget; -import com.lowdragmc.lowdraglib.utils.Position; -import com.lowdragmc.lowdraglib.utils.Size; - -import java.util.function.Consumer; -import java.util.function.Supplier; - -/** - * A widget containing an integer input field, as well as adjacent buttons for increasing or decreasing the value. - * - *

- * The buttons' change amount can be altered with Ctrl, Shift, or both.
- * The input is limited by a minimum and maximum value. - *

- */ -public class LongInputWidget extends NumberInputWidget { - - public LongInputWidget(Supplier valueSupplier, Consumer onChanged) { - super(valueSupplier, onChanged); - } - - public LongInputWidget(Position position, Supplier valueSupplier, Consumer onChanged) { - super(position, valueSupplier, onChanged); - } - - public LongInputWidget(Position position, Size size, Supplier valueSupplier, Consumer onChanged) { - super(position, size, valueSupplier, onChanged); - } - - public LongInputWidget(int x, int y, int width, int height, Supplier valueSupplier, - Consumer onChanged) { - super(x, y, width, height, valueSupplier, onChanged); - } - - @Override - protected Long defaultMin() { - return 0L; - } - - @Override - protected Long defaultMax() { - return Long.MAX_VALUE; - } - - @Override - protected String toText(Long value) { - return String.valueOf(value); - } - - @Override - protected Long fromText(String value) { - return Long.parseLong(value); - } - - @Override - protected ChangeValues getChangeValues() { - return new ChangeValues<>(1L, 8L, 64L, 512L); - } - - @Override - protected Long add(Long a, Long b) { - return a + b; - } - - @Override - protected Long multiply(Long a, Long b) { - return a * b; - } - - @Override - protected Long clamp(Long value, Long min, Long max) { - return GTMath.clamp(value, min, max); - } - - @Override - protected void setTextFieldRange(TextFieldWidget textField, Long min, Long max) { - textField.setNumbersOnly(min, max); - } - - @Override - protected Long getOne(boolean positive) { - return positive ? 1L : -1L; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/NumberInputWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/NumberInputWidget.java deleted file mode 100644 index fdcd8bf9884..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/NumberInputWidget.java +++ /dev/null @@ -1,208 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget; - -import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.utils.GTUtil; - -import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.TextTexture; -import com.lowdragmc.lowdraglib.gui.util.ClickData; -import com.lowdragmc.lowdraglib.gui.widget.ButtonWidget; -import com.lowdragmc.lowdraglib.gui.widget.TextFieldWidget; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.utils.Position; -import com.lowdragmc.lowdraglib.utils.Size; - -import net.minecraft.client.Minecraft; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.util.Mth; - -import lombok.Getter; - -import java.util.function.Consumer; -import java.util.function.Supplier; - -/** - * A widget containing an integer input field, as well as adjacent buttons for increasing or decreasing the value. - * - *

- * The buttons' change amount can be altered with Ctrl, Shift, or both.
- * The input is limited by a minimum and maximum value. - *

- */ -public abstract class NumberInputWidget extends WidgetGroup { - - protected abstract T defaultMin(); - - protected abstract T defaultMax(); - - protected abstract String toText(T value); - - protected abstract T fromText(String value); - - protected record ChangeValues(T regular, T shift, T ctrl, T ctrlShift) {} - - protected abstract ChangeValues getChangeValues(); - - protected abstract T add(T a, T b); - - protected abstract T multiply(T a, T b); - - protected abstract T clamp(T value, T min, T max); - - protected abstract void setTextFieldRange(TextFieldWidget textField, T min, T max); - - protected abstract T getOne(boolean positive); - - ///////////////////////////////////////////////// - // *********** IMPLEMENTATION ***********// - ///////////////////////////////////////////////// - - private final ChangeValues CHANGE_VALUES = getChangeValues(); - private final T ONE_POSITIVE = getOne(true); - private final T ONE_NEGATIVE = getOne(false); - - @Getter - private Supplier valueSupplier; - @Getter - private T min = defaultMin(); - @Getter - private T max = defaultMax(); - - private final Consumer onChanged; - - private TextFieldWidget textField; - - public NumberInputWidget(Supplier valueSupplier, Consumer onChanged) { - this(0, 0, 100, 20, valueSupplier, onChanged); - } - - public NumberInputWidget(Position position, Supplier valueSupplier, Consumer onChanged) { - this(position, new Size(100, 20), valueSupplier, onChanged); - } - - public NumberInputWidget(Position position, Size size, Supplier valueSupplier, Consumer onChanged) { - this(position.x, position.y, size.width, size.height, valueSupplier, onChanged); - } - - public NumberInputWidget(int x, int y, int width, int height, Supplier valueSupplier, Consumer onChanged) { - super(x, y, width, height); - this.valueSupplier = valueSupplier; - this.onChanged = onChanged; - buildUI(); - } - - @Override - public void initWidget() { - super.initWidget(); - textField.setCurrentString(toText(valueSupplier.get())); - } - - @Override - public void writeInitialData(FriendlyByteBuf buffer) { - super.writeInitialData(buffer); - buffer.writeUtf(toText(valueSupplier.get())); - } - - @Override - public void readInitialData(FriendlyByteBuf buffer) { - super.readInitialData(buffer); - textField.setCurrentString(buffer.readUtf()); - } - - @Override - public Widget setHoverTooltips(String... tooltipText) { - textField.setHoverTooltips(tooltipText); - return super.setHoverTooltips(tooltipText); - } - - private void buildUI() { - int buttonWidth = Mth.clamp(this.getSize().width / 5, 15, 40); - int textFieldWidth = this.getSize().width - (2 * buttonWidth) - 4; - - this.addWidget(new ButtonWidget(0, 0, buttonWidth, 20, - new GuiTextureGroup(GuiTextures.VANILLA_BUTTON, getButtonTexture("-", buttonWidth)), - this::decrease).setHoverTooltips("gui.widget.incrementButton.default_tooltip")); - - this.textField = new TextFieldWidget(buttonWidth + 2, 0, textFieldWidth, 20, - () -> toText(valueSupplier.get()), - stringValue -> this.setValue(clamp(fromText(stringValue), min, max))); - this.updateTextFieldRange(); - this.addWidget(this.textField); - - this.addWidget(new ButtonWidget(buttonWidth + textFieldWidth + 4, 0, buttonWidth, 20, - new GuiTextureGroup(GuiTextures.VANILLA_BUTTON, getButtonTexture("+", buttonWidth)), - this::increase).setHoverTooltips("gui.widget.incrementButton.default_tooltip")); - } - - private IGuiTexture getButtonTexture(String prefix, int buttonWidth) { - var texture = new TextTexture(prefix + "1"); - - if (!GTCEu.isClientThread()) { - return texture; - } - - // Dynamic text is only necessary on the remote side: - - int maxTextWidth = buttonWidth - 4; - - texture.setSupplier(() -> { - T amount = GTUtil.isCtrlDown() ? - GTUtil.isShiftDown() ? CHANGE_VALUES.ctrlShift : CHANGE_VALUES.ctrl : - GTUtil.isShiftDown() ? CHANGE_VALUES.shift : CHANGE_VALUES.regular; - - String text = prefix + toText(amount); - - texture.scale(maxTextWidth / (float) Math.max(Minecraft.getInstance().font.width(text), maxTextWidth)); - - return text; - }); - - return texture; - } - - private void increase(ClickData cd) { - this.changeValue(cd, ONE_POSITIVE); - } - - private void decrease(ClickData cd) { - this.changeValue(cd, ONE_NEGATIVE); - } - - private void changeValue(ClickData cd, T multiplier) { - if (!cd.isRemote) { - T amount = cd.isCtrlClick ? - cd.isShiftClick ? CHANGE_VALUES.ctrlShift : CHANGE_VALUES.ctrl : - cd.isShiftClick ? CHANGE_VALUES.shift : CHANGE_VALUES.regular; - - this.setValue(clamp(add(valueSupplier.get(), multiply(amount, multiplier)), min, max)); - } - } - - public NumberInputWidget setMin(T min) { - this.min = min; - updateTextFieldRange(); - - return this; - } - - public NumberInputWidget setMax(T max) { - this.max = max; - updateTextFieldRange(); - - return this; - } - - public NumberInputWidget setValue(T value) { - onChanged.accept(value); - return this; - } - - protected void updateTextFieldRange() { - setTextFieldRange(textField, min, max); - - this.setValue(clamp(valueSupplier.get(), min, max)); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/PatternPreviewWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/PatternPreviewWidget.java index 182707f3530..087670b518f 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/PatternPreviewWidget.java +++ b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/PatternPreviewWidget.java @@ -10,7 +10,7 @@ import com.gregtechceu.gtceu.api.pattern.TraceabilityPredicate; import com.gregtechceu.gtceu.api.pattern.predicates.SimplePredicate; import com.gregtechceu.gtceu.config.ConfigHolder; -import com.gregtechceu.gtceu.integration.xei.handlers.item.CycleItemEntryHandler; +import com.gregtechceu.gtceu.integration.recipeviewer.handlers.item.CycleItemEntryHandler; import com.lowdragmc.lowdraglib.client.scene.WorldSceneRenderer; import com.lowdragmc.lowdraglib.client.utils.RenderUtils; diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/PhantomSlotWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/PhantomSlotWidget.java deleted file mode 100644 index 190de3930ff..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/PhantomSlotWidget.java +++ /dev/null @@ -1,258 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget; - -import com.gregtechceu.gtceu.GTCEu; - -import com.lowdragmc.lowdraglib.gui.editor.annotation.ConfigSetter; -import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; -import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; -import com.lowdragmc.lowdraglib.gui.editor.annotation.NumberRange; -import com.lowdragmc.lowdraglib.gui.editor.configurator.IConfigurableWidget; -import com.lowdragmc.lowdraglib.gui.ingredient.IGhostIngredientTarget; -import com.lowdragmc.lowdraglib.gui.ingredient.Target; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.Rect2i; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.ClickType; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.items.IItemHandlerModifiable; - -import com.google.common.collect.Lists; -import com.mojang.blaze3d.platform.InputConstants; -import dev.emi.emi.api.stack.EmiStack; -import mezz.jei.api.ingredients.ITypedIngredient; -import org.lwjgl.glfw.GLFW; - -import java.util.Collections; -import java.util.List; -import java.util.function.Predicate; - -import javax.annotation.Nonnull; - -@LDLRegister(name = "gtm_phantom_item_slot", group = "widget.gtm_container", priority = 50) -public class PhantomSlotWidget extends SlotWidget implements IGhostIngredientTarget, IConfigurableWidget { - - private boolean clearSlotOnRightClick; - - @Configurable - @NumberRange(range = { 0, 64 }) - private int maxStackSize = 64; - - private Predicate validator = stack -> true; - - public PhantomSlotWidget() { - super(); - } - - public PhantomSlotWidget(IItemHandlerModifiable itemHandler, int slotIndex, int xPosition, int yPosition) { - super(itemHandler, slotIndex, xPosition, yPosition, true, true); - } - - public PhantomSlotWidget(IItemHandlerModifiable itemHandler, int slotIndex, int xPosition, int yPosition, - Predicate validator) { - super(itemHandler, slotIndex, xPosition, yPosition, true, true); - this.validator = validator; - } - - public PhantomSlotWidget setClearSlotOnRightClick(boolean clearSlotOnRightClick) { - this.clearSlotOnRightClick = clearSlotOnRightClick; - return this; - } - - @ConfigSetter(field = "canTakeItems") - public PhantomSlotWidget setCanTakeItems(boolean v) { - // you cant modify it - return this; - } - - @ConfigSetter(field = "canPutItems") - public PhantomSlotWidget setCanPutItems(boolean v) { - // you cant modify it - return this; - } - - public PhantomSlotWidget setMaxStackSize(int stackSize) { - maxStackSize = stackSize; - return this; - } - - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (slotReference != null && isMouseOverElement(mouseX, mouseY) && gui != null) { - if (isClientSideWidget && !gui.getModularUIContainer().getCarried().isEmpty()) { - slotReference.set(gui.getModularUIContainer().getCarried()); - } else if (button == 1 && clearSlotOnRightClick && !slotReference.getItem().isEmpty()) { - slotReference.set(ItemStack.EMPTY); - writeClientAction(2, buf -> {}); - } else { - HOVER_SLOT = slotReference; - gui.getModularUIGui().superMouseClicked(mouseX, mouseY, button); - HOVER_SLOT = null; - } - return true; - } - return false; - } - - @Override - public ItemStack slotClick(int dragType, ClickType clickTypeIn, Player player) { - if (slotReference != null && gui != null) { - ItemStack stackHeld = gui.getModularUIContainer().getCarried(); - return slotClickPhantom(slotReference, dragType, clickTypeIn, stackHeld); - } - return ItemStack.EMPTY; - } - - @Override - public boolean canMergeSlot(ItemStack stack) { - return false; - } - - @Override - public boolean canTakeStack(Player player) { - return false; - } - - @Override - public boolean canPutStack(ItemStack stack) { - return false; - } - - @Override - @OnlyIn(Dist.CLIENT) - public List getPhantomTargets(Object ingredient) { - if (GTCEu.Mods.isEMILoaded() && ingredient instanceof EmiStack emiStack) { - Item item = emiStack.getKeyOfType(Item.class); - if (item != null) { - ingredient = new ItemStack(item, (int) emiStack.getAmount()); - ((ItemStack) ingredient).setTag(emiStack.getNbt()); - } - } else if (GTCEu.Mods.isJEILoaded() && ingredient instanceof ITypedIngredient jeiStack) { - ingredient = jeiStack.getItemStack().orElse(null); - } - if (!(ingredient instanceof ItemStack)) { - return Collections.emptyList(); - } - - Rect2i rectangle = toRectangleBox(); - return Lists.newArrayList(new Target() { - - @Nonnull - @Override - public Rect2i getArea() { - return rectangle; - } - - @Override - public void accept(@Nonnull Object ingredient) { - if (GTCEu.Mods.isEMILoaded() && ingredient instanceof EmiStack emiStack) { - Item item = emiStack.getKeyOfType(Item.class); - if (item != null) { - ingredient = new ItemStack(item, (int) emiStack.getAmount()); - ((ItemStack) ingredient).setTag(emiStack.getNbt()); - } - } else if (GTCEu.Mods.isJEILoaded() && ingredient instanceof ITypedIngredient jeiStack) { - ingredient = jeiStack.getItemStack().orElse(null); - } - if (slotReference != null && ingredient instanceof ItemStack stack) { - long id = Minecraft.getInstance().getWindow().getWindow(); - boolean shiftDown = InputConstants.isKeyDown(id, GLFW.GLFW_KEY_LEFT_SHIFT); - ClickType clickType = shiftDown ? ClickType.QUICK_MOVE : ClickType.PICKUP; - slotClickPhantom(slotReference, 0, clickType, stack); - writeClientAction(1, buffer -> { - buffer.writeItem(stack); - buffer.writeVarInt(0); - buffer.writeBoolean(shiftDown); - }); - } - } - }); - } - - @Override - public void handleClientAction(int id, FriendlyByteBuf buffer) { - if (slotReference != null && id == 1) { - ItemStack stackHeld = buffer.readItem(); - int mouseButton = buffer.readVarInt(); - boolean shiftKeyDown = buffer.readBoolean(); - ClickType clickType = shiftKeyDown ? ClickType.QUICK_MOVE : ClickType.PICKUP; - slotClickPhantom(slotReference, mouseButton, clickType, stackHeld); - } else if (slotReference != null && id == 2) { - slotReference.set(ItemStack.EMPTY); - } - } - - public ItemStack slotClickPhantom(Slot slot, int mouseButton, ClickType clickTypeIn, ItemStack stackHeld) { - ItemStack stack = ItemStack.EMPTY; - - ItemStack stackSlot = slot.getItem(); - if (!stackSlot.isEmpty()) { - stack = stackSlot.copy(); - } - - if (mouseButton == 2) { - fillPhantomSlot(slot, ItemStack.EMPTY, mouseButton); - } else if (mouseButton == 0 || mouseButton == 1) { - - if (stackSlot.isEmpty()) { - if (!stackHeld.isEmpty()) { - fillPhantomSlot(slot, stackHeld, mouseButton); - } - } else if (stackHeld.isEmpty()) { - adjustPhantomSlot(slot, mouseButton, clickTypeIn); - } else { - if (!areItemsEqual(stackSlot, stackHeld)) { - adjustPhantomSlot(slot, mouseButton, clickTypeIn); - } - fillPhantomSlot(slot, stackHeld, mouseButton); - } - } else if (mouseButton == 5) { - if (!slot.hasItem()) { - fillPhantomSlot(slot, stackHeld, mouseButton); - } - } - return stack; - } - - private void adjustPhantomSlot(Slot slot, int mouseButton, ClickType clickTypeIn) { - ItemStack stackSlot = slot.getItem(); - int stackSize; - if (clickTypeIn == ClickType.QUICK_MOVE) { - stackSize = mouseButton == 0 ? (stackSlot.getCount() + 1) / 2 : stackSlot.getCount() * 2; - } else { - stackSize = mouseButton == 0 ? stackSlot.getCount() - 1 : stackSlot.getCount() + 1; - } - - if (stackSize > slot.getMaxStackSize()) { - stackSize = slot.getMaxStackSize(); - } - - stackSlot.setCount(Math.min(maxStackSize, stackSize)); - - slot.set(stackSlot); - } - - private void fillPhantomSlot(Slot slot, ItemStack stackHeld, int mouseButton) { - if (stackHeld.isEmpty()) { - slot.set(ItemStack.EMPTY); - return; - } - - int stackSize = mouseButton == 0 ? stackHeld.getCount() : 1; - if (stackSize > slot.getMaxStackSize()) { - stackSize = slot.getMaxStackSize(); - } - ItemStack phantomStack = stackHeld.copy(); - phantomStack.setCount(Math.min(maxStackSize, stackSize)); - if (validator.test(phantomStack)) slot.set(phantomStack); - } - - public boolean areItemsEqual(ItemStack itemStack1, ItemStack itemStack2) { - return ItemStack.matches(itemStack1, itemStack2); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/PredicatedImageWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/PredicatedImageWidget.java deleted file mode 100644 index be26db6e526..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/PredicatedImageWidget.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.widget.ImageWidget; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import lombok.Setter; -import lombok.experimental.Accessors; -import org.jetbrains.annotations.NotNull; - -import java.util.function.BooleanSupplier; - -@Accessors(chain = true) -public class PredicatedImageWidget extends ImageWidget { - - @Setter - private BooleanSupplier predicate; - private boolean isVisible = true; - - public PredicatedImageWidget(int xPosition, int yPosition, int width, int height, IGuiTexture area) { - super(xPosition, yPosition, width, height, area); - } - - @Override - public void writeInitialData(FriendlyByteBuf buffer) { - super.writeInitialData(buffer); - isVisible = predicate == null || predicate.getAsBoolean(); - buffer.writeBoolean(isVisible); - } - - @Override - public void readInitialData(FriendlyByteBuf buffer) { - super.readInitialData(buffer); - isVisible = buffer.readBoolean(); - } - - @Override - public void detectAndSendChanges() { - super.detectAndSendChanges(); - if (predicate != null) { - if (isVisible != predicate.getAsBoolean()) { - isVisible = !isVisible; - writeUpdateInfo(1, buf -> buf.writeBoolean(isVisible)); - } - } - } - - @Override - @OnlyIn(Dist.CLIENT) - public void readUpdateInfo(int id, FriendlyByteBuf buffer) { - if (id == 1) { - isVisible = buffer.readBoolean(); - } else { - super.readUpdateInfo(id, buffer); - } - } - - @Override - @OnlyIn(Dist.CLIENT) - public void drawInBackground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - if (isVisible) { - super.drawInBackground(graphics, mouseX, mouseY, partialTicks); - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/ScrollablePhantomFluidWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/ScrollablePhantomFluidWidget.java deleted file mode 100644 index 93f621d2aaa..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/ScrollablePhantomFluidWidget.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget; - -import com.gregtechceu.gtceu.api.transfer.fluid.IFluidHandlerModifiable; -import com.gregtechceu.gtceu.utils.GTUtil; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fluids.FluidStack; - -import org.jetbrains.annotations.Nullable; - -import java.util.function.Consumer; -import java.util.function.Supplier; - -public class ScrollablePhantomFluidWidget extends PhantomFluidWidget { - - private static final int SCROLL_ACTION_ID = 0x0001_0001; - - public ScrollablePhantomFluidWidget(@Nullable IFluidHandlerModifiable fluidTank, int tank, int x, int y, int width, - int height, Supplier phantomFluidGetter, - Consumer phantomFluidSetter) { - super(fluidTank, tank, x, y, width, height, phantomFluidGetter, phantomFluidSetter); - } - - @Override - @OnlyIn(Dist.CLIENT) - public boolean mouseWheelMove(double mouseX, double mouseY, double wheelDelta) { - if (!isMouseOverElement(mouseX, mouseY)) - return false; - - var delta = getModifiedChangeAmount((wheelDelta > 0) ? 1 : -1); - writeClientAction(SCROLL_ACTION_ID, buf -> buf.writeInt(delta)); - - return true; - } - - private int getModifiedChangeAmount(int amount) { - if (GTUtil.isShiftDown()) - amount *= 10; - - if (GTUtil.isCtrlDown()) - amount *= 100; - - if (!GTUtil.isAltDown()) - amount *= 1000; - - return amount; - } - - @Override - public void handleClientAction(int id, FriendlyByteBuf buffer) { - switch (id) { - case SCROLL_ACTION_ID -> handleScrollAction(buffer.readInt()); - default -> super.handleClientAction(id, buffer); - } - - detectAndSendChanges(); - } - - private void handleScrollAction(int delta) { - IFluidHandlerModifiable fluidTank = (IFluidHandlerModifiable) getFluidTank(); - if (fluidTank == null) - return; - - FluidStack fluid = fluidTank.getFluidInTank(tank); - if (fluid.isEmpty()) - return; - - if (fluid.isEmpty()) - return; - - fluid.setAmount(Math.min(Math.max(fluid.getAmount() + delta, 0), fluidTank.getTankCapacity(tank))); - if (fluid.getAmount() <= 0L) { - fluidTank.setFluidInTank(tank, FluidStack.EMPTY); - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/SlotWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/SlotWidget.java index ef7f6b23990..52b383b7ccc 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/SlotWidget.java +++ b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/SlotWidget.java @@ -1,10 +1,10 @@ package com.gregtechceu.gtceu.api.gui.widget; import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.integration.xei.entry.item.ItemEntryList; -import com.gregtechceu.gtceu.integration.xei.entry.item.ItemStackList; -import com.gregtechceu.gtceu.integration.xei.entry.item.ItemTagList; -import com.gregtechceu.gtceu.integration.xei.handlers.item.CycleItemEntryHandler; +import com.gregtechceu.gtceu.integration.recipeviewer.entry.item.ItemEntryList; +import com.gregtechceu.gtceu.integration.recipeviewer.entry.item.ItemStackList; +import com.gregtechceu.gtceu.integration.recipeviewer.entry.item.ItemTagList; +import com.gregtechceu.gtceu.integration.recipeviewer.handlers.item.CycleItemEntryHandler; import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; import com.lowdragmc.lowdraglib.gui.editor.configurator.ConfiguratorGroup; diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/TankWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/TankWidget.java index 5230f99742d..2e474162c67 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/TankWidget.java +++ b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/TankWidget.java @@ -4,10 +4,10 @@ import com.gregtechceu.gtceu.api.machine.trait.NotifiableFluidTank; import com.gregtechceu.gtceu.api.transfer.fluid.IFluidHandlerModifiable; import com.gregtechceu.gtceu.client.TooltipsHandler; -import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidEntryList; -import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidStackList; -import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidTagList; -import com.gregtechceu.gtceu.integration.xei.handlers.fluid.CycleFluidEntryHandler; +import com.gregtechceu.gtceu.integration.recipeviewer.entry.fluid.FluidEntryList; +import com.gregtechceu.gtceu.integration.recipeviewer.entry.fluid.FluidStackList; +import com.gregtechceu.gtceu.integration.recipeviewer.entry.fluid.FluidTagList; +import com.gregtechceu.gtceu.integration.recipeviewer.handlers.fluid.CycleFluidEntryHandler; import com.gregtechceu.gtceu.utils.FormattingUtil; import com.gregtechceu.gtceu.utils.GTUtil; diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/ToggleButtonWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/ToggleButtonWidget.java deleted file mode 100644 index 716725601e1..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/ToggleButtonWidget.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.data.lang.LangHandler; - -import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; -import com.lowdragmc.lowdraglib.gui.widget.SwitchWidget; - -import it.unimi.dsi.fastutil.booleans.BooleanConsumer; - -import java.util.List; -import java.util.function.BooleanSupplier; - -public class ToggleButtonWidget extends SwitchWidget { - - private final IGuiTexture texture; - private String tooltipText; - private boolean isMultiLang; - - public ToggleButtonWidget(int xPosition, int yPosition, int width, int height, BooleanSupplier isPressedCondition, - BooleanConsumer setPressedExecutor) { - this(xPosition, yPosition, width, height, GuiTextures.VANILLA_BUTTON, isPressedCondition, setPressedExecutor); - } - - public ToggleButtonWidget(int xPosition, int yPosition, int width, int height, IGuiTexture buttonTexture, - BooleanSupplier isPressedCondition, BooleanConsumer setPressedExecutor) { - super(xPosition, yPosition, width, height, null); - texture = buttonTexture; - if (buttonTexture instanceof ResourceTexture resourceTexture) { - setTexture(resourceTexture.getSubTexture(0, 0, 1, 0.5), resourceTexture.getSubTexture(0, 0.5, 1, 0.5)); - } else { - setTexture(buttonTexture, buttonTexture); - } - - setSupplier(isPressedCondition::getAsBoolean); - setOnPressCallback((cd, bool) -> { - setPressedExecutor.accept(bool.booleanValue()); - this.updateHoverTooltips(); - }); - } - - public ToggleButtonWidget setShouldUseBaseBackground() { - if (texture != null) { - setTexture( - new GuiTextureGroup(GuiTextures.TOGGLE_BUTTON_BACK.getSubTexture(0, 0, 1, 0.5), texture), - new GuiTextureGroup(GuiTextures.TOGGLE_BUTTON_BACK.getSubTexture(0, 0.5, 1, 0.5), texture)); - } - return this; - } - - public ToggleButtonWidget setTooltipText(String tooltipText) { - this.tooltipText = tooltipText; - updateHoverTooltips(); - return this; - } - - public ToggleButtonWidget isMultiLang() { - isMultiLang = true; - updateHoverTooltips(); - return this; - } - - protected void updateHoverTooltips() { - if (tooltipText != null) { - if (!isMultiLang) { - setHoverTooltips(tooltipText + (isPressed ? ".enabled" : ".disabled")); - } else { - setHoverTooltips( - List.copyOf(LangHandler.getMultiLang(tooltipText + (isPressed ? ".enabled" : ".disabled")))); - } - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/directional/CombinedDirectionalConfigurator.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/directional/CombinedDirectionalConfigurator.java deleted file mode 100644 index cf281d96a37..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/directional/CombinedDirectionalConfigurator.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget.directional; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.FancyMachineUIWidget; -import com.gregtechceu.gtceu.api.machine.MetaMachine; -import com.gregtechceu.gtceu.utils.GTUtil; - -import com.lowdragmc.lowdraglib.client.scene.ISceneBlockRenderHook; -import com.lowdragmc.lowdraglib.client.scene.WorldSceneRenderer; -import com.lowdragmc.lowdraglib.gui.editor.ColorPattern; -import com.lowdragmc.lowdraglib.gui.util.ClickData; -import com.lowdragmc.lowdraglib.gui.widget.ImageWidget; -import com.lowdragmc.lowdraglib.gui.widget.SceneWidget; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.utils.BlockPosFace; -import com.lowdragmc.lowdraglib.utils.Position; -import com.lowdragmc.lowdraglib.utils.Size; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -import javax.annotation.ParametersAreNonnullByDefault; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class CombinedDirectionalConfigurator extends WidgetGroup { - - protected final static int MOUSE_CLICK_CLIENT_ACTION_ID = 0x0001_0001; - protected final static int UPDATE_UI_ID = 0x0001_0002; - - protected final IDirectionalConfigHandler[] configHandlers; - protected final int width, height; - private final FancyMachineUIWidget machineUI; - private final MetaMachine machine; - - protected SceneWidget sceneWidget; - protected ImageWidget imageWidget; - - protected @Nullable BlockPos selectedPos; - protected @Nullable Direction selectedSide; - - public CombinedDirectionalConfigurator(FancyMachineUIWidget machineUI, IDirectionalConfigHandler[] configHandlers, - MetaMachine machine, int width, int height) { - super(0, 0, width, height); - this.width = width; - this.height = height; - - this.machineUI = machineUI; - this.configHandlers = configHandlers; - this.machine = machine; - } - - @Override - public void initWidget() { - super.initWidget(); - - addWidget(imageWidget = new ImageWidget(0, 0, width, height, GuiTextures.BACKGROUND_INVERSE)); - addWidget(sceneWidget = createSceneWidget()); - - for (IDirectionalConfigHandler configHandler : configHandlers) { - configHandler.addAdditionalUIElements(this); - } - - addConfigWidgets(sceneWidget); - } - - private SceneWidget createSceneWidget() { - var pos = this.machine.getBlockPos(); - - SceneWidget sceneWidget = new SceneWidget(4, 4, width - 8, height - 8, this.machine.getLevel()) - .setRenderedCore(List.of(pos), null) - .setRenderSelect(false) - .setOnSelected(this::onSideSelected); - - if (isRemote()) { - sceneWidget.getRenderer().addRenderedBlocks( - List.of(pos.above(), pos.below(), pos.north(), pos.south(), pos.east(), pos.west()), - new ISceneBlockRenderHook() { - - @Override - @OnlyIn(Dist.CLIENT) - public void apply(boolean isTESR, RenderType layer) { - RenderSystem.enableBlend(); - RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE); - } - }); - - sceneWidget.getRenderer().setAfterWorldRender(this::renderOverlays); - - var playerRotation = gui.entityPlayer.getRotationVector(); - sceneWidget.setCameraYawAndPitch(playerRotation.x, playerRotation.y - 90); - } - sceneWidget.setBackground(ColorPattern.BLACK.rectTexture()); - return sceneWidget; - } - - private void renderOverlays(WorldSceneRenderer renderer) { - sceneWidget.renderBlockOverLay(renderer); - - for (Direction face : GTUtil.DIRECTIONS) { - for (IDirectionalConfigHandler configHandler : configHandlers) { - configHandler.renderOverlay(sceneWidget, new BlockPosFace(machine.getBlockPos(), face)); - } - } - } - - private void addConfigWidgets(SceneWidget sceneWidget) { - int yOffsetLeft = 0, yOffsetRight = 0; - - for (IDirectionalConfigHandler configHandler : configHandlers) { - Widget widget = configHandler.getSideSelectorWidget(sceneWidget, machineUI); - - if (widget == null) - continue; - - final Size widgetSize = widget.getSize(); - switch (configHandler.getScreenSide()) { - case LEFT -> { - widget.setSelfPosition(new Position(6, height - 6 - widgetSize.height - yOffsetLeft)); - yOffsetLeft += widgetSize.height + 3; - } - case RIGHT -> { - widget.setSelfPosition( - new Position(width - widgetSize.width - 6, height - 6 - widgetSize.height - yOffsetRight)); - yOffsetRight += widgetSize.height + 3; - } - } - - this.addWidget(widget); - } - } - - protected void onSideSelected(BlockPos pos, Direction side) { - if (!pos.equals(machine.getBlockPos())) - return; - - if (this.selectedSide == side) - return; // No need to do anything if the same side is already selected - - this.selectedSide = side; - - for (IDirectionalConfigHandler configWidget : this.configHandlers) { - configWidget.onSideSelected(pos, side); - } - } - - @Override - @OnlyIn(Dist.CLIENT) - public boolean mouseClicked(double mouseX, double mouseY, int button) { - var lastSide = this.selectedSide; - - var result = super.mouseClicked(mouseX, mouseY, button); - - if (isMouseOverElement(mouseX, mouseY) && this.selectedSide == lastSide && this.selectedSide != null) { - var hover = sceneWidget.getHoverPosFace(); - - if (hover != null && hover.pos.equals(machine.getBlockPos()) && hover.facing == this.selectedSide) { - var cd = new ClickData(); - writeClientAction(MOUSE_CLICK_CLIENT_ACTION_ID, buf -> { - cd.writeToBuf(buf); - buf.writeByte(this.selectedSide.ordinal()); - }); - } - } - - return result; - } - - @Override - public void handleClientAction(int id, FriendlyByteBuf buf) { - if (id != MOUSE_CLICK_CLIENT_ACTION_ID) { - super.handleClientAction(id, buf); - return; - } - - var clickData = ClickData.readFromBuf(buf); - var side = GTUtil.DIRECTIONS[buf.readByte()]; - - for (IDirectionalConfigHandler configHandler : configHandlers) { - configHandler.handleClick(clickData, side); - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/directional/IDirectionalConfigHandler.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/directional/IDirectionalConfigHandler.java deleted file mode 100644 index 024b4465873..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/directional/IDirectionalConfigHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget.directional; - -import com.gregtechceu.gtceu.api.gui.fancy.FancyMachineUIWidget; - -import com.lowdragmc.lowdraglib.gui.util.ClickData; -import com.lowdragmc.lowdraglib.gui.widget.SceneWidget; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.utils.BlockPosFace; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public interface IDirectionalConfigHandler { - - /** - * Returns the buttons to display inside the side selector - */ - Widget getSideSelectorWidget(SceneWidget scene, FancyMachineUIWidget machineUI); - - /** - * Called whenever a side is selected in the side selector GUI - */ - void onSideSelected(BlockPos pos, Direction side); - - /** - * Determines which side of the screen the UI element should be placed on. - */ - ScreenSide getScreenSide(); - - enum ScreenSide { - LEFT, - RIGHT, - } - - default void handleClick(ClickData cd, Direction direction) { - // Do nothing by default - } - - @OnlyIn(Dist.CLIENT) - default void renderOverlay(SceneWidget sceneWidget, BlockPosFace blockPosFace) { - // Do nothing by default - } - - default void addAdditionalUIElements(WidgetGroup parent) { - // Do nothing by default - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/directional/handlers/AutoOutputFluidConfigHandler.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/directional/handlers/AutoOutputFluidConfigHandler.java deleted file mode 100644 index d291f19880c..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/directional/handlers/AutoOutputFluidConfigHandler.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget.directional.handlers; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.FancyMachineUIWidget; -import com.gregtechceu.gtceu.api.gui.widget.ToggleButtonWidget; -import com.gregtechceu.gtceu.api.gui.widget.directional.IDirectionalConfigHandler; -import com.gregtechceu.gtceu.common.machine.trait.AutoOutputTrait; -import com.gregtechceu.gtceu.data.lang.LangHandler; - -import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.util.ClickData; -import com.lowdragmc.lowdraglib.gui.widget.*; -import com.lowdragmc.lowdraglib.utils.BlockPosFace; -import com.lowdragmc.lowdraglib.utils.Position; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.chat.Component; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import com.mojang.blaze3d.vertex.PoseStack; - -import javax.annotation.ParametersAreNonnullByDefault; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class AutoOutputFluidConfigHandler implements IDirectionalConfigHandler { - - private static final IGuiTexture TEXTURE_OFF = new GuiTextureGroup( - GuiTextures.VANILLA_BUTTON, - GuiTextures.IO_CONFIG_FLUID_MODES_BUTTON.getSubTexture(0, 0, 1, 1 / 3f)); - private static final IGuiTexture TEXTURE_OUTPUT = new GuiTextureGroup( - GuiTextures.VANILLA_BUTTON, - GuiTextures.IO_CONFIG_FLUID_MODES_BUTTON.getSubTexture(0, 1 / 3f, 1, 1 / 3f)); - private static final IGuiTexture TEXTURE_AUTO = new GuiTextureGroup( - GuiTextures.VANILLA_BUTTON, - GuiTextures.IO_CONFIG_FLUID_MODES_BUTTON.getSubTexture(0, 2 / 3f, 1, 1 / 3f)); - - private final AutoOutputTrait trait; - private Direction side; - private ButtonWidget ioModeButton; - - public AutoOutputFluidConfigHandler(AutoOutputTrait trait) { - this.trait = trait; - } - - @Override - public Widget getSideSelectorWidget(SceneWidget scene, FancyMachineUIWidget machineUI) { - WidgetGroup group = new WidgetGroup(0, 0, (18 * 2) + 1, 18); - - group.addWidget(ioModeButton = new ButtonWidget(0, 0, 18, 18, this::onIOModePressed) { - - @Override - public void updateScreen() { - super.updateScreen(); - if (side == null) { - setButtonTexture(TEXTURE_OFF); - setHoverTooltips(LangHandler.getMultiLang("gtceu.gui.fluid_auto_output.unselected") - .toArray(Component[]::new)); - } else if (trait.getFluidOutputDirection() == side) { - if (trait.isAutoOutputFluids()) { - setButtonTexture(TEXTURE_AUTO); - setHoverTooltips("gtceu.gui.fluid_auto_output.enabled"); - } else { - setButtonTexture(TEXTURE_OUTPUT); - setHoverTooltips("gtceu.gui.fluid_auto_output.disabled"); - } - } else { - setButtonTexture(TEXTURE_OFF); - setHoverTooltips(LangHandler.getMultiLang("gtceu.gui.fluid_auto_output.other_direction") - .toArray(Component[]::new)); - } - } - }); - - group.addWidget(new ToggleButtonWidget( - 19, 0, 18, 18, GuiTextures.BUTTON_FLUID_OUTPUT, - trait::allowsFluidInputFromOutputSide, trait::setAllowFluidInputFromOutputSide) - .setShouldUseBaseBackground().setTooltipText("gtceu.gui.fluid_auto_output.allow_input")); - - return group; - } - - private void onIOModePressed(ClickData cd) { - if (this.side == null) - return; - - if (trait.getFluidOutputDirection() == this.side) { - trait.setAllowAutoOutputFluids(!trait.isAutoOutputFluids()); - } else { - trait.setAllowAutoOutputFluids(false); - trait.setFluidOutputDirection(this.side); - } - } - - @Override - public void onSideSelected(BlockPos pos, Direction side) { - this.side = side; - } - - @Override - public ScreenSide getScreenSide() { - return ScreenSide.LEFT; - } - - @Override - public void handleClick(ClickData cd, Direction direction) { - if (!canHandleClick(cd) || !trait.supportsAutoOutputFluids()) - return; - - if (trait.getFluidOutputDirection() != side) { - trait.setFluidOutputDirection(side); - trait.setAllowAutoOutputFluids(false); - } else { - trait.setAllowAutoOutputFluids(!trait.isAutoOutputFluids()); - } - } - - @SuppressWarnings("RedundantIfStatement") // Cleaner code this way - private boolean canHandleClick(ClickData cd) { - if (cd.button == 1) - return true; - - return false; - } - - @Override - @OnlyIn(Dist.CLIENT) - public void renderOverlay(SceneWidget sceneWidget, BlockPosFace blockPosFace) { - if (trait.getFluidOutputDirection() != blockPosFace.facing) - return; - - sceneWidget.drawFacingBorder(new PoseStack(), blockPosFace, - trait.isAutoOutputFluids() ? 0xff00b4ff : 0x8f00b4ff, 2); - } - - @Override - public void addAdditionalUIElements(WidgetGroup parent) { - LabelWidget text = new LabelWidget(4, 4, "gtceu.gui.auto_output.name") { - - @Override - public boolean isVisible() { - return trait.isAutoOutputFluids() && trait.getFluidOutputDirection() != null; - } - }; - - text.setSelfPosition(new Position(parent.getSize().width - 4 - text.getSize().width, 4)); - - text.setTextColor(0xff00b4ff).setDropShadow(false); - parent.addWidget(text); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/directional/handlers/AutoOutputItemConfigHandler.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/directional/handlers/AutoOutputItemConfigHandler.java deleted file mode 100644 index b2e9bdc19b2..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/directional/handlers/AutoOutputItemConfigHandler.java +++ /dev/null @@ -1,153 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget.directional.handlers; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.FancyMachineUIWidget; -import com.gregtechceu.gtceu.api.gui.widget.ToggleButtonWidget; -import com.gregtechceu.gtceu.api.gui.widget.directional.IDirectionalConfigHandler; -import com.gregtechceu.gtceu.common.machine.trait.AutoOutputTrait; -import com.gregtechceu.gtceu.data.lang.LangHandler; - -import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.util.ClickData; -import com.lowdragmc.lowdraglib.gui.widget.*; -import com.lowdragmc.lowdraglib.utils.BlockPosFace; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.chat.Component; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import com.mojang.blaze3d.vertex.PoseStack; - -import javax.annotation.ParametersAreNonnullByDefault; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class AutoOutputItemConfigHandler implements IDirectionalConfigHandler { - - private static final IGuiTexture TEXTURE_OFF = new GuiTextureGroup( - GuiTextures.VANILLA_BUTTON, - GuiTextures.IO_CONFIG_ITEM_MODES_BUTTON.getSubTexture(0, 0, 1, 1 / 3f)); - private static final IGuiTexture TEXTURE_OUTPUT = new GuiTextureGroup( - GuiTextures.VANILLA_BUTTON, - GuiTextures.IO_CONFIG_ITEM_MODES_BUTTON.getSubTexture(0, 1 / 3f, 1, 1 / 3f)); - private static final IGuiTexture TEXTURE_AUTO = new GuiTextureGroup( - GuiTextures.VANILLA_BUTTON, - GuiTextures.IO_CONFIG_ITEM_MODES_BUTTON.getSubTexture(0, 2 / 3f, 1, 1 / 3f)); - - private final AutoOutputTrait trait; - private Direction side; - private ButtonWidget ioModeButton; - - public AutoOutputItemConfigHandler(AutoOutputTrait trait) { - this.trait = trait; - } - - @Override - public Widget getSideSelectorWidget(SceneWidget scene, FancyMachineUIWidget machineUI) { - WidgetGroup group = new WidgetGroup(0, 0, (18 * 2) + 1, 18); - - group.addWidget(ioModeButton = new ButtonWidget(0, 0, 18, 18, this::onIOModePressed) { - - @Override - public void updateScreen() { - super.updateScreen(); - - if (side == null) { - setButtonTexture(TEXTURE_OFF); - setHoverTooltips(LangHandler.getMultiLang("gtceu.gui.item_auto_output.unselected") - .toArray(Component[]::new)); - } else if (trait.getItemOutputDirection() == side) { - if (trait.isAutoOutputItems()) { - setButtonTexture(TEXTURE_AUTO); - setHoverTooltips("gtceu.gui.item_auto_output.enabled"); - } else { - setButtonTexture(TEXTURE_OUTPUT); - setHoverTooltips("gtceu.gui.item_auto_output.disabled"); - } - } else { - setButtonTexture(TEXTURE_OFF); - setHoverTooltips(LangHandler.getMultiLang("gtceu.gui.item_auto_output.other_direction") - .toArray(Component[]::new)); - } - } - }); - - group.addWidget(new ToggleButtonWidget( - 19, 0, 18, 18, GuiTextures.BUTTON_ITEM_OUTPUT, - trait::allowsItemInputFromOutputSide, trait::setAllowItemInputFromOutputSide) - .setShouldUseBaseBackground().setTooltipText("gtceu.gui.item_auto_output.allow_input")); - - return group; - } - - private void onIOModePressed(ClickData cd) { - if (this.side == null) - return; - - if (trait.getItemOutputDirection() == this.side) { - trait.setAllowAutoOutputItems(!trait.isAutoOutputItems()); - } else { - trait.setAllowAutoOutputItems(false); - trait.setItemOutputDirection(this.side); - } - } - - @Override - public void onSideSelected(BlockPos pos, Direction side) { - this.side = side; - } - - @Override - public ScreenSide getScreenSide() { - return ScreenSide.LEFT; - } - - @Override - public void handleClick(ClickData cd, Direction direction) { - if (!canHandleClick(cd) || !trait.supportsAutoOutputItems()) - return; - - if (trait.getItemOutputDirection() != side) { - trait.setItemOutputDirection(side); - trait.setAllowAutoOutputItems(false); - } else { - trait.setAllowAutoOutputItems(!trait.isAutoOutputItems()); - } - } - - @SuppressWarnings("RedundantIfStatement") // Cleaner code this way - private boolean canHandleClick(ClickData cd) { - if (cd.button == 0) - return true; - - return false; - } - - @Override - @OnlyIn(Dist.CLIENT) - public void renderOverlay(SceneWidget sceneWidget, BlockPosFace blockPosFace) { - if (trait.getItemOutputDirection() != blockPosFace.facing) - return; - - sceneWidget.drawFacingBorder(new PoseStack(), blockPosFace, - trait.isAutoOutputItems() ? 0xffff6e0f : 0x8fff6e0f, 1); - } - - @Override - public void addAdditionalUIElements(WidgetGroup parent) { - LabelWidget text = new LabelWidget(4, 4, "gtceu.gui.auto_output.name") { - - @Override - public boolean isVisible() { - return trait.isAutoOutputItems() && trait.getItemOutputDirection() != null; - } - }; - - text.setTextColor(0xffff6e0f).setDropShadow(false); - parent.addWidget(text); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/directional/handlers/CoverableConfigHandler.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/directional/handlers/CoverableConfigHandler.java deleted file mode 100644 index d20d95c0003..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/directional/handlers/CoverableConfigHandler.java +++ /dev/null @@ -1,218 +0,0 @@ -package com.gregtechceu.gtceu.api.gui.widget.directional.handlers; - -import com.gregtechceu.gtceu.api.capability.ICoverable; -import com.gregtechceu.gtceu.api.cover.CoverBehavior; -import com.gregtechceu.gtceu.api.cover.IUICover; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.ConfiguratorPanel; -import com.gregtechceu.gtceu.api.gui.fancy.FancyMachineUIWidget; -import com.gregtechceu.gtceu.api.gui.widget.CoverConfigurator; -import com.gregtechceu.gtceu.api.gui.widget.PredicatedButtonWidget; -import com.gregtechceu.gtceu.api.gui.widget.SlotWidget; -import com.gregtechceu.gtceu.api.gui.widget.directional.IDirectionalConfigHandler; -import com.gregtechceu.gtceu.api.item.IComponentItem; -import com.gregtechceu.gtceu.api.item.component.IItemComponent; -import com.gregtechceu.gtceu.api.transfer.item.CustomItemStackHandler; -import com.gregtechceu.gtceu.common.item.behavior.CoverPlaceBehavior; - -import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.util.ClickData; -import com.lowdragmc.lowdraglib.gui.widget.SceneWidget; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.utils.Position; -import com.lowdragmc.lowdraglib.utils.Size; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.item.ItemStack; - -import javax.annotation.ParametersAreNonnullByDefault; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class CoverableConfigHandler implements IDirectionalConfigHandler { - - private static final IGuiTexture CONFIG_BTN_TEXTURE = new GuiTextureGroup(GuiTextures.IO_CONFIG_COVER_SETTINGS); - - private final ICoverable machine; - private CustomItemStackHandler handler; - private Direction side; - - private ConfiguratorPanel panel; - private ConfiguratorPanel.FloatingTab coverConfigurator; - - private SlotWidget slotWidget; - private CoverBehavior coverBehavior; - - public CoverableConfigHandler(ICoverable machine) { - this.machine = machine; - this.handler = createItemStackHandler(); - } - - private CustomItemStackHandler createItemStackHandler() { - var handler = new CustomItemStackHandler(1) { - - @Override - public int getSlotLimit(int slot) { - return 1; - } - }; - - handler.setFilter(itemStack -> { - if (itemStack.isEmpty()) return true; - if (this.side == null) return false; - return CoverPlaceBehavior.isCoverBehaviorItem(itemStack, () -> false, - coverDef -> ICoverable.canPlaceCover(coverDef, this.machine)); - }); - - return handler; - } - - @Override - public Widget getSideSelectorWidget(SceneWidget scene, FancyMachineUIWidget machineUI) { - WidgetGroup group = new WidgetGroup(0, 0, (18 * 2) + 1, 18); - this.panel = machineUI.getConfiguratorPanel(); - - group.addWidget(slotWidget = new SlotWidget(handler, 0, 19, 0) { - - @Override - public boolean canPutStack(ItemStack stack) { - return super.canPutStack(stack) && CoverPlaceBehavior.isCoverBehaviorItem(stack, () -> false, - def -> def.createCoverBehavior(machine, side).canAttach()); - } - } - .setChangeListener(this::coverItemChanged) - .setBackgroundTexture(new GuiTextureGroup(GuiTextures.SLOT, GuiTextures.IO_CONFIG_COVER_SLOT_OVERLAY))); - group.addWidget(new PredicatedButtonWidget(0, 0, 18, 18, CONFIG_BTN_TEXTURE, this::toggleConfigTab, - () -> side != null && coverBehavior != null && machine.getCoverAtSide(side) instanceof IUICover)); - - checkCoverBehaviour(); - - return group; - } - - // FIXME: This gets called twice in a single tick, causing two covers to exist simultaneously - private void coverItemChanged() { - closeConfigTab(); - - if (!(panel.getGui().entityPlayer instanceof ServerPlayer serverPlayer) || side == null) - return; - - var item = handler.getStackInSlot(0); - if (machine.getCoverAtSide(side) != null) { - machine.removeCover(false, side, serverPlayer); - } - - if (!item.isEmpty() && machine.getCoverAtSide(side) == null) { - if (item.getItem() instanceof IComponentItem componentItem) { - for (IItemComponent component : componentItem.getComponents()) { - if (component instanceof CoverPlaceBehavior placeBehavior) { - machine.placeCoverOnSide(side, item, placeBehavior.coverDefinition(), serverPlayer); - break; - } - } - } - } - - checkCoverBehaviour(); - } - - @Override - public void onSideSelected(BlockPos pos, Direction side) { - this.side = side; - checkCoverBehaviour(); - closeConfigTab(); - } - - private void updateWidgetVisibility() { - var sideSelected = this.side != null; - slotWidget.setVisible(sideSelected); - slotWidget.setActive(sideSelected); - } - - public void checkCoverBehaviour() { - if (side == null) - return; - - var coverBehaviour = machine.getCoverAtSide(side); - if (coverBehaviour != this.coverBehavior) { - this.coverBehavior = coverBehaviour; - - var attachItem = coverBehaviour == null ? ItemStack.EMPTY : coverBehaviour.getAttachItem(); - handler.setStackInSlot(0, attachItem); - handler.onContentsChanged(0); - } - - updateWidgetVisibility(); - } - - private void toggleConfigTab(ClickData cd) { - if (this.coverConfigurator == null) - openConfigTab(); - else - closeConfigTab(); - } - - private void openConfigTab() { - CoverConfigurator configurator = new CoverConfigurator(this.machine, this.side, this.coverBehavior) { - - @Override - public Component getTitle() { - // Uses the widget's own title - return Component.empty(); - } - - @Override - public IGuiTexture getIcon() { - return GuiTextures.CLOSE_ICON; - } - - @Override - public Widget createConfigurator() { - WidgetGroup group = new WidgetGroup(new Position(0, 0)); - - if (side == null || !(coverable.getCoverAtSide(side) instanceof IUICover iuiCover)) - return group; - - Widget coverConfigurator = iuiCover.createUIWidget(); - coverConfigurator.addSelfPosition(-1, -20); - - group.addWidget(coverConfigurator); - group.setSize(new Size( - Math.max(120, coverConfigurator.getSize().width), - Math.max(80, coverConfigurator.getSize().height - 20))); - - return group; - } - }; - - this.coverConfigurator = this.panel.createFloatingTab(configurator); - this.coverConfigurator.setGui(this.panel.getGui()); - this.panel.addWidget(this.coverConfigurator); - this.panel.expandTab(this.coverConfigurator); - - coverConfigurator.onClose(() -> { - if (coverConfigurator != null) { - this.panel.removeWidget(this.coverConfigurator); - } - - this.coverConfigurator = null; - }); - } - - private void closeConfigTab() { - if (this.coverConfigurator != null) { - this.panel.collapseTab(); - } - } - - @Override - public ScreenSide getScreenSide() { - return ScreenSide.RIGHT; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/ComponentItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/ComponentItem.java index b45213e753e..682e2965d35 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/ComponentItem.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/ComponentItem.java @@ -1,12 +1,12 @@ package com.gregtechceu.gtceu.api.item; +import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; import com.gregtechceu.gtceu.api.capability.IElectricItem; import com.gregtechceu.gtceu.api.item.capability.ElectricItem; import com.gregtechceu.gtceu.api.item.component.*; +import com.gregtechceu.gtceu.api.mui.IItemUIHolder; -import com.lowdragmc.lowdraglib.client.renderer.IItemRendererProvider; -import com.lowdragmc.lowdraglib.client.renderer.IRenderer; import com.lowdragmc.lowdraglib.gui.factory.HeldItemUIFactory; import com.lowdragmc.lowdraglib.gui.modular.ModularUI; @@ -36,6 +36,10 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelReader; +import brachy.modularui.factory.PlayerInventoryGuiData; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.sync.PanelSyncManager; import com.google.common.collect.Multimap; import lombok.Getter; import org.jetbrains.annotations.Nullable; @@ -49,7 +53,8 @@ @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault public class ComponentItem extends Item - implements HeldItemUIFactory.IHeldItemUIHolder, IItemRendererProvider, IComponentItem { + implements HeldItemUIFactory.IHeldItemUIHolder, IComponentItem, + IItemUIHolder { protected int burnTime = -1; @@ -305,17 +310,6 @@ public ModularUI createUI(Player entityPlayer, HeldItemUIFactory.HeldItemHolder return null; } - @Nullable - @Override - public IRenderer getRenderer(ItemStack stack) { - for (IItemComponent component : components) { - if (component instanceof ICustomRenderer customRenderer) { - return customRenderer.getRenderer(); - } - } - return null; - } - @Override public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) { for (IItemComponent component : components) { @@ -443,4 +437,24 @@ public ItemStack getInfiniteChargedStack() { electricItem.setInfiniteCharge(true); return itemStack; } + + @Override + public @Nullable ModularPanel buildUI(PlayerInventoryGuiData data, PanelSyncManager syncManager, + UISettings settings) { + for (IItemComponent component : getComponents()) { + if (component instanceof IItemUIHolder uiHolder) { + return uiHolder.buildUI(data, syncManager, settings); + } + } + GTCEu.LOGGER.error("Tried to get UI of {} item when it does not have one!", data.getUsedItemStack()); + return null; + } + + @Override + public boolean shouldOpenUI() { + for (IItemComponent component : getComponents()) { + if (component instanceof IItemUIHolder holder) return holder.shouldOpenUI(); + } + return false; + } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/IGTTool.java b/src/main/java/com/gregtechceu/gtceu/api/item/IGTTool.java index 57dff0347c9..731db0e7c44 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/IGTTool.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/IGTTool.java @@ -19,15 +19,13 @@ import com.gregtechceu.gtceu.api.item.tool.aoe.AoESymmetrical; import com.gregtechceu.gtceu.api.item.tool.behavior.IToolBehavior; import com.gregtechceu.gtceu.api.item.tool.behavior.IToolUIBehavior; +import com.gregtechceu.gtceu.api.mui.GTGuiScreen; import com.gregtechceu.gtceu.api.sound.SoundEntry; import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.data.recipe.VanillaRecipeHelper; import com.gregtechceu.gtceu.utils.FormattingUtil; import com.gregtechceu.gtceu.utils.GTUtil; -import com.lowdragmc.lowdraglib.gui.factory.HeldItemUIFactory; -import com.lowdragmc.lowdraglib.gui.modular.ModularUI; - import net.minecraft.Util; import net.minecraft.client.color.item.ItemColor; import net.minecraft.core.BlockPos; @@ -69,6 +67,12 @@ import net.minecraftforge.common.extensions.IForgeItem; import net.minecraftforge.common.util.LazyOptional; +import brachy.modularui.api.IUIHolder; +import brachy.modularui.factory.PlayerInventoryGuiData; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.ModularScreen; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.sync.PanelSyncManager; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap; @@ -83,7 +87,7 @@ import static net.minecraft.world.item.Item.BASE_ATTACK_DAMAGE_UUID; import static net.minecraft.world.item.Item.BASE_ATTACK_SPEED_UUID; -public interface IGTTool extends HeldItemUIFactory.IHeldItemUIHolder, ItemLike, IForgeItem { +public interface IGTTool extends IUIHolder>, ItemLike, IForgeItem { GTToolType getToolType(); @@ -878,14 +882,21 @@ default void playSound(Player player) { } @Override - default ModularUI createUI(Player player, HeldItemUIFactory.HeldItemHolder holder) { + @OnlyIn(Dist.CLIENT) + default ModularScreen createScreen(PlayerInventoryGuiData data, ModularPanel mainPanel) { + return new GTGuiScreen(mainPanel); + } + + @Override + default ModularPanel buildUI(PlayerInventoryGuiData data, PanelSyncManager syncManager, UISettings settings) { for (var behavior : getToolStats().getBehaviors()) { - if (!(behavior instanceof IToolUIBehavior uiBehavior) || !uiBehavior.openUI(player, holder.getHand())) { + if (!(behavior instanceof IToolUIBehavior uiBehavior) || + !uiBehavior.shouldOpenUI(data.getPlayer(), data.getPlayer().getUsedItemHand())) { continue; } - return uiBehavior.createUI(player, holder); + return uiBehavior.buildUI(data, syncManager, settings); } - return new ModularUI(holder, player); + return null; } default Set getToolClasses(ItemStack stack) { diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/MaterialBlockItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/MaterialBlockItem.java index 6c8addb7469..48f3e90e44c 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/MaterialBlockItem.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/MaterialBlockItem.java @@ -7,10 +7,6 @@ import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; import com.gregtechceu.gtceu.api.data.tag.TagPrefix; -import com.lowdragmc.lowdraglib.client.renderer.IBlockRendererProvider; -import com.lowdragmc.lowdraglib.client.renderer.IItemRendererProvider; -import com.lowdragmc.lowdraglib.client.renderer.IRenderer; - import net.minecraft.client.color.item.ItemColor; import net.minecraft.network.chat.Component; import net.minecraft.world.item.BlockItem; @@ -23,7 +19,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class MaterialBlockItem extends BlockItem implements IItemRendererProvider { +public class MaterialBlockItem extends BlockItem { public final TagPrefix tagPrefix; public final Material material; @@ -50,18 +46,8 @@ public static ItemColor tintColor(Material material) { return (itemStack, index) -> material.getLayerARGB(index); } - @Nullable - @Override - @OnlyIn(Dist.CLIENT) - public IRenderer getRenderer(ItemStack stack) { - if (getBlock() instanceof IBlockRendererProvider provider) { - return provider.getRenderer(getBlock().defaultBlockState()); - } - return null; - } - @Override - public String getDescriptionId() { + public @NotNull String getDescriptionId() { return getBlock().getDescriptionId(); } diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/armor/ArmorComponentItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/armor/ArmorComponentItem.java index 5579e039564..17b18202137 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/armor/ArmorComponentItem.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/armor/ArmorComponentItem.java @@ -24,6 +24,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.*; import lombok.Getter; +import lombok.experimental.Accessors; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNullByDefault; import org.jetbrains.annotations.Nullable; @@ -31,6 +32,7 @@ import java.util.*; import java.util.function.Consumer; +@Accessors(chain = true) @NotNullByDefault public class ArmorComponentItem extends ArmorItem implements IComponentItem { @@ -162,11 +164,11 @@ public void fillItemCategory(CreativeModeTab category, NonNullList it } @Override - public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltipComponents, + public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltips, TooltipFlag isAdvanced) { for (IItemComponent component : components) { if (component instanceof IAddInformation addInformation) { - addInformation.appendHoverText(stack, level, tooltipComponents, isAdvanced); + addInformation.appendHoverText(stack, level, tooltips, isAdvanced); } } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/armor/ArmorLogicSuite.java b/src/main/java/com/gregtechceu/gtceu/api/item/armor/ArmorLogicSuite.java index 8fdf231f41d..794e90cfae0 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/armor/ArmorLogicSuite.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/armor/ArmorLogicSuite.java @@ -87,7 +87,7 @@ public InteractionResultHolder use(Item item, Level level, Player pla @Override public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltipComponents, TooltipFlag isAdvanced) { - addInfo(stack, tooltipComponents); + // addInfo(stack, tooltipComponents); } }); } diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/armor/IArmorLogic.java b/src/main/java/com/gregtechceu/gtceu/api/item/armor/IArmorLogic.java index 3ae5f075c83..181b33d5d38 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/armor/IArmorLogic.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/armor/IArmorLogic.java @@ -1,5 +1,9 @@ package com.gregtechceu.gtceu.api.item.armor; +import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; +import com.gregtechceu.gtceu.api.item.module.AppliedItemModule; +import com.gregtechceu.gtceu.api.item.module.IModularItem; + import net.minecraft.Util; import net.minecraft.client.model.HumanoidModel; import net.minecraft.resources.ResourceLocation; @@ -50,7 +54,13 @@ default boolean canBreakWithDamage(ItemStack stack) { return false; } - default boolean isPPE() { + default boolean isPPE(ItemStack stack) { + IModularItem modularItem = GTCapabilityHelper.getModularItem(stack); + if (modularItem != null) { + for (AppliedItemModule module : modularItem.getAppliedModules()) { + if (module.isPPE()) return true; + } + } return false; } diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/armor/ModularArmorItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/armor/ModularArmorItem.java new file mode 100644 index 00000000000..f63e6da54b1 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/armor/ModularArmorItem.java @@ -0,0 +1,286 @@ +package com.gregtechceu.gtceu.api.item.armor; + +import com.gregtechceu.gtceu.api.item.IComponentItem; +import com.gregtechceu.gtceu.api.item.component.*; +import com.gregtechceu.gtceu.api.item.component.forge.IComponentCapability; + +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.core.NonNullList; +import net.minecraft.network.chat.Component; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.*; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import net.minecraftforge.client.extensions.common.IClientItemExtensions; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; + +import lombok.Getter; +import lombok.experimental.Accessors; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +@Accessors(chain = true) +public class ModularArmorItem extends ArmorItem implements IComponentItem { + + @Getter + protected List components = new ArrayList<>(); + + public ModularArmorItem(ArmorMaterial material, Type type, Properties properties) { + super(material, type, properties); + } + + @Override + public void attachComponents(IItemComponent... components) { + this.components.addAll(Arrays.asList(components)); + for (IItemComponent component : components) { + component.onAttached(this); + } + } + + @Override + public int getMaxDamage(ItemStack stack) { + return super.getMaxDamage(stack); + } + + @Override + public boolean isValidRepairItem(ItemStack stack, ItemStack repairCandidate) { + return false; + } + + @Override + public boolean isEnchantable(ItemStack stack) { + return true; + } + + @Override + public int getEnchantmentValue() { + return 50; + } + + @Override + public void initializeClient(Consumer consumer) { + consumer.accept(new IClientItemExtensions() { + + @Override + public @NotNull HumanoidModel getHumanoidArmorModel(LivingEntity livingEntity, ItemStack itemStack, + EquipmentSlot equipmentSlot, + HumanoidModel original) { + // TODO modifiable armor model + // return armorLogic.getArmorModel(livingEntity, itemStack, equipmentSlot, original); + return original; + } + }); + } + + @Nullable + @Override + public String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlot slot, String type) { + // TODO add custom texture logic (or not? do we need it?) + // return armorLogic.getArmorTexture(stack, entity, slot, type).toString(); + return null; + } + + /////////////////////////////////////////// + ///// ALL component item things /////// + /////////////////////////////////////////// + + public void fillItemCategory(CreativeModeTab category, NonNullList items) { + boolean found = false; + for (IItemComponent component : components) { + if (component instanceof ISubItemHandler subItemHandler) { + subItemHandler.fillItemCategory(this, category, items); + found = true; + } + } + if (found) return; + items.add(new ItemStack(this)); + } + + @Override + public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltips, + TooltipFlag isAdvanced) { + for (IItemComponent component : components) { + if (component instanceof IAddInformation addInformation) { + addInformation.appendHoverText(stack, level, tooltips, isAdvanced); + } + } + } + + @Override + public boolean isBarVisible(ItemStack stack) { + for (IItemComponent component : components) { + if (component instanceof IDurabilityBar durabilityBar) { + return durabilityBar.isBarVisible(stack); + } + } + return super.isBarVisible(stack); + } + + @Override + public int getBarWidth(ItemStack stack) { + for (IItemComponent component : components) { + if (component instanceof IDurabilityBar durabilityBar) { + return durabilityBar.getBarWidth(stack); + } + } + return super.getBarWidth(stack); + } + + @Override + public int getBarColor(ItemStack stack) { + for (IItemComponent component : components) { + if (component instanceof IDurabilityBar durabilityBar) { + return durabilityBar.getBarColor(stack); + } + } + return super.getBarColor(stack); + } + + @Override + public InteractionResult useOn(UseOnContext context) { + for (IItemComponent component : components) { + if (component instanceof IInteractionItem interactionItem) { + var result = interactionItem.useOn(context); + if (result != InteractionResult.PASS) { + return result; + } + } + } + return super.useOn(context); + } + + @Override + public InteractionResultHolder use(Level level, Player player, InteractionHand usedHand) { + for (IItemComponent component : components) { + if (component instanceof IInteractionItem interactionItem) { + var result = interactionItem.use(this, level, player, usedHand); + if (result.getResult() != InteractionResult.PASS) { + return result; + } + } + } + return super.use(level, player, usedHand); + } + + @Override + public ItemStack finishUsingItem(ItemStack stack, Level level, LivingEntity livingEntity) { + for (IItemComponent component : components) { + if (component instanceof IInteractionItem interactionItem) { + stack = interactionItem.finishUsingItem(stack, level, livingEntity); + } + } + return super.finishUsingItem(stack, level, livingEntity); + } + + @Override + public InteractionResult onItemUseFirst(ItemStack itemStack, UseOnContext context) { + for (IItemComponent component : components) { + if (component instanceof IInteractionItem interactionItem) { + var result = interactionItem.onItemUseFirst(itemStack, context); + if (result != InteractionResult.PASS) { + return result; + } + } + } + return InteractionResult.PASS; + } + + @Override + public InteractionResult interactLivingEntity(ItemStack stack, Player player, LivingEntity interactionTarget, + InteractionHand usedHand) { + for (IItemComponent component : components) { + if (component instanceof IInteractionItem interactionItem) { + var result = interactionItem.interactLivingEntity(stack, player, interactionTarget, usedHand); + if (result != InteractionResult.PASS) { + return result; + } + } + } + return InteractionResult.PASS; + } + + @Override + public Component getName(ItemStack stack) { + for (IItemComponent component : components) { + if (component instanceof ICustomDescriptionId customDescriptionId) { + Component name = customDescriptionId.getItemName(stack); + if (name != null) { + return name; + } + } + } + return super.getName(stack); + } + + @Override + public String getDescriptionId(ItemStack stack) { + for (IItemComponent component : components) { + if (component instanceof ICustomDescriptionId customDescriptionId) { + String langId = customDescriptionId.getItemDescriptionId(stack); + if (langId != null) { + return langId; + } + } + } + return super.getDescriptionId(stack); + } + + @Override + public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) { + for (IItemComponent component : components) { + if (component instanceof IItemLifeCycle lifeCycle) { + lifeCycle.inventoryTick(stack, level, entity, slotId, isSelected); + } + } + } + + @Override + public ItemStack getCraftingRemainingItem(ItemStack itemStack) { + for (IItemComponent component : components) { + if (component instanceof IRecipeRemainder recipeRemainder) { + return recipeRemainder.getRecipeRemained(itemStack); + } + } + return super.getCraftingRemainingItem(itemStack); + } + + @Override + public boolean hasCraftingRemainingItem(ItemStack stack) { + for (IItemComponent component : components) { + if (component instanceof IRecipeRemainder recipeRemainder) { + return recipeRemainder.getRecipeRemained(stack) != ItemStack.EMPTY; + } + } + return super.hasCraftingRemainingItem(stack); + } + + // TODO: this was an @Override before, figure out what it did + public LazyOptional getCapability(@NotNull final ItemStack itemStack, @NotNull final Capability cap) { + for (IItemComponent component : components) { + if (component instanceof IComponentCapability componentCapability) { + var value = componentCapability.getCapability(itemStack, cap); + if (value.isPresent()) { + return value; + } + } + } + return LazyOptional.empty(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/capability/ModularItemStack.java b/src/main/java/com/gregtechceu/gtceu/api/item/capability/ModularItemStack.java new file mode 100644 index 00000000000..040efbc9f78 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/capability/ModularItemStack.java @@ -0,0 +1,119 @@ +package com.gregtechceu.gtceu.api.item.capability; + +import com.gregtechceu.gtceu.api.item.module.AppliedItemModule; +import com.gregtechceu.gtceu.api.item.module.IModularItem; +import com.gregtechceu.gtceu.api.item.module.ItemModule; +import com.gregtechceu.gtceu.api.item.module.ItemModuleSlot; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.world.item.ItemStack; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +public class ModularItemStack implements IModularItem { + + public static final String MODULE_SLOTS_KEY = "ModuleSlots"; + public static final String MODULES_TAG = "Modules"; + + private final ItemStack stack; + private final Function> defaultSlotGetter; + + public ModularItemStack(ItemStack stack, Function> defaultSlotGetter) { + this.stack = stack; + this.defaultSlotGetter = defaultSlotGetter; + } + + @Override + public AppliedItemModule attach(ItemModule module, int slot, boolean simulate) { + CompoundTag modulesTag = stack.getOrCreateTagElement(MODULES_TAG); + ItemModuleSlot moduleSlot = getSlots().get(slot); + if (moduleSlot == null || !moduleSlot.acceptsModule(module) || !module.canApplyTo(stack)) return null; + if (!modulesTag.contains(String.valueOf(slot)) && !simulate) + modulesTag.put(String.valueOf(slot), new CompoundTag()); + AppliedItemModule appliedModule = new AppliedItemModule( + simulate ? new CompoundTag() : modulesTag.getCompound(String.valueOf(slot)), + module, + slot); + appliedModule.setAppliedTo(stack); + if (!simulate) { + module.onAttach(appliedModule); + } + return appliedModule; + } + + @Override + public @Nullable AppliedItemModule attach(ItemModule module, boolean simulate) { + for (int i = 0; i < getSlots().size(); i++) { + if (getModuleInSlot(i) == null) return attach(module, i, simulate); + } + return null; + } + + @Override + public void clearModules() { + stack.removeTagKey(MODULES_TAG); + } + + @Override + public @Nullable AppliedItemModule getModuleInSlot(int slot) { + CompoundTag modulesTag = stack.getOrCreateTagElement(MODULES_TAG); + if (!modulesTag.contains(String.valueOf(slot))) return null; + return new AppliedItemModule(modulesTag.getCompound(String.valueOf(slot)), stack, slot); + } + + @Override + public @NotNull List getAppliedModules() { + CompoundTag modulesTag = stack.getOrCreateTagElement(MODULES_TAG); + List modules = new ArrayList<>(); + for (String key : modulesTag.getAllKeys()) { + modules.add(new AppliedItemModule(modulesTag.getCompound(key), stack, Integer.parseInt(key))); + } + return modules; + } + + @Override + public @Nullable AppliedItemModule getModule(ItemModule module) { + return getAppliedModules().stream().filter(appliedModule -> appliedModule.getModule() == module).findAny() + .orElse(null); + } + + public List getDefaultSlots() { + return this.defaultSlotGetter.apply(stack); + } + + @Override + public void setSlots(List slots) { + CompoundTag tag = new CompoundTag(); + for (int i = 0; i < slots.size(); i++) { + ItemModuleSlot slot = slots.get(i); + if (slot != null) tag.put(String.valueOf(i), slot.serializeNBT()); + } + stack.getOrCreateTag().put(MODULE_SLOTS_KEY, tag); + } + + @Unmodifiable + @Override + public List getSlots() { + if (!stack.getOrCreateTag().contains(MODULE_SLOTS_KEY, Tag.TAG_COMPOUND)) { + List slots = getDefaultSlots(); + setSlots(slots); + return slots; + } else { + List slots = new ArrayList<>(); + CompoundTag tag = stack.getOrCreateTagElement(MODULE_SLOTS_KEY); + for (String key : tag.getAllKeys()) { + int i = Integer.parseInt(key); + while (slots.size() <= i) slots.add(null); + slots.set(i, ItemModuleSlot.fromNBT(tag.getCompound(key))); + } + return slots; + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/component/ICustomRenderer.java b/src/main/java/com/gregtechceu/gtceu/api/item/component/ICustomRenderer.java deleted file mode 100644 index 9a295f6e91f..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/item/component/ICustomRenderer.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gregtechceu.gtceu.api.item.component; - -import com.lowdragmc.lowdraglib.client.renderer.IRenderer; - -import org.jetbrains.annotations.NotNull; - -public interface ICustomRenderer extends IItemComponent { - - @NotNull - IRenderer getRenderer(); -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/component/IMonitorModuleItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/component/IMonitorModuleItem.java index 91a12e74343..2d78e03b506 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/component/IMonitorModuleItem.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/component/IMonitorModuleItem.java @@ -5,19 +5,21 @@ import com.gregtechceu.gtceu.common.machine.multiblock.electric.CentralMonitorMachine; import com.gregtechceu.gtceu.common.machine.multiblock.electric.monitor.MonitorGroup; -import com.lowdragmc.lowdraglib.gui.widget.Widget; - import net.minecraft.world.item.ItemStack; +import brachy.modularui.api.IPanelHandler; +import brachy.modularui.value.sync.PanelSyncManager; + public interface IMonitorModuleItem extends IItemComponent { default void tick(ItemStack stack, CentralMonitorMachine machine, MonitorGroup group) {} default void tickInPlaceholder(ItemStack stack, PlaceholderContext context) {} - IMonitorRenderer getRenderer(ItemStack stack); + IMonitorRenderer getRenderer(ItemStack stack, CentralMonitorMachine machine, MonitorGroup group); - Widget createUIWidget(ItemStack stack, CentralMonitorMachine machine, MonitorGroup group); + IPanelHandler createModularPanel(ItemStack stack, CentralMonitorMachine machine, MonitorGroup group, + PanelSyncManager syncManager); default String getType() { return "unknown"; diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/component/ModularItemComponent.java b/src/main/java/com/gregtechceu/gtceu/api/item/component/ModularItemComponent.java new file mode 100644 index 00000000000..602e6103dc9 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/component/ModularItemComponent.java @@ -0,0 +1,150 @@ +package com.gregtechceu.gtceu.api.item.component; + +import com.gregtechceu.gtceu.api.capability.GTCapability; +import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; +import com.gregtechceu.gtceu.api.item.capability.ModularItemStack; +import com.gregtechceu.gtceu.api.item.component.forge.IComponentCapability; +import com.gregtechceu.gtceu.api.item.module.AppliedItemModule; +import com.gregtechceu.gtceu.api.item.module.ICapabilityModule; +import com.gregtechceu.gtceu.api.item.module.IModularItem; +import com.gregtechceu.gtceu.api.item.module.ItemModuleSlot; +import com.gregtechceu.gtceu.common.data.GTItemModules; + +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +public class ModularItemComponent implements IItemComponent, IComponentCapability, IInteractionItem, IAddInformation { + + private final Function> defaultSlotGetter; + + public ModularItemComponent(Function> defaultSlotGetter) { + this.defaultSlotGetter = defaultSlotGetter; + } + + public ModularItemComponent(int slots, int maxTier) { + List defaultSlots = new ArrayList<>(); + for (int i = 0; i < slots; i++) defaultSlots.add(GTItemModules.TIERED_SLOTS[maxTier]); + this.defaultSlotGetter = stack -> defaultSlots; + } + + @Override + public @NotNull LazyOptional getCapability(ItemStack stack, @NotNull Capability cap) { + if (cap == GTCapability.CAPABILITY_MODULAR_ITEM) + return GTCapability.CAPABILITY_MODULAR_ITEM.orEmpty(cap, + LazyOptional.of(() -> new ModularItemStack(stack, defaultSlotGetter))); + else { + IModularItem modularItem = GTCapabilityHelper.getModularItem(stack); + if (modularItem != null) { + for (AppliedItemModule module : modularItem.getAppliedModules()) { + if (module.getModule() instanceof ICapabilityModule capabilityModule) { + LazyOptional optional = capabilityModule.getCapability(module, cap); + if (optional.isPresent()) return optional; + } + } + } + return LazyOptional.empty(); + } + } + + @Override + public InteractionResultHolder use(Item item, Level level, Player player, InteractionHand usedHand) { + IModularItem modularItem = GTCapabilityHelper.getModularItem(player.getItemInHand(usedHand)); + if (modularItem != null) { + for (AppliedItemModule module : modularItem.getAppliedModules()) { + InteractionResultHolder result = module.getModule().use(module, level, player, usedHand); + if (result.getResult() != InteractionResult.PASS) return result; + } + } + return IInteractionItem.super.use(item, level, player, usedHand); + } + + @Override + public InteractionResult useOn(UseOnContext context) { + IModularItem modularItem = GTCapabilityHelper.getModularItem(context.getItemInHand()); + if (modularItem != null) { + for (AppliedItemModule module : modularItem.getAppliedModules()) { + InteractionResult result = module.getModule().useOn(module, context); + if (result != InteractionResult.PASS) return result; + } + } + return IInteractionItem.super.useOn(context); + } + + @Override + public InteractionResult onItemUseFirst(ItemStack itemStack, UseOnContext context) { + IModularItem modularItem = GTCapabilityHelper.getModularItem(itemStack); + if (modularItem != null) { + for (AppliedItemModule module : modularItem.getAppliedModules()) { + InteractionResult result = module.getModule().onItemUseFirst(module, context); + if (result != InteractionResult.PASS) return result; + } + } + return IInteractionItem.super.onItemUseFirst(itemStack, context); + } + + @Override + public InteractionResult interactLivingEntity(ItemStack stack, Player player, LivingEntity interactionTarget, + InteractionHand usedHand) { + IModularItem modularItem = GTCapabilityHelper.getModularItem(stack); + if (modularItem != null) { + for (AppliedItemModule module : modularItem.getAppliedModules()) { + InteractionResult result = module.getModule().interactLivingEntity(module, player, interactionTarget, + usedHand); + if (result != InteractionResult.PASS) return result; + } + } + return IInteractionItem.super.interactLivingEntity(stack, player, interactionTarget, usedHand); + } + + @Override + public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltipComponents, + TooltipFlag isAdvanced) { + IModularItem modularItem = GTCapabilityHelper.getModularItem(stack); + if (modularItem != null) { + List slots = modularItem.getSlots(); + if (!slots.isEmpty()) tooltipComponents.add(Component.translatable("metaarmor.tooltip.modifiers")); + for (int slotI = 0; slotI < slots.size(); slotI++) { + ItemModuleSlot slot = slots.get(slotI); + if (slot == null) continue; + AppliedItemModule module = modularItem.getModuleInSlot(slotI); + if (module != null) { + int prevIndex = tooltipComponents.size(); + module.appendHoverText(level, isAdvanced, tooltipComponents); + if (tooltipComponents.size() > prevIndex) { + tooltipComponents.set(prevIndex, Component.translatable( + "metaarmor.tooltip.modifier", + slot.getDisplayName(), + tooltipComponents.get(prevIndex))); + for (int i = prevIndex + 1; i < tooltipComponents.size(); i++) { + tooltipComponents.set(i, Component.literal(" ").append(tooltipComponents.get(i))); + } + } + } else { + tooltipComponents.add(Component.translatable( + "metaarmor.tooltip.modifier", + slot.getDisplayName(), + Component.translatable("metaarmor.tooltip.modifier.empty").withStyle(ChatFormatting.GRAY))); + } + } + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/module/AppliedItemModule.java b/src/main/java/com/gregtechceu/gtceu/api/item/module/AppliedItemModule.java new file mode 100644 index 00000000000..d314ef618f0 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/module/AppliedItemModule.java @@ -0,0 +1,142 @@ +package com.gregtechceu.gtceu.api.item.module; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.api.item.capability.ModularItemStack; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; + +import lombok.Getter; +import lombok.Setter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public final class AppliedItemModule { + + private final CompoundTag moduleTag; + @Getter + private final int slot; + + @Getter + private ItemModule module; + + @Getter + private CompoundTag tag; + + @Getter + private ItemStack moduleItem; + + /** + * The stack that this module is applied to. + * If this module is not applied to anything, this field is {@code null}. + */ + @Getter + @Setter + private ItemStack appliedTo; + + /** + * Create an applied module and fill the provided tag with module data + */ + public AppliedItemModule(CompoundTag moduleTag, ItemModule module, int slot) { + this.moduleTag = moduleTag; + this.moduleTag.put("module", module.serializeNBT()); + this.moduleTag.put("tag", new CompoundTag()); + this.module = module; + this.tag = this.moduleTag.getCompound("tag"); + this.slot = slot; + } + + /** + * Load an applied module from an existing module tag + */ + public AppliedItemModule(CompoundTag moduleTag, @Nullable ItemStack appliedTo, int slot) { + this.moduleTag = moduleTag; + if (!this.moduleTag.contains("module")) { + GTCEu.LOGGER.warn("Created an AppliedItemModule from an invalid tag, module will be null!"); + } + this.module = ItemModule.fromNBT(this.moduleTag.getCompound("module")); + if (!this.moduleTag.contains("tag")) this.moduleTag.put("tag", new CompoundTag()); + this.tag = this.moduleTag.getCompound("tag"); + this.slot = slot; + if (this.moduleTag.contains("item")) { + this.moduleItem = ItemStack.of(this.moduleTag.getCompound("item")); + } + this.appliedTo = appliedTo; + } + + public void setModule(ItemModule module) { + this.moduleTag.put("module", module.serializeNBT()); + this.module = module; + } + + public void setModuleItem(ItemStack stack) { + this.moduleItem = stack; + this.moduleTag.put("item", stack.serializeNBT()); + } + + public void setTag(CompoundTag tag) { + this.moduleTag.put("tag", tag); + this.tag = tag; + } + + public void detach() { + if (this.appliedTo == null || !this.module.canRemove(this)) return; + this.module.onRemove(this); + this.appliedTo.getOrCreateTagElement(ModularItemStack.MODULES_TAG).remove(String.valueOf(slot)); + this.appliedTo = null; + } + + public void inventoryTick(Player player) { + if (this.isEnabled()) this.module.onInventoryTick(player, this); + this.module.onTickRaw(this, player, player.level(), null); + } + + public void armorTick(@NotNull LivingEntity entity) { + if (this.isEnabled()) this.module.onArmorTick(entity, this); + } + + public void tick(@NotNull Level level, @Nullable BlockPos pos) { + this.module.onTickRaw(this, null, level, pos); + } + + public void equip(@NotNull LivingEntity entity) { + this.module.onEquip(entity, this); + } + + public void unequip(@NotNull LivingEntity entity) { + this.module.onUnequip(entity, this); + } + + public float changeDamage(LivingEntity entity, float damage, DamageSource source) { + return this.isEnabled() ? this.module.changeDamage(entity, this, damage, source) : damage; + } + + public void appendHoverText(Level level, TooltipFlag isAdvanced, List tooltips) { + this.module.appendHoverText(level, isAdvanced, tooltips, this); + } + + public boolean isEnabled() { + return this.module.isEnabled(this); + } + + public void setEnabled(boolean enabled) { + this.module.setEnabled(this, enabled); + } + + public boolean isPPE() { + return this.module.isPPE(this) && this.isEnabled(); + } + + public boolean canRemove() { + return this.module.canRemove(this); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/module/ArmorLogicItemModule.java b/src/main/java/com/gregtechceu/gtceu/api/item/module/ArmorLogicItemModule.java new file mode 100644 index 00000000000..090c6e5195a --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/module/ArmorLogicItemModule.java @@ -0,0 +1,63 @@ +package com.gregtechceu.gtceu.api.item.module; + +import com.gregtechceu.gtceu.api.item.armor.IArmorLogic; +import com.gregtechceu.gtceu.api.item.component.IItemHUDProvider; + +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; + +import org.jetbrains.annotations.Nullable; + +public abstract class ArmorLogicItemModule extends ItemModule implements IHUDProviderItemModule { + + public ArmorLogicItemModule(ResourceLocation id) { + super(id); + } + + protected abstract @Nullable IArmorLogic getArmorLogic(AppliedItemModule module); + + @Override + public void onArmorTick(LivingEntity entity, AppliedItemModule module) { + super.onArmorTick(entity, module); + IArmorLogic armorLogic = getArmorLogic(module); + if (armorLogic == null) return; + if (entity instanceof Player player) armorLogic.onArmorTick(player.level(), player, module.getAppliedTo()); + } + + @Override + public void onEquip(LivingEntity entity, AppliedItemModule module) { + super.onEquip(entity, module); + IArmorLogic armorLogic = getArmorLogic(module); + if (armorLogic == null) return; + if (entity instanceof Player player) armorLogic.onEquip(player); + } + + @Override + public void onUnequip(LivingEntity entity, AppliedItemModule module) { + super.onUnequip(entity, module); + IArmorLogic armorLogic = getArmorLogic(module); + if (armorLogic == null) return; + if (entity instanceof Player player) armorLogic.onUnequip(player); + } + + @Override + public boolean isPPE(AppliedItemModule module) { + IArmorLogic armorLogic = getArmorLogic(module); + if (armorLogic == null) return super.isPPE(module); + return armorLogic.isPPE(module.getAppliedTo()); + } + + @Override + public boolean shouldDrawHUD(AppliedItemModule module) { + return getArmorLogic(module) instanceof IItemHUDProvider; + } + + @Override + public void drawHUD(AppliedItemModule module, GuiGraphics graphics) { + if (getArmorLogic(module) instanceof IItemHUDProvider provider) { + IItemHUDProvider.tryDrawHud(provider, module.getAppliedTo(), graphics); + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/module/ICapabilityModule.java b/src/main/java/com/gregtechceu/gtceu/api/item/module/ICapabilityModule.java new file mode 100644 index 00000000000..321a45e895f --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/module/ICapabilityModule.java @@ -0,0 +1,11 @@ +package com.gregtechceu.gtceu.api.item.module; + +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; + +import org.jetbrains.annotations.NotNull; + +public interface ICapabilityModule { + + @NotNull LazyOptional getCapability(AppliedItemModule module, @NotNull Capability cap); +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/module/IConfigurableModule.java b/src/main/java/com/gregtechceu/gtceu/api/item/module/IConfigurableModule.java new file mode 100644 index 00000000000..a2f63e43fee --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/module/IConfigurableModule.java @@ -0,0 +1,11 @@ +package com.gregtechceu.gtceu.api.item.module; + +import com.lowdragmc.lowdraglib.gui.widget.Widget; + +import org.jetbrains.annotations.NotNull; + +public interface IConfigurableModule { + + @NotNull + Widget createConfigUI(@NotNull AppliedItemModule module); +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/module/IHUDProviderItemModule.java b/src/main/java/com/gregtechceu/gtceu/api/item/module/IHUDProviderItemModule.java new file mode 100644 index 00000000000..6d9e2d84a10 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/module/IHUDProviderItemModule.java @@ -0,0 +1,31 @@ +package com.gregtechceu.gtceu.api.item.module; + +import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; + +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public interface IHUDProviderItemModule { + + @OnlyIn(Dist.CLIENT) + default boolean shouldDrawHUD(AppliedItemModule module) { + return true; + } + + @OnlyIn(Dist.CLIENT) + void drawHUD(AppliedItemModule module, GuiGraphics graphics); + + @OnlyIn(Dist.CLIENT) + static void tryDrawHUD(ItemStack stack, GuiGraphics graphics) { + if (stack == null || stack.isEmpty()) return; + IModularItem modularItem = GTCapabilityHelper.getModularItem(stack); + if (modularItem == null) return; + for (AppliedItemModule module : modularItem.getAppliedModules()) { + if (module.getModule() instanceof IHUDProviderItemModule hudProvider) { + if (hudProvider.shouldDrawHUD(module)) hudProvider.drawHUD(module, graphics); + } + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/module/IJumpBoostItemModule.java b/src/main/java/com/gregtechceu/gtceu/api/item/module/IJumpBoostItemModule.java new file mode 100644 index 00000000000..52ff35a812a --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/module/IJumpBoostItemModule.java @@ -0,0 +1,6 @@ +package com.gregtechceu.gtceu.api.item.module; + +public interface IJumpBoostItemModule { + + float getJumpBoost(AppliedItemModule module); +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/module/IModularItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/module/IModularItem.java new file mode 100644 index 00000000000..e907c107f6e --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/module/IModularItem.java @@ -0,0 +1,31 @@ +package com.gregtechceu.gtceu.api.item.module; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public interface IModularItem { + + /** + * @return the default module slot configuration of this item + */ + List getSlots(); + + void clearModules(); + + @Nullable + AppliedItemModule getModuleInSlot(int slot); + + @NotNull + List getAppliedModules(); + + @Nullable + AppliedItemModule getModule(ItemModule module); + + void setSlots(List slots); + + AppliedItemModule attach(ItemModule module, int slot, boolean simulate); + + AppliedItemModule attach(ItemModule module, boolean simulate); +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/module/ITieredItemModule.java b/src/main/java/com/gregtechceu/gtceu/api/item/module/ITieredItemModule.java new file mode 100644 index 00000000000..8cd8ef09722 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/module/ITieredItemModule.java @@ -0,0 +1,6 @@ +package com.gregtechceu.gtceu.api.item.module; + +public interface ITieredItemModule { + + int getTier(); +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/module/ItemModule.java b/src/main/java/com/gregtechceu/gtceu/api/item/module/ItemModule.java new file mode 100644 index 00000000000..d2f58aeffb7 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/module/ItemModule.java @@ -0,0 +1,296 @@ +package com.gregtechceu.gtceu.api.item.module; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; +import com.gregtechceu.gtceu.api.capability.IElectricItem; +import com.gregtechceu.gtceu.common.mui.GTGuiTextures; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; + +import brachy.modularui.api.drawable.IKey; +import brachy.modularui.api.widget.IWidget; +import brachy.modularui.drawable.GuiTextures; +import brachy.modularui.value.sync.DoubleSyncValue; +import brachy.modularui.value.sync.PanelSyncManager; +import brachy.modularui.value.sync.SyncHandler; +import brachy.modularui.value.sync.SyncHandlers; +import brachy.modularui.widget.Widget; +import brachy.modularui.widgets.ProgressWidget; +import brachy.modularui.widgets.SliderWidget; +import brachy.modularui.widgets.TextWidget; +import brachy.modularui.widgets.ToggleButton; +import brachy.modularui.widgets.layout.Flow; +import brachy.modularui.widgets.textfield.TextFieldWidget; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.*; + +public abstract class ItemModule { + + private static final Map MODULES = new HashMap<>(); + + @Getter + private final ResourceLocation id; + + public static @Nullable ItemModule getModuleById(ResourceLocation id) { + return MODULES.get(id); + } + + public ItemModule(ResourceLocation id) { + this.id = id; + if (MODULES.containsKey(id)) { + GTCEu.LOGGER.warn("Attempted to create 2 modules with the same id: {}", id); + } else MODULES.put(id, this); + } + + public final CompoundTag serializeNBT() { + CompoundTag tag = new CompoundTag(); + tag.putString("id", id.toString()); + return tag; + } + + public static ItemModule fromNBT(CompoundTag tag) { + return getModuleById(ResourceLocation.tryParse(tag.getString("id"))); + } + + public abstract Component getInfo(); + + public void onAttach(AppliedItemModule module) {} + + public void onRemove(AppliedItemModule module) {} + + public void onEquip(LivingEntity entity, AppliedItemModule module) {} + + public void onArmorTick(LivingEntity entity, AppliedItemModule module) { + IElectricItem electricItem = GTCapabilityHelper.getElectricItem(module.getModuleItem()); + long energy = energyUsagePerTick(entity, module); + if (electricItem != null) { + electricItem.discharge(energy, electricItem.getTier(), true, false, false); + } + } + + public void onUnequip(LivingEntity entity, AppliedItemModule module) {} + + /** + * Called each tick this item is in a player's inventory or equipment slots + */ + public void onInventoryTick(Player player, AppliedItemModule module) { + if (module.getModuleItem() == null) return; + IElectricItem electricItem = GTCapabilityHelper.getElectricItem(module.getModuleItem()); + long energy = energyUsagePerTick(player, module); + if (electricItem != null && useEnergyInInventory(player, module)) { + electricItem.discharge(energy, electricItem.getTier(), true, false, false); + } + } + + /** + * @return name displayed in the modules UI + */ + public Component getDisplayName(AppliedItemModule module) { + List list = new ArrayList<>(); + appendHoverText(null, TooltipFlag.NORMAL, list, module); + return list.isEmpty() ? Component.empty() : list.get(0); + } + + public void appendHoverText(Level level, TooltipFlag isAdvanced, List tooltips, + AppliedItemModule module) {} + + public boolean useEnergyInInventory(LivingEntity entity, AppliedItemModule module) { + return true; + } + + public long energyUsagePerTick(LivingEntity entity, AppliedItemModule module) { + return 0; + } + + public float changeDamage(LivingEntity entity, AppliedItemModule modifier, float damage, DamageSource source) { + return damage; + } + + public boolean canRemove(AppliedItemModule module) { + return true; + } + + public boolean isPPE(AppliedItemModule module) { + return false; + } + + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + public boolean canApplyTo(ItemStack stack) { + IModularItem modularItem = GTCapabilityHelper.getModularItem(stack); + return modularItem != null && modularItem.getModule(this) == null; + } + + public boolean isEnabled(AppliedItemModule module) { + if (!module.getTag().contains("enabled")) { + setEnabled(module, true); + } + return module.getTag().getBoolean("enabled"); + } + + public void setEnabled(AppliedItemModule module, boolean enabled) { + module.getTag().putBoolean("enabled", enabled); + } + + /** + * Called when the item this module is attached to is ticked, + * ignores {@link #isEnabled(AppliedItemModule)}. + * + * @param entity the entity in which the item is, {@code null} if the item is not in one + * @param pos the position of the block in which the item is, {@code null} if the item is not in one + */ + public void onTickRaw(AppliedItemModule module, @Nullable Entity entity, @NotNull Level level, + @Nullable BlockPos pos) {} + + public InteractionResultHolder use(AppliedItemModule module, Level level, Player player, + InteractionHand hand) { + return InteractionResultHolder.pass(player.getItemInHand(hand)); + } + + public InteractionResult useOn(AppliedItemModule module, UseOnContext context) { + return InteractionResult.PASS; + } + + public InteractionResult onItemUseFirst(AppliedItemModule module, UseOnContext context) { + return InteractionResult.PASS; + } + + public InteractionResult interactLivingEntity(AppliedItemModule module, Player player, + LivingEntity interactionTarget, InteractionHand usedHand) { + return InteractionResult.PASS; + } + + public Settings getSettings(AppliedItemModule module, PanelSyncManager psm, int id) { + psm.syncValue("module_enabled", id, + SyncHandlers.intNumber(() -> isEnabled(module) ? 0 : 1, x -> setEnabled(module, x == 0))); + Settings settings = new Settings(psm, id); + return settings + .bool(IKey.lang("gtceu.module.gui.enabled"), () -> isEnabled(module), b -> setEnabled(module, b)); + } + + public static final class Settings extends ArrayList { + + private final PanelSyncManager psm; + private final int id; + private int current = 0; + + private Settings(PanelSyncManager psm, int id) { + this.psm = psm; + this.id = id; + } + + private String registerSyncValue(SyncHandler syncHandler) { + String key = "module_setting" + current; + current++; + psm.syncValue(key, id, syncHandler); + return key; + } + + private Settings pop() { + remove(size() - 1); + return this; + } + + private W last() { + // noinspection unchecked + return (W) get(size() - 1); + } + + private static Flow wrap(IKey label, IWidget widget) { + return Flow.row() + .coverChildren() + .childPadding(5) + .child(new TextWidget<>(label)) + .child(widget); + } + + public Settings custom(IKey label, SyncHandler syncHandler, Widget widget) { + String key = registerSyncValue(syncHandler); + add(wrap(label, widget + .syncHandler(key, id))); + return this; + } + + public Settings bool(IKey label, BooleanSupplier getter, Consumer setter) { + return custom(label, + SyncHandlers.intNumber(() -> getter.getAsBoolean() ? 0 : 1, x -> setter.accept(x == 0)), + new ToggleButton() + .invertSelected(true) + .overlay(false, GuiTextures.CHECKMARK)); + } + + public Settings num(IKey label, IntSupplier getter, IntConsumer setter, int min, int max) { + return num(label, getter, setter, min, max, "%d"); + } + + public Settings num(IKey label, IntSupplier getter, IntConsumer setter, int min, int max, String sliderLabel) { + custom(label, + SyncHandlers.intNumber(getter, setter), + new SliderWidget() + .bounds(min, max) + .width(50) + .stopper(1)) + .last() + .child(new TextWidget<>( + IKey.dynamic(() -> Component.literal(sliderLabel.formatted(getter.getAsInt()))))); + return this; + } + + public Settings num(IKey label, DoubleSupplier getter, DoubleConsumer setter, double min, double max) { + return num(label, getter, setter, min, max, "%.2f"::formatted); + } + + public Settings num(IKey label, DoubleSupplier getter, DoubleConsumer setter, double min, double max, + DoubleFunction sliderLabel) { + custom(label, + SyncHandlers.doubleNumber(getter, setter), + new SliderWidget() + .bounds(min, max) + .width(50) + .stopper((max - min) / 10)) + .last() + .child(new TextWidget<>( + IKey.dynamic(() -> Component.literal(sliderLabel.apply(getter.getAsDouble()))))); + return this; + } + + public Settings str(IKey label, Supplier getter, Consumer setter) { + return custom(label, + SyncHandlers.string(getter, setter), + new TextFieldWidget()); + } + + public Settings progress(IKey label, DoubleSupplier getter, DoubleFunction rightLabel) { + DoubleSyncValue syncValue = SyncHandlers.doubleNumber(getter, null); + custom(label, syncValue, new ProgressWidget() + .texture(GTGuiTextures.PROGRESS_BAR_BOILER_EMPTY_STEEL, + GTGuiTextures.PROGRESS_BAR_BOILER_HEAT, 60) + .direction(ProgressWidget.Direction.RIGHT) + .width(50)) + .last() + .child(new TextWidget<>( + IKey.dynamic(() -> Component.literal(rightLabel.apply(syncValue.getValue()))))); + return this; + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/module/ItemModuleSlot.java b/src/main/java/com/gregtechceu/gtceu/api/item/module/ItemModuleSlot.java new file mode 100644 index 00000000000..6d731f384aa --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/module/ItemModuleSlot.java @@ -0,0 +1,47 @@ +package com.gregtechceu.gtceu.api.item.module; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +import brachy.modularui.api.drawable.IDrawable; +import lombok.Getter; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +public abstract class ItemModuleSlot { + + private static final Map SLOTS = new HashMap<>(); + + @Getter + private final ResourceLocation id; + + public static @Nullable ItemModuleSlot getById(ResourceLocation id) { + return SLOTS.get(id); + } + + protected ItemModuleSlot(ResourceLocation id) { + this.id = id; + SLOTS.put(id, this); + } + + public CompoundTag serializeNBT() { + CompoundTag tag = new CompoundTag(); + tag.putString("id", id.toString()); + return tag; + } + + public static ItemModuleSlot fromNBT(CompoundTag tag) { + return getById(ResourceLocation.tryParse(tag.getString("id"))); + } + + public abstract boolean acceptsModule(ItemModule module); + + public abstract Component getDisplayName(); + + public IDrawable getSlotTexture() { + return null; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/module/TieredAttributeItemModule.java b/src/main/java/com/gregtechceu/gtceu/api/item/module/TieredAttributeItemModule.java new file mode 100644 index 00000000000..db9faef2e56 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/module/TieredAttributeItemModule.java @@ -0,0 +1,127 @@ +package com.gregtechceu.gtceu.api.item.module; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; + +import brachy.modularui.api.drawable.IKey; +import brachy.modularui.value.sync.PanelSyncManager; + +import java.util.Iterator; +import java.util.UUID; + +public abstract class TieredAttributeItemModule extends TieredItemModule { + + private static final String MODIFIER_UUID_KEY = "modifier_id"; + private static final String MODIFIER_AMOUNT_KEY = "modifier_amount"; + + public TieredAttributeItemModule(ResourceLocation id, int tier) { + super(id, tier); + } + + private void attachAttribute(AppliedItemModule appliedItemModule) { + if (appliedItemModule.getTag().contains(MODIFIER_UUID_KEY)) return; + if (appliedItemModule.getAppliedTo() == null) return; + EquipmentSlot slot = LivingEntity.getEquipmentSlotForItem(appliedItemModule.getAppliedTo()); + AttributeModifier attributeModifier = applySettingsToModifier(appliedItemModule, + getAttributeModifier(appliedItemModule)); + appliedItemModule.getAppliedTo().addAttributeModifier(getAttribute(appliedItemModule), attributeModifier, slot); + appliedItemModule.getTag().putUUID(MODIFIER_UUID_KEY, attributeModifier.getId()); + } + + private void detachAttribute(AppliedItemModule appliedItemModule) { + UUID uuid = appliedItemModule.getTag().getUUID(MODIFIER_UUID_KEY); + ListTag listTag = appliedItemModule.getAppliedTo().getOrCreateTag().getList("AttributeModifiers", + Tag.TAG_COMPOUND); + Iterator it = listTag.iterator(); + while (it.hasNext()) { + Tag tag = it.next(); + if (tag instanceof CompoundTag compoundTag) { + AttributeModifier attributeModifier = AttributeModifier.load(compoundTag); + if (attributeModifier != null && attributeModifier.getId().equals(uuid)) it.remove(); + } + } + appliedItemModule.getTag().remove(MODIFIER_UUID_KEY); + } + + protected double getNeutralModifier(AppliedItemModule module) { + return 0; + } + + public double getMinModifier(AppliedItemModule module) { + AttributeModifier attributeModifier = getAttributeModifier(module); + double original = attributeModifier.getAmount(); + double neutral = getNeutralModifier(module); + return Math.min(neutral, original); + } + + public double getMaxModifier(AppliedItemModule module) { + AttributeModifier attributeModifier = getAttributeModifier(module); + double original = attributeModifier.getAmount(); + double neutral = getNeutralModifier(module); + return Math.max(neutral, original); + } + + protected AttributeModifier applySettingsToModifier(AppliedItemModule module, AttributeModifier modifier) { + double modifiedAmount = getModifier(module); + return new AttributeModifier(modifier.getId(), modifier.getName(), modifiedAmount, modifier.getOperation()); + } + + public double getModifier(AppliedItemModule module) { + if (module.getTag().contains(MODIFIER_AMOUNT_KEY)) + return module.getTag().getDouble(MODIFIER_AMOUNT_KEY); + return getAttributeModifier(module).getAmount(); + } + + public void setModifier(AppliedItemModule module, double modifier) { + module.getTag().putDouble(MODIFIER_AMOUNT_KEY, modifier); + detachAttribute(module); + attachAttribute(module); + } + + protected String getSliderString(AppliedItemModule module, double value) { + return switch (getAttributeModifier(module).getOperation()) { + case ADDITION -> "+%.2f".formatted(value); + case MULTIPLY_BASE, MULTIPLY_TOTAL -> "+%.2f%%".formatted(value * 100); + }; + } + + @Override + public Settings getSettings(AppliedItemModule module, PanelSyncManager psm, int id) { + return super.getSettings(module, psm, id) + .num(IKey.lang("gtceu.module.gui.power"), + () -> getModifier(module), + x -> setModifier(module, x), + getMinModifier(module), getMaxModifier(module), + x -> getSliderString(module, x)); + } + + @Override + public void onAttach(AppliedItemModule appliedItemModule) { + super.onAttach(appliedItemModule); + attachAttribute(appliedItemModule); + } + + @Override + public void onRemove(AppliedItemModule appliedItemModule) { + super.onRemove(appliedItemModule); + detachAttribute(appliedItemModule); + } + + @Override + public void setEnabled(AppliedItemModule module, boolean enabled) { + super.setEnabled(module, enabled); + if (this.isEnabled(module)) { + this.attachAttribute(module); + } else this.detachAttribute(module); + } + + public abstract Attribute getAttribute(AppliedItemModule module); + + public abstract AttributeModifier getAttributeModifier(AppliedItemModule module); +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/module/TieredItemModule.java b/src/main/java/com/gregtechceu/gtceu/api/item/module/TieredItemModule.java new file mode 100644 index 00000000000..fb347d35638 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/module/TieredItemModule.java @@ -0,0 +1,49 @@ +package com.gregtechceu.gtceu.api.item.module; + +import com.gregtechceu.gtceu.api.GTValues; +import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; + +import lombok.Getter; + +import java.util.function.BiFunction; + +public abstract class TieredItemModule extends ItemModule implements ITieredItemModule { + + @Getter + private final int tier; + @Getter + private TieredItemModule[] otherTierModules; + + public TieredItemModule(ResourceLocation id, int tier) { + super(id); + this.tier = tier; + } + + @Override + public boolean canApplyTo(ItemStack stack) { + if (otherTierModules == null) return super.canApplyTo(stack); + IModularItem modularItem = GTCapabilityHelper.getModularItem(stack); + if (modularItem == null) return false; + for (TieredItemModule module : otherTierModules) if (modularItem.getModule(module) != null) return false; + return super.canApplyTo(stack); + } + + public static TieredItemModule[] create(ResourceLocation id, int minTier, int maxTier, + BiFunction constructor) { + TieredItemModule[] result = new TieredItemModule[maxTier - minTier + 1]; + for (int i = 0; i <= maxTier - minTier; i++) { + ResourceLocation resourceLocation = id.withSuffix("_" + (i + minTier)); + result[i] = constructor.apply(resourceLocation, i + minTier); + result[i].otherTierModules = result; + } + return result; + } + + public static TieredItemModule[] create(ResourceLocation id, + BiFunction constructor) { + return create(id, GTValues.LV, GTValues.MAX, constructor); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/module/TieredItemModuleSlot.java b/src/main/java/com/gregtechceu/gtceu/api/item/module/TieredItemModuleSlot.java new file mode 100644 index 00000000000..0edf46e6ce2 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/module/TieredItemModuleSlot.java @@ -0,0 +1,53 @@ +package com.gregtechceu.gtceu.api.item.module; + +import com.gregtechceu.gtceu.api.GTValues; +import com.gregtechceu.gtceu.common.mui.drawable.BorderDrawable; + +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +import brachy.modularui.api.drawable.IDrawable; +import lombok.Getter; + +import java.util.function.BiFunction; + +public class TieredItemModuleSlot extends ItemModuleSlot { + + @Getter + private final int tier; + + public TieredItemModuleSlot(ResourceLocation id, int tier) { + super(id); + this.tier = tier; + } + + @Override + public boolean acceptsModule(ItemModule module) { + return !(module instanceof ITieredItemModule tieredModule) || tieredModule.getTier() <= getTier(); + } + + @Override + public Component getDisplayName() { + return Component.translatable("metaarmor.tooltip.modifier_slot.tiered", GTValues.VNF[getTier()]); + } + + public static TieredItemModuleSlot[] create(ResourceLocation id, int minTier, int maxTier, + BiFunction constructor) { + TieredItemModuleSlot[] result = new TieredItemModuleSlot[maxTier - minTier + 1]; + for (int i = 0; i <= maxTier - minTier; i++) { + ResourceLocation resourceLocation = id.withSuffix("_" + (i + minTier)); + result[i] = constructor.apply(resourceLocation, i + minTier); + } + return result; + } + + public static TieredItemModuleSlot[] create(ResourceLocation id, + BiFunction constructor) { + return create(id, GTValues.ULV, GTValues.MAX, constructor); + } + + @Override + public IDrawable getSlotTexture() { + return new BorderDrawable(0xFF000000 | GTValues.VCM[getTier()], 1); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/module/UniversalItemModuleSlot.java b/src/main/java/com/gregtechceu/gtceu/api/item/module/UniversalItemModuleSlot.java new file mode 100644 index 00000000000..c5903fa4e71 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/item/module/UniversalItemModuleSlot.java @@ -0,0 +1,30 @@ +package com.gregtechceu.gtceu.api.item.module; + +import com.gregtechceu.gtceu.common.mui.drawable.BorderDrawable; + +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +import brachy.modularui.api.drawable.IDrawable; + +public class UniversalItemModuleSlot extends ItemModuleSlot { + + public UniversalItemModuleSlot(ResourceLocation id) { + super(id); + } + + @Override + public boolean acceptsModule(ItemModule module) { + return true; + } + + @Override + public Component getDisplayName() { + return Component.translatable("metaarmor.tooltip.modifier_slot.universal"); + } + + @Override + public IDrawable getSlotTexture() { + return new BorderDrawable(0xFFFFFFFF, 1); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/tool/IToolGridHighlight.java b/src/main/java/com/gregtechceu/gtceu/api/item/tool/IToolGridHighlight.java index 9621d355051..d91f04b3940 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/tool/IToolGridHighlight.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/tool/IToolGridHighlight.java @@ -1,13 +1,12 @@ package com.gregtechceu.gtceu.api.item.tool; -import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; - import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; +import brachy.modularui.drawable.UITexture; import org.jetbrains.annotations.Nullable; import java.util.Set; @@ -16,7 +15,7 @@ public interface IToolGridHighlight { /** * Called to determine if the grid overlay should be rendered on this machine. - * + * * @param player Player looking at this machine * @param pos Block pos * @param state Block state @@ -32,7 +31,7 @@ default boolean shouldRenderGrid(Player player, BlockPos pos, BlockState state, /** * Called when the machine grid overlay is being rendered to determine the icon to be rendered within the grid * segment on a specifc side. - * + * * @param player Player looking at this machine * @param pos Block pos * @param state Block state @@ -40,8 +39,8 @@ default boolean shouldRenderGrid(Player player, BlockPos pos, BlockState state, * @param side The machine side which this grid segment correspond to * @return The icon to be rendered, or null */ - default @Nullable ResourceTexture sideTips(Player player, BlockPos pos, BlockState state, Set toolTypes, - Direction side) { + default @Nullable UITexture sideTips(Player player, BlockPos pos, BlockState state, Set toolTypes, + Direction side) { return null; } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/tool/behavior/IToolUIBehavior.java b/src/main/java/com/gregtechceu/gtceu/api/item/tool/behavior/IToolUIBehavior.java index e00fd5f658e..c2df3dd28f7 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/tool/behavior/IToolUIBehavior.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/tool/behavior/IToolUIBehavior.java @@ -1,31 +1,39 @@ package com.gregtechceu.gtceu.api.item.tool.behavior; -import com.lowdragmc.lowdraglib.gui.factory.HeldItemUIFactory; -import com.lowdragmc.lowdraglib.gui.modular.ModularUI; +import com.gregtechceu.gtceu.api.mui.GTGuiScreen; -import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import brachy.modularui.api.IUIHolder; +import brachy.modularui.factory.PlayerInventoryGuiData; +import brachy.modularui.factory.PlayerInventoryUIFactory; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.ModularScreen; import org.jetbrains.annotations.NotNull; -public interface IToolUIBehavior extends IToolBehavior { +public interface IToolUIBehavior extends IToolBehavior, IUIHolder> { @Override default @NotNull InteractionResultHolder onItemRightClick(@NotNull Level level, @NotNull Player player, @NotNull InteractionHand hand) { - var heldItem = player.getItemInHand(hand); - if (player instanceof ServerPlayer serverPlayer && openUI(serverPlayer, hand)) { - HeldItemUIFactory.INSTANCE.openUI(serverPlayer, hand); - return InteractionResultHolder.success(heldItem); + ItemStack heldItem = player.getItemInHand(hand); + if (level.isClientSide && shouldOpenUI(player, hand)) { + PlayerInventoryUIFactory.INSTANCE.openFromHandClient(hand); } return InteractionResultHolder.pass(heldItem); } - boolean openUI(@NotNull Player player, @NotNull InteractionHand hand); + @Override + @OnlyIn(Dist.CLIENT) + default ModularScreen createScreen(PlayerInventoryGuiData data, ModularPanel mainPanel) { + return new GTGuiScreen(mainPanel); + } - ModularUI createUI(Player player, HeldItemUIFactory.HeldItemHolder holder); + boolean shouldOpenUI(@NotNull Player player, @NotNull InteractionHand hand); } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/MachineCoverContainer.java b/src/main/java/com/gregtechceu/gtceu/api/machine/MachineCoverContainer.java index 270aad6f1fb..2feb1641551 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/MachineCoverContainer.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/MachineCoverContainer.java @@ -17,8 +17,6 @@ import com.gregtechceu.gtceu.api.transfer.fluid.IFluidHandlerModifiable; import com.gregtechceu.gtceu.utils.GTUtil; -import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; - import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.entity.player.Player; @@ -28,6 +26,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.items.IItemHandlerModifiable; +import brachy.modularui.drawable.UITexture; import lombok.Getter; import org.jetbrains.annotations.Nullable; @@ -90,8 +89,8 @@ public boolean shouldRenderGridOverlay(Player player, BlockPos pos, BlockState s } @Override - public @Nullable ResourceTexture getGridOverlayIcon(Player player, BlockPos pos, BlockState state, - Set toolTypes, Direction side) { + public @Nullable UITexture getGridOverlayIcon(Player player, BlockPos pos, BlockState state, + Set toolTypes, Direction side) { var cover = getCoverAtSide(side); if (cover != null) { return cover.sideTips(player, pos, state, toolTypes, side); diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/MachineDefinition.java b/src/main/java/com/gregtechceu/gtceu/api/machine/MachineDefinition.java index 01b6204239c..ff57306e85e 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/MachineDefinition.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/MachineDefinition.java @@ -3,15 +3,14 @@ import com.gregtechceu.gtceu.api.block.MetaMachineBlock; import com.gregtechceu.gtceu.api.capability.recipe.RecipeCapability; import com.gregtechceu.gtceu.api.data.RotationState; -import com.gregtechceu.gtceu.api.gui.editor.EditableMachineUI; import com.gregtechceu.gtceu.api.item.MetaMachineItem; import com.gregtechceu.gtceu.api.machine.feature.IRecipeLogicMachine; +import com.gregtechceu.gtceu.api.mui.factory.PanelFactory; import com.gregtechceu.gtceu.api.recipe.GTRecipe; import com.gregtechceu.gtceu.api.recipe.GTRecipeType; import com.gregtechceu.gtceu.api.recipe.modifier.RecipeModifier; import com.gregtechceu.gtceu.client.model.machine.MachineRenderState; - -import com.lowdragmc.lowdraglib.utils.ShapeUtils; +import com.gregtechceu.gtceu.utils.GTUtil; import net.minecraft.core.Direction; import net.minecraft.core.IdMapper; @@ -26,6 +25,7 @@ import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; +import brachy.modularui.theme.ThemeAPI; import it.unimi.dsi.fastutil.objects.Reference2IntMap; import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; import lombok.Getter; @@ -119,10 +119,13 @@ public class MachineDefinition implements Supplier { @Getter @Setter private boolean allowCoverOnFront; + @Getter + @Setter @Nullable + private PanelFactory UI; @Getter @Setter - private EditableMachineUI editableUI; + private String themeId = ThemeAPI.DEFAULT_ID; @Getter @Setter private Reference2IntMap> recipeOutputLimits = new Reference2IntOpenHashMap<>(); @@ -164,7 +167,7 @@ public ItemStack asStack(int count) { public VoxelShape getShape(Direction direction) { if (shape.isEmpty() || shape == Shapes.block() || direction == Direction.NORTH) return shape; - return this.cache.computeIfAbsent(direction, dir -> ShapeUtils.rotate(shape, dir)); + return this.cache.computeIfAbsent(direction, dir -> GTUtil.rotateVoxelShape(shape, dir)); } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java index 7a011bb3c71..f4b398b1222 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java @@ -13,8 +13,6 @@ import com.gregtechceu.gtceu.api.capability.recipe.IO; import com.gregtechceu.gtceu.api.cover.CoverBehavior; import com.gregtechceu.gtceu.api.data.RotationState; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.IFancyTooltip; import com.gregtechceu.gtceu.api.item.tool.GTToolType; import com.gregtechceu.gtceu.api.item.tool.IToolGridHighlight; import com.gregtechceu.gtceu.api.item.tool.ToolHelper; @@ -45,11 +43,10 @@ import com.gregtechceu.gtceu.common.machine.owner.MachineOwner; import com.gregtechceu.gtceu.common.machine.owner.PlayerOwner; import com.gregtechceu.gtceu.common.machine.trait.AutoOutputTrait; +import com.gregtechceu.gtceu.common.mui.GTGuiTextures; import com.gregtechceu.gtceu.utils.ExtendedUseOnContext; import com.gregtechceu.gtceu.utils.data.TagCompatibilityFixer; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; import com.lowdragmc.lowdraglib.utils.DummyWorld; import net.minecraft.ChatFormatting; @@ -58,7 +55,6 @@ import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.locale.Language; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; @@ -89,6 +85,7 @@ import appeng.api.networking.IInWorldGridNodeHost; import appeng.capabilities.Capabilities; +import brachy.modularui.drawable.UITexture; import com.mojang.datafixers.util.Pair; import lombok.AccessLevel; import lombok.Getter; @@ -102,7 +99,7 @@ * The base BlockEntity for all GT machines. */ public class MetaMachine extends ManagedSyncBlockEntity implements IGregtechBlockEntity, IToolGridHighlight, - IFancyTooltip, IPaintable, IMachineFeature, ICopyable { + IPaintable, IMachineFeature, ICopyable { @Getter protected final SyncDataHolder syncDataHolder = new SyncDataHolder(this); @@ -202,7 +199,7 @@ public void onMachineDestroyed() { /** * Called to modify the drops returned when this block is destroyed - * + * * @param drops A modifiable list of drops. */ public void modifyDrops(List drops) {} @@ -382,7 +379,7 @@ public Optional getTraitOptional(MachineTraitType /** * Called when a player clicks this machine with a GT tool - * + * * @param context The context of this interaction. * @return A pair containing the type of the tool (if the interaction was successful), and the result of the * interaction. @@ -487,7 +484,7 @@ protected InteractionResult onScrewdriverClick(ExtendedUseOnContext context) { /** * Called when a machine is right clicked with an item. - * + * * @param context The context which this interaction is being performed from. * @return The result of this interaction callback. */ @@ -512,7 +509,7 @@ public InteractionResult onUseWithItem(ExtendedUseOnContext context) { /** * Called when a machine is right clicked without an item, or if this machine was clicked with an item but no * item-specific interaction was performed. - * + * * @param context The context which this interaction is being performed from. * @return The result of this interaction callback. */ @@ -621,21 +618,21 @@ public boolean shouldRenderGrid(Player player, BlockPos pos, BlockState state, I } @Override - public @Nullable ResourceTexture sideTips(Player player, BlockPos pos, BlockState state, Set toolTypes, - Direction side) { + public @Nullable UITexture sideTips(Player player, BlockPos pos, BlockState state, Set toolTypes, + Direction side) { if (toolTypes.contains(GTToolType.WRENCH)) { if (player.isShiftKeyDown()) { if (isFacingValid(side) || (allowExtendedFacing() && hasFrontFacing() && side == getFrontFacing())) { - return GuiTextures.TOOL_FRONT_FACING_ROTATION; + return GTGuiTextures.TOOL_FRONT_FACING_ROTATION; } } } else if (toolTypes.contains(GTToolType.SOFT_MALLET)) { if (this instanceof IControllable controllable) { - return controllable.isWorkingEnabled() ? GuiTextures.TOOL_START : GuiTextures.TOOL_PAUSE; + return controllable.isWorkingEnabled() ? GTGuiTextures.TOOL_START : GTGuiTextures.TOOL_PAUSE; } } else if (toolTypes.contains(GTToolType.HARD_HAMMER)) { if (this instanceof IMufflableMachine mufflableMachine) { - return mufflableMachine.isMuffled() ? GuiTextures.TOOL_SOUND : GuiTextures.TOOL_MUTE; + return mufflableMachine.isMuffled() ? GTGuiTextures.TOOL_SOUND : GTGuiTextures.TOOL_MUTE; } } @@ -651,7 +648,7 @@ public boolean shouldRenderGrid(Player player, BlockPos pos, BlockState state, I /** * Adds extra information to the F3 debug overlay when looking at this machine. - * + * * @param lines A string consumer which lines are added to. */ public void addDebugOverlayText(Consumer lines) { @@ -667,7 +664,7 @@ public void addDebugOverlayText(Consumer lines) { /** * The {@link MachineDefinition} of this machine. - * + * * @return The {@link MachineDefinition} */ public MachineDefinition getDefinition() { @@ -689,7 +686,7 @@ public void addCollisionBoundingBox(List collisionList) { /** * Gets the direction which this machine is facing. - * + * * @return The direction the machine is facing, or north if this machine does not have a front face. */ public Direction getFrontFacing() { @@ -699,7 +696,7 @@ public Direction getFrontFacing() { /** * Returns whether this machine has a front face. - * + * * @return If this machine has a front face. */ public final boolean hasFrontFacing() { @@ -708,7 +705,7 @@ public final boolean hasFrontFacing() { /** * Returns whether this machine can be rotated to face a specific direction - * + * * @param facing The direction to test * @return If it is possible to rotate this machine to face the given direction. */ @@ -726,7 +723,7 @@ public boolean isFacingValid(Direction facing) { /** * Returns the {@link RotationState} properties which this machine type supports. - * + * * @return The {@link RotationState} */ public RotationState getRotationState() { @@ -735,7 +732,7 @@ public RotationState getRotationState() { /** * Rotates this machine to face a specific direction, if that direction is a valid facing direction. - * + * * @param facing The new facing direction. */ public void setFrontFacing(Direction facing) { @@ -759,7 +756,7 @@ public void setFrontFacing(Direction facing) { /** * Gets the direction which is this machine's upwards face. - * + * * @return The upwards facing direction, or north if this machine does not allow extended facing. */ public Direction getUpwardsFacing() { @@ -769,7 +766,7 @@ public Direction getUpwardsFacing() { /** * Changes this machine's upwards facing direction, if this machine supports extended facing directions. - * + * * @param upwardsFacing The new upwards facing direction. */ public void setUpwardsFacing(Direction upwardsFacing) { @@ -793,7 +790,7 @@ public void setUpwardsFacing(Direction upwardsFacing) { /** * Returns whether this machine supports extended facing directions. - * + * * @return If extended facing directions are supported. */ public boolean allowExtendedFacing() { @@ -802,7 +799,7 @@ public boolean allowExtendedFacing() { /** * Called when this machine is rotated - * + * * @param oldFacing The previous facing direction * @param newFacing The new facing direction */ @@ -810,7 +807,7 @@ public void onRotated(Direction oldFacing, Direction newFacing) {} /** * Called by the block colour handler to get tint colour for a specific layer index - * + * * @param index colour layer index * @return Integer colour, or -1 to not apply a colour tint. */ @@ -833,7 +830,7 @@ public ModelData getModelData() { /** * Called when a neighboring block is updated. - * + * * @param neighborBlock The neighbor block type. * @param neighborPos The neighbor position. * @param isMoving If the neighbor block is moving (e.g. moved by a piston) @@ -865,7 +862,7 @@ public BlockState getBlockAppearance(BlockState state, BlockAndTintGetter level, /** * Gets the current tick offset, which can be used to run code after a certain number of ticks. * For example, {@code getOffsetTimer() % 20 == 0} will be true every 20 ticks (1 second) - * + * * @return The current tick offset. */ public final long getOffsetTimer() { @@ -877,11 +874,6 @@ public final long getOffsetTimer() { return server.getTickCount() + getOffset(); } - @Override - public boolean isRemote() { - return IGregtechBlockEntity.super.isRemote(); - } - //////////////////////////////// // ***** Redstone Signals ****// //////////////////////////////// @@ -973,35 +965,6 @@ public boolean canConnectRedstone(Direction side) { return MachineOwner.getPlayerOwner(ownerUUID); } - ////////////////////////////////////// - // ******** GUI *********// - ////////////////////////////////////// - @Override - public IGuiTexture getFancyTooltipIcon() { - return GuiTextures.INFO_ICON; - } - - @Override - public final List getFancyTooltip() { - var tooltips = new ArrayList(); - onAddFancyInformationTooltip(tooltips); - return tooltips; - } - - @Override - public boolean showFancyTooltip() { - return !getFancyTooltip().isEmpty(); - } - - public void onAddFancyInformationTooltip(List tooltips) { - getDefinition().getTooltipBuilder().accept(getDefinition().asStack(), tooltips); - String mainKey = String.format("%s.machine.%s.tooltip", getDefinition().getId().getNamespace(), - getDefinition().getId().getPath()); - if (Language.getInstance().has(mainKey)) { - tooltips.add(0, Component.translatable(mainKey)); - } - } - @Override public int getDefaultPaintingColor() { return getDefinition().getDefaultPaintingColor(); @@ -1029,7 +992,7 @@ public AABB getRenderBoundingBox() { /** * Gets the item filter for a specific side of this machine. - * + * * @param side Side * @param io The IO mode this filter should be applicable to. * @return A {@code Predicate} representing this filter @@ -1054,7 +1017,7 @@ public Predicate getItemCapFilter(@Nullable Direction side, IO io) { /** * Gets the fluid filter for a specific side of this machine. - * + * * @param side Side * @param io The IO mode this filter should be applicable to. * @return A {@code Predicate} representing this filter @@ -1079,7 +1042,7 @@ public Predicate getFluidCapFilter(@Nullable Direction side, IO io) /** * Gets the item handler capability for a specific side of this machine - * + * * @param side The side * @param useCoverCapability Whether to return an item handler provided by an attached cover, if present. * @return The {@link IItemHandlerModifiable} capability, or null. @@ -1111,7 +1074,7 @@ public IItemHandlerModifiable getItemHandlerCap(@Nullable Direction side, boolea /** * Gets the fluid handler capability for a specific side of this machine - * + * * @param side The side * @param useCoverCapability Whether to return a fluid handler provided by an attached cover, if present. * @return The {@link IFluidHandlerModifiable} capability, or null. diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/SimpleGeneratorMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/SimpleGeneratorMachine.java index 28afe1e2bfe..8183c0a87c1 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/SimpleGeneratorMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/SimpleGeneratorMachine.java @@ -3,40 +3,21 @@ import com.gregtechceu.gtceu.api.GTValues; import com.gregtechceu.gtceu.api.blockentity.BlockEntityCreationInfo; import com.gregtechceu.gtceu.api.capability.recipe.*; -import com.gregtechceu.gtceu.api.gui.editor.EditableMachineUI; -import com.gregtechceu.gtceu.api.machine.feature.IFancyUIMachine; import com.gregtechceu.gtceu.api.recipe.GTRecipe; -import com.gregtechceu.gtceu.api.recipe.GTRecipeType; import com.gregtechceu.gtceu.api.recipe.content.ContentModifier; import com.gregtechceu.gtceu.api.recipe.modifier.ModifierFunction; import com.gregtechceu.gtceu.api.recipe.modifier.ParallelLogic; import com.gregtechceu.gtceu.api.recipe.modifier.RecipeModifier; -import com.gregtechceu.gtceu.api.recipe.ui.GTRecipeTypeUI; import com.gregtechceu.gtceu.common.data.GTMedicalConditions; import com.gregtechceu.gtceu.common.machine.trait.hazard.EnvironmentalHazardEmitterTrait; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.utils.Position; -import com.lowdragmc.lowdraglib.utils.Size; - -import net.minecraft.Util; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; - -import com.google.common.collect.Tables; import it.unimi.dsi.fastutil.ints.Int2IntFunction; import lombok.Getter; -import java.util.Collections; -import java.util.EnumMap; -import java.util.LinkedHashMap; -import java.util.function.BiFunction; - /** * All singleblock generators are implemented here. */ -public class SimpleGeneratorMachine extends WorkableTieredMachine - implements IFancyUIMachine { +public class SimpleGeneratorMachine extends WorkableTieredMachine { @Getter private final EnvironmentalHazardEmitterTrait hazardEmitter; @@ -124,40 +105,4 @@ public void afterWorking() { public long getDisplayRecipeVoltage() { return GTValues.V[this.tier]; } - - ////////////////////////////////////// - // *********** GUI ***********// - ////////////////////////////////////// - - @SuppressWarnings("UnstableApiUsage") - public static BiFunction EDITABLE_UI_CREATOR = Util - .memoize((path, recipeType) -> new EditableMachineUI("generator", path, () -> { - WidgetGroup template = recipeType.getRecipeUI().createEditableUITemplate(false, false).createDefault(); - WidgetGroup group = new WidgetGroup(0, 0, template.getSize().width + 4 + 8, - template.getSize().height + 8); - Size size = group.getSize(); - template.setSelfPosition(new Position( - (size.width - 4 - template.getSize().width) / 2 + 4, - (size.height - template.getSize().height) / 2)); - group.addWidget(template); - return group; - }, (template, machine) -> { - if (machine instanceof SimpleGeneratorMachine generatorMachine) { - var storages = Tables.newCustomTable(new EnumMap<>(IO.class), - LinkedHashMap, Object>::new); - storages.put(IO.IN, ItemRecipeCapability.CAP, generatorMachine.importItems.storage); - storages.put(IO.OUT, ItemRecipeCapability.CAP, generatorMachine.exportItems.storage); - storages.put(IO.IN, FluidRecipeCapability.CAP, generatorMachine.importFluids); - storages.put(IO.OUT, FluidRecipeCapability.CAP, generatorMachine.exportFluids); - - generatorMachine.getRecipeType().getRecipeUI().createEditableUITemplate(false, false).setupUI( - template, - new GTRecipeTypeUI.RecipeHolder(generatorMachine.recipeLogic::getProgressPercent, - storages, - new CompoundTag(), - Collections.emptyList(), - false, false)); - createEnergyBar().setupUI(template, generatorMachine); - } - })); } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/SimpleTieredMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/SimpleTieredMachine.java index 077803826a6..a6e94605482 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/SimpleTieredMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/SimpleTieredMachine.java @@ -4,42 +4,17 @@ import com.gregtechceu.gtceu.api.blockentity.BlockEntityCreationInfo; import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; import com.gregtechceu.gtceu.api.capability.recipe.*; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.editor.EditableMachineUI; -import com.gregtechceu.gtceu.api.gui.editor.EditableUI; -import com.gregtechceu.gtceu.api.gui.fancy.ConfiguratorPanel; -import com.gregtechceu.gtceu.api.gui.fancy.IFancyConfigurator; -import com.gregtechceu.gtceu.api.gui.fancy.IFancyConfiguratorButton; -import com.gregtechceu.gtceu.api.gui.widget.GhostCircuitSlotWidget; -import com.gregtechceu.gtceu.api.gui.widget.SlotWidget; -import com.gregtechceu.gtceu.api.machine.fancyconfigurator.CircuitFancyConfigurator; -import com.gregtechceu.gtceu.api.machine.feature.IFancyUIMachine; +import com.gregtechceu.gtceu.api.machine.feature.IHasBatterySlot; import com.gregtechceu.gtceu.api.machine.feature.IHasCircuitSlot; import com.gregtechceu.gtceu.api.machine.trait.NotifiableItemStackHandler; -import com.gregtechceu.gtceu.api.recipe.GTRecipeType; -import com.gregtechceu.gtceu.api.recipe.ui.GTRecipeTypeUI; import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField; import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; import com.gregtechceu.gtceu.api.transfer.item.CustomItemStackHandler; import com.gregtechceu.gtceu.common.item.behavior.IntCircuitBehaviour; import com.gregtechceu.gtceu.common.machine.trait.AutoOutputTrait; import com.gregtechceu.gtceu.config.ConfigHolder; -import com.gregtechceu.gtceu.data.lang.LangHandler; import com.gregtechceu.gtceu.utils.ISubscription; -import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; -import com.lowdragmc.lowdraglib.gui.util.ClickData; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.utils.Position; - -import net.minecraft.Util; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; - -import com.google.common.collect.Tables; import it.unimi.dsi.fastutil.ints.Int2IntFunction; import lombok.Getter; import org.jetbrains.annotations.Nullable; @@ -51,7 +26,7 @@ * All simple single machines are implemented here. */ public class SimpleTieredMachine extends WorkableTieredMachine - implements IFancyUIMachine, IHasCircuitSlot { + implements IHasCircuitSlot, IHasBatterySlot { @Getter @SaveField @@ -134,151 +109,12 @@ public void onMachineDestroyed() { chargerInventory.dropInventoryInWorld(getLevel(), getBlockPos()); } - /// ////////////////////////////////// + ///////////////////////////////////// // ****** RECIPE LOGIC *******// - /// ////////////////////////////////// + ///////////////////////////////////// @Override public long getDisplayRecipeVoltage() { return GTValues.V[this.tier]; } - - ////////////////////////////////////// - // *********** GUI ***********// - ////////////////////////////////////// - - @Override - public void attachConfigurators(ConfiguratorPanel configuratorPanel) { - IFancyUIMachine.super.attachConfigurators(configuratorPanel); - - if (autoOutput.supportsAutoOutputFluids()) { - configuratorPanel.attachConfigurators(createAutoOutputFluidConfigurator()); - } - if (autoOutput.supportsAutoOutputItems()) { - configuratorPanel.attachConfigurators(createAutoOutputItemConfigurator()); - } - - if (isCircuitSlotEnabled()) { - configuratorPanel.attachConfigurators(new CircuitFancyConfigurator(circuitInventory.storage)); - } - } - - private IFancyConfigurator createAutoOutputFluidConfigurator() { - return createAutoOutputConfigurator( - GuiTextures.IO_CONFIG_FLUID_MODES_BUTTON, - "gtceu.gui.fluid_auto_output", - this.autoOutput::isAutoOutputFluids, - (cd, nextState) -> this.autoOutput.setAllowAutoOutputFluids(nextState)); - } - - private IFancyConfigurator createAutoOutputItemConfigurator() { - return createAutoOutputConfigurator( - GuiTextures.IO_CONFIG_ITEM_MODES_BUTTON, - "gtceu.gui.item_auto_output", - this.autoOutput::isAutoOutputItems, - (cd, nextState) -> this.autoOutput.setAllowAutoOutputItems(nextState)); - } - - private IFancyConfigurator createAutoOutputConfigurator(ResourceTexture modesButtonTexture, - String tooltipBaseLangKey, - BooleanSupplier stateSupplier, - BiConsumer onToggle) { - var toggle = new IFancyConfiguratorButton.Toggle( - new GuiTextureGroup( - GuiTextures.TOGGLE_BUTTON_BACK.getSubTexture(0, 0, 1, 0.5), - modesButtonTexture.getSubTexture(0, 1 / 3f, 1, 1 / 3f)), - new GuiTextureGroup( - GuiTextures.TOGGLE_BUTTON_BACK.getSubTexture(0, 0.5, 1, 0.5), - modesButtonTexture.getSubTexture(0, 2 / 3f, 1, 1 / 3f)), - stateSupplier, - onToggle); - - toggle.setTooltipsSupplier(enabled -> { - var key = tooltipBaseLangKey + '.' + (enabled ? "enabled" : "disabled"); - return List.of(Component.translatable(key)); - }); - - return toggle; - } - - @SuppressWarnings("UnstableApiUsage") - public static BiFunction EDITABLE_UI_CREATOR = Util - .memoize((path, recipeType) -> new EditableMachineUI("simple", path, () -> { - WidgetGroup template = recipeType.getRecipeUI().createEditableUITemplate(false, false).createDefault(); - SlotWidget batterySlot = createBatterySlot().createDefault(); - WidgetGroup group = new WidgetGroup(0, 0, template.getSize().width, - Math.max(template.getSize().height, 78)); - template.setSelfPosition(new Position(0, (group.getSize().height - template.getSize().height) / 2)); - batterySlot.setSelfPosition(new Position(group.getSize().width / 2 - 9, group.getSize().height - 18)); - group.addWidget(batterySlot); - group.addWidget(template); - - // TODO fix this. - // if (ConfigHolder.INSTANCE.machines.ghostCircuit) { - // SlotWidget circuitSlot = createCircuitConfigurator().createDefault(); - // circuitSlot.setSelfPosition(new Position(120, 62)); - // group.addWidget(circuitSlot); - // } - - return group; - }, (template, machine) -> { - if (machine instanceof SimpleTieredMachine tieredMachine) { - var storages = Tables.newCustomTable(new EnumMap<>(IO.class), - LinkedHashMap, Object>::new); - storages.put(IO.IN, ItemRecipeCapability.CAP, tieredMachine.importItems.storage); - storages.put(IO.OUT, ItemRecipeCapability.CAP, tieredMachine.exportItems.storage); - storages.put(IO.IN, FluidRecipeCapability.CAP, tieredMachine.importFluids); - storages.put(IO.OUT, FluidRecipeCapability.CAP, tieredMachine.exportFluids); - storages.put(IO.IN, CWURecipeCapability.CAP, tieredMachine.importComputation); - storages.put(IO.OUT, CWURecipeCapability.CAP, tieredMachine.exportComputation); - - tieredMachine.getRecipeType().getRecipeUI().createEditableUITemplate(false, false).setupUI(template, - new GTRecipeTypeUI.RecipeHolder(tieredMachine.recipeLogic::getProgressPercent, - storages, - new CompoundTag(), - Collections.emptyList(), - false, false)); - createBatterySlot().setupUI(template, tieredMachine); - // createCircuitConfigurator().setupUI(template, tieredMachine); - } - })); - - /** - * Create a battery slot widget. - */ - protected static EditableUI createBatterySlot() { - return new EditableUI<>("battery_slot", SlotWidget.class, () -> { - var slotWidget = new SlotWidget(); - slotWidget.setBackground(GuiTextures.SLOT, GuiTextures.CHARGER_OVERLAY); - return slotWidget; - }, (slotWidget, machine) -> { - slotWidget.setHandlerSlot(machine.chargerInventory, 0); - slotWidget.setCanPutItems(true); - slotWidget.setCanTakeItems(true); - slotWidget.setHoverTooltips(LangHandler.getMultiLang("gtceu.gui.charger_slot.tooltip", - GTValues.VNF[machine.getTier()], GTValues.VNF[machine.getTier()]).toArray(Component[]::new)); - }); - } - - /** - * Create a ghost circuit slot widget. - */ - protected static EditableUI createCircuitConfigurator() { - return new EditableUI<>("circuit_configurator", GhostCircuitSlotWidget.class, () -> { - var slotWidget = new GhostCircuitSlotWidget(); - slotWidget.setBackground(GuiTextures.SLOT, GuiTextures.INT_CIRCUIT_OVERLAY); - return slotWidget; - }, (slotWidget, machine) -> { - slotWidget.setCircuitInventory(machine.circuitInventory); - slotWidget.setCanPutItems(false); - slotWidget.setCanTakeItems(false); - slotWidget.setHoverTooltips( - LangHandler.getMultiLang("gtceu.gui.configurator_slot.tooltip").toArray(Component[]::new)); - }); - } - - // Method provided to override - protected IGuiTexture getCircuitSlotOverlay() { - return GuiTextures.INT_CIRCUIT_OVERLAY; - } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/TieredEnergyMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/TieredEnergyMachine.java index c6236776f7c..bdcdeb674fc 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/TieredEnergyMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/TieredEnergyMachine.java @@ -2,17 +2,11 @@ import com.gregtechceu.gtceu.api.GTValues; import com.gregtechceu.gtceu.api.blockentity.BlockEntityCreationInfo; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.editor.EditableUI; import com.gregtechceu.gtceu.api.machine.trait.NotifiableEnergyContainer; import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField; import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; import com.gregtechceu.gtceu.common.machine.trait.EnvironmentalExplosionTrait; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.ProgressTexture; -import com.lowdragmc.lowdraglib.gui.widget.ProgressWidget; - import net.minecraft.util.Mth; import lombok.Getter; @@ -92,18 +86,4 @@ protected long getMaxInputOutputAmperage() { protected boolean isEnergyEmitter() { return false; } - - /** - * Create an energy bar widget. - */ - protected static EditableUI createEnergyBar() { - return new EditableUI<>("energy_container", ProgressWidget.class, () -> { - var progressBar = new ProgressWidget(ProgressWidget.JEIProgress, 0, 0, 18, 60, - new ProgressTexture(IGuiTexture.EMPTY, GuiTextures.ENERGY_BAR_BASE)); - progressBar.setFillDirection(ProgressTexture.FillDirection.DOWN_TO_UP); - progressBar.setBackground(GuiTextures.ENERGY_BAR_BACKGROUND); - return progressBar; - }, (progressBar, machine) -> progressBar.setProgressSupplier( - () -> machine.energyContainer.getEnergyStored() * 1d / machine.energyContainer.getEnergyCapacity())); - } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/WorkableTieredMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/WorkableTieredMachine.java index f5b2553f098..1ef33be41b7 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/WorkableTieredMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/WorkableTieredMachine.java @@ -95,7 +95,7 @@ public WorkableTieredMachine(BlockEntityCreationInfo info, int tier, Int2IntFunc this.recipeLogic = attachTrait(new RecipeLogic()); this.importItems = attachTrait( new NotifiableItemStackHandler(getRecipeType().getMaxInputs(ItemRecipeCapability.CAP), - IO.IN)); + IO.IN, IO.BOTH)); this.exportItems = attachTrait( new NotifiableItemStackHandler(getRecipeType().getMaxOutputs(ItemRecipeCapability.CAP), IO.OUT)); diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/AutoStockingFancyConfigurator.java b/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/AutoStockingFancyConfigurator.java deleted file mode 100644 index 94620e8736c..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/AutoStockingFancyConfigurator.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.gregtechceu.gtceu.api.machine.fancyconfigurator; - -import com.gregtechceu.gtceu.api.gui.fancy.IFancyConfigurator; -import com.gregtechceu.gtceu.api.gui.widget.IntInputWidget; -import com.gregtechceu.gtceu.common.data.GTItems; -import com.gregtechceu.gtceu.config.ConfigHolder; -import com.gregtechceu.gtceu.integration.ae2.machine.MEStockingBusPartMachine; -import com.gregtechceu.gtceu.integration.ae2.machine.feature.multiblock.IMEStockingPart; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.ItemStackTexture; -import com.lowdragmc.lowdraglib.gui.widget.LabelWidget; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - -import net.minecraft.network.chat.Component; - -public class AutoStockingFancyConfigurator implements IFancyConfigurator { - - private IMEStockingPart machine; - - public AutoStockingFancyConfigurator(IMEStockingPart machine) { - this.machine = machine; - } - - @Override - public Component getTitle() { - return Component.translatable("gtceu.gui.adv_stocking_config.title"); - } - - @Override - public IGuiTexture getIcon() { - return new ItemStackTexture(GTItems.TOOL_DATA_STICK.asStack()); - } - - @Override - public Widget createConfigurator() { - var group = new WidgetGroup(0, 0, 90, 70); - - String suffix = machine instanceof MEStockingBusPartMachine ? "min_item_count" : "min_fluid_count"; - - group.addWidget(new LabelWidget(4, 2, "gtceu.gui.title.adv_stocking_config." + suffix)); - group.addWidget(new IntInputWidget(4, 12, 81, 14, machine::getMinStackSize, - machine::setMinStackSize).setMin(1) - .appendHoverTooltips(Component.translatable("gtceu.gui.adv_stocking_config." + suffix))); - group.addWidget(new LabelWidget(4, 36, "gtceu.gui.title.adv_stocking_config.ticks_per_cycle")); - group.addWidget(new IntInputWidget(4, 46, 81, 14, machine::getTicksPerCycle, - machine::setTicksPerCycle).setMin(ConfigHolder.INSTANCE.compat.ae2.updateIntervals) - .setHoverTooltips(Component.translatable("gtceu.gui.adv_stocking_config.ticks_per_cycle"))); - - return group; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/ButtonConfigurator.java b/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/ButtonConfigurator.java deleted file mode 100644 index 839da741dc9..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/ButtonConfigurator.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.gregtechceu.gtceu.api.machine.fancyconfigurator; - -import com.gregtechceu.gtceu.api.gui.fancy.IFancyConfiguratorButton; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.util.ClickData; - -import net.minecraft.network.chat.Component; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.util.Collections; -import java.util.List; -import java.util.function.Consumer; - -@Accessors(chain = true) -public class ButtonConfigurator implements IFancyConfiguratorButton { - - @Getter - protected IGuiTexture icon; - - protected Consumer onClick; - - @Getter - @Setter - protected List tooltips = Collections.emptyList(); - - public ButtonConfigurator(IGuiTexture texture, Consumer onClick) { - this.icon = texture; - this.onClick = onClick; - } - - @Override - public void onClick(ClickData clickData) { - onClick.accept(clickData); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/CircuitFancyConfigurator.java b/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/CircuitFancyConfigurator.java deleted file mode 100644 index dec55d9951c..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/CircuitFancyConfigurator.java +++ /dev/null @@ -1,201 +0,0 @@ -package com.gregtechceu.gtceu.api.machine.fancyconfigurator; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.IFancyConfigurator; -import com.gregtechceu.gtceu.api.gui.fancy.IFancyCustomMiddleClickAction; -import com.gregtechceu.gtceu.api.gui.fancy.IFancyCustomMouseWheelAction; -import com.gregtechceu.gtceu.api.gui.widget.SlotWidget; -import com.gregtechceu.gtceu.common.item.behavior.IntCircuitBehaviour; -import com.gregtechceu.gtceu.config.ConfigHolder; -import com.gregtechceu.gtceu.data.lang.LangHandler; - -import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.ItemStackTexture; -import com.lowdragmc.lowdraglib.gui.widget.ButtonWidget; -import com.lowdragmc.lowdraglib.gui.widget.LabelWidget; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraftforge.items.ItemStackHandler; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -public class CircuitFancyConfigurator implements IFancyConfigurator, IFancyCustomMouseWheelAction, - IFancyCustomMiddleClickAction { - - private static final int SET_TO_ZERO = 2; - private static final int SET_TO_EMPTY = 3; - private static final int SET_TO_N = 4; - - private static final int NO_CONFIG = -1; - - final ItemStackHandler circuitSlot; - - public CircuitFancyConfigurator(ItemStackHandler circuitSlot) { - this.circuitSlot = circuitSlot; - } - - @Override - public Component getTitle() { - return Component.translatable("gtceu.gui.circuit.title"); - } - - @Override - public IGuiTexture getIcon() { - if (IntCircuitBehaviour.isIntegratedCircuit(circuitSlot.getStackInSlot(0))) { - return new ItemStackTexture(circuitSlot.getStackInSlot(0)); - } - return new GuiTextureGroup(new ItemStackTexture(IntCircuitBehaviour.stack(0)), - new ItemStackTexture(Items.BARRIER)); - } - - @Override - public boolean mouseWheelMove(BiConsumer> writeClientAction, double mouseX, - double mouseY, double wheelDelta) { - if (wheelDelta == 0) return false; - if (!ConfigHolder.INSTANCE.machines.ghostCircuit && circuitSlot.getStackInSlot(0).isEmpty()) return false; - int nextValue = getNextValue(wheelDelta > 0); - if (nextValue == NO_CONFIG) { - if (ConfigHolder.INSTANCE.machines.ghostCircuit) { - circuitSlot.setStackInSlot(0, ItemStack.EMPTY); - writeClientAction.accept(SET_TO_EMPTY, buf -> {}); - } - } else { - circuitSlot.setStackInSlot(0, IntCircuitBehaviour.stack(nextValue)); - writeClientAction.accept(SET_TO_N, buf -> buf.writeVarInt(nextValue)); - } - return true; - } - - @Override - public void handleClientAction(int id, FriendlyByteBuf buffer) { - switch (id) { - case SET_TO_ZERO -> { - if (ConfigHolder.INSTANCE.machines.ghostCircuit || !circuitSlot.getStackInSlot(0).isEmpty()) - circuitSlot.setStackInSlot(0, IntCircuitBehaviour.stack(0)); - } - case SET_TO_EMPTY -> { - if (ConfigHolder.INSTANCE.machines.ghostCircuit || circuitSlot.getStackInSlot(0).isEmpty()) - circuitSlot.setStackInSlot(0, ItemStack.EMPTY); - else - circuitSlot.setStackInSlot(0, IntCircuitBehaviour.stack(0)); - } - case SET_TO_N -> { - if (ConfigHolder.INSTANCE.machines.ghostCircuit || !circuitSlot.getStackInSlot(0).isEmpty()) - circuitSlot.setStackInSlot(0, IntCircuitBehaviour.stack(buffer.readVarInt())); - } - } - } - - @Override - public void onMiddleClick(BiConsumer> writeClientAction) { - if (!ConfigHolder.INSTANCE.machines.ghostCircuit && !circuitSlot.getStackInSlot(0).isEmpty()) - circuitSlot.setStackInSlot(0, IntCircuitBehaviour.stack(0)); - else - circuitSlot.setStackInSlot(0, ItemStack.EMPTY); - writeClientAction.accept(SET_TO_EMPTY, buf -> {}); - } - - @Override - public Widget createConfigurator() { - var group = new WidgetGroup(0, 0, 174, 132); - group.addWidget(new LabelWidget(9, 8, "Programmed Circuit Configuration")); - group.addWidget(new SlotWidget(circuitSlot, 0, (group.getSize().width - 18) / 2, 20, - !ConfigHolder.INSTANCE.machines.ghostCircuit, !ConfigHolder.INSTANCE.machines.ghostCircuit) - .setBackground(new GuiTextureGroup(GuiTextures.SLOT, GuiTextures.INT_CIRCUIT_OVERLAY))); - if (ConfigHolder.INSTANCE.machines.ghostCircuit) { - group.addWidget(new ButtonWidget((group.getSize().width - 18) / 2, 20, 18, 18, IGuiTexture.EMPTY, - clickData -> { - if (!clickData.isRemote) { - circuitSlot.setStackInSlot(0, ItemStack.EMPTY); - } - })); - } - int idx = 0; - for (int x = 0; x <= 2; x++) { - for (int y = 0; y <= 8; y++) { - int finalIdx = idx; - group.addWidget(new ButtonWidget(5 + (18 * y), 48 + (18 * x), 18, 18, - new GuiTextureGroup(GuiTextures.SLOT, - new ItemStackTexture(IntCircuitBehaviour.stack(finalIdx)).scale(16f / 18)), - clickData -> { - if (!clickData.isRemote) { - ItemStack stack = circuitSlot.getStackInSlot(0).copy(); - if (IntCircuitBehaviour.isIntegratedCircuit(stack)) { - IntCircuitBehaviour.setCircuitConfiguration(stack, finalIdx); - circuitSlot.setStackInSlot(0, stack); - } else if (ConfigHolder.INSTANCE.machines.ghostCircuit) { - circuitSlot.setStackInSlot(0, IntCircuitBehaviour.stack(finalIdx)); - } - } - })); - idx++; - } - } - for (int x = 0; x <= 5; x++) { - int finalIdx = x + 27; - group.addWidget(new ButtonWidget(5 + (18 * x), 102, 18, 18, - new GuiTextureGroup(GuiTextures.SLOT, - new ItemStackTexture(IntCircuitBehaviour.stack(finalIdx)).scale(16f / 18)), - clickData -> { - if (!clickData.isRemote) { - ItemStack stack = circuitSlot.getStackInSlot(0).copy(); - if (IntCircuitBehaviour.isIntegratedCircuit(stack)) { - IntCircuitBehaviour.setCircuitConfiguration(stack, finalIdx); - circuitSlot.setStackInSlot(0, stack); - } else if (ConfigHolder.INSTANCE.machines.ghostCircuit) { - circuitSlot.setStackInSlot(0, IntCircuitBehaviour.stack(finalIdx)); - } - } - })); - } - return group; - } - - @Override - public List getTooltips() { - var list = new ArrayList<>(IFancyConfigurator.super.getTooltips()); - list.addAll(Arrays.stream( - LangHandler.getMultiLang("gtceu.gui.configurator_slot.tooltip").toArray(new MutableComponent[0])) - .toList()); - return list; - } - - private int getNextValue(boolean increment) { - int currentValue = IntCircuitBehaviour.getCircuitConfiguration(circuitSlot.getStackInSlot(0)); - if (increment) { - // if at max, loop around to no circuit - if (currentValue == IntCircuitBehaviour.CIRCUIT_MAX) { - return 0; - } - // if at no circuit, skip 0 and return 1 - if (this.circuitSlot.getStackInSlot(0).isEmpty()) { - return 1; - } - // normal case: increment by 1 - return currentValue + 1; - } else { - // if at no circuit, loop around to max - if (this.circuitSlot.getStackInSlot(0).isEmpty() || - (currentValue == 0 && !ConfigHolder.INSTANCE.machines.ghostCircuit)) { - return IntCircuitBehaviour.CIRCUIT_MAX; - } - // if at 1, skip 0 and return no circuit - if (currentValue == 1 && ConfigHolder.INSTANCE.machines.ghostCircuit) { - return -1; - } - // normal case: decrement by 1 - return currentValue - 1; - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/CombinedDirectionalFancyConfigurator.java b/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/CombinedDirectionalFancyConfigurator.java deleted file mode 100644 index c46b0c93dad..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/CombinedDirectionalFancyConfigurator.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.gregtechceu.gtceu.api.machine.fancyconfigurator; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.WidgetUtils; -import com.gregtechceu.gtceu.api.gui.fancy.FancyMachineUIWidget; -import com.gregtechceu.gtceu.api.gui.fancy.IFancyUIProvider; -import com.gregtechceu.gtceu.api.gui.widget.directional.CombinedDirectionalConfigurator; -import com.gregtechceu.gtceu.api.gui.widget.directional.IDirectionalConfigHandler; -import com.gregtechceu.gtceu.api.gui.widget.directional.handlers.AutoOutputFluidConfigHandler; -import com.gregtechceu.gtceu.api.gui.widget.directional.handlers.AutoOutputItemConfigHandler; -import com.gregtechceu.gtceu.api.gui.widget.directional.handlers.CoverableConfigHandler; -import com.gregtechceu.gtceu.api.machine.MetaMachine; -import com.gregtechceu.gtceu.common.machine.trait.AutoOutputTrait; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.utils.Size; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.network.chat.Component; - -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import java.util.function.Supplier; - -import javax.annotation.ParametersAreNonnullByDefault; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class CombinedDirectionalFancyConfigurator implements IFancyUIProvider { - - private final List> configs; - private final MetaMachine machine; - - public CombinedDirectionalFancyConfigurator(List> configs, - MetaMachine machine) { - this.configs = configs; - this.machine = machine; - } - - @Override - public Widget createMainPage(FancyMachineUIWidget widget) { - Size parentSize = widget.getSize(); - return new CombinedDirectionalConfigurator( - widget, configs.stream().map(Supplier::get).toArray(IDirectionalConfigHandler[]::new), machine, - parentSize.width - 8, - parentSize.height - WidgetUtils.getInventoryHeight(true)); - } - - @Override - public IGuiTexture getTabIcon() { - return GuiTextures.TOOL_COVER_SETTINGS; - } - - @Override - public Component getTitle() { - return Component.translatable("gtceu.gui.directional_setting.title"); - } - - @Override - public List getTabTooltips() { - List tooltip = new ArrayList<>(); - tooltip.add(Component.translatable("gtceu.gui.directional_setting.tab_tooltip")); - return tooltip; - } - - // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - private static final List>> CONFIG_HANDLERS = new ArrayList<>(); - - static { - // Left side: - CONFIG_HANDLERS.add( - machine -> { - var trait = machine.getTraitHolder().getTrait(AutoOutputTrait.TYPE); - return trait != null && trait.supportsAutoOutputItems() ? - () -> new AutoOutputItemConfigHandler(trait) : null; - }); - CONFIG_HANDLERS.add( - machine -> { - var trait = machine.getTraitHolder().getTrait(AutoOutputTrait.TYPE); - return trait != null && trait.supportsAutoOutputFluids() ? - () -> new AutoOutputFluidConfigHandler(trait) : null; - }); - - // Right side: - CONFIG_HANDLERS.add(machine -> () -> new CoverableConfigHandler(machine.getCoverContainer())); - } - - /** - * To be used by addons for registering their own directional configurations - */ - public static void registerConfigHandler(Function> factory) { - CONFIG_HANDLERS.add(factory); - } - - @Nullable - public static CombinedDirectionalFancyConfigurator of(MetaMachine container, MetaMachine machine) { - var configs = CONFIG_HANDLERS.stream() - .map(handler -> handler.apply(container)) - .filter(Objects::nonNull) - .toList(); - - return configs.isEmpty() ? null : new CombinedDirectionalFancyConfigurator(configs, machine); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/FancyInvConfigurator.java b/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/FancyInvConfigurator.java deleted file mode 100644 index 9d3efb6993b..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/FancyInvConfigurator.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.gregtechceu.gtceu.api.machine.fancyconfigurator; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.IFancyConfigurator; -import com.gregtechceu.gtceu.api.gui.widget.SlotWidget; -import com.gregtechceu.gtceu.api.transfer.item.CustomItemStackHandler; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.jei.IngredientIO; - -import net.minecraft.network.chat.Component; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.util.Collections; -import java.util.List; - -@Accessors(chain = true) -public class FancyInvConfigurator implements IFancyConfigurator { - - private final CustomItemStackHandler inventory; - - @Getter - private final Component title; - - @Getter - @Setter - private List tooltips = Collections.emptyList(); - - public FancyInvConfigurator(CustomItemStackHandler inventory, Component title) { - this.inventory = inventory; - this.title = title; - } - - @Override - public IGuiTexture getIcon() { - return GuiTextures.BUTTON_ITEM_OUTPUT; - } - - @Override - public Widget createConfigurator() { - int rowSize = (int) Math.sqrt(inventory.getSlots()); - int colSize = rowSize; - if (inventory.getSlots() == 8) { - rowSize = 4; - colSize = 2; - } - var group = new WidgetGroup(0, 0, 18 * rowSize + 16, 18 * colSize + 16); - var container = new WidgetGroup(4, 4, 18 * rowSize + 8, 18 * colSize + 8); - int index = 0; - for (int y = 0; y < colSize; y++) { - for (int x = 0; x < rowSize; x++) { - container.addWidget(new SlotWidget(inventory, index++, 4 + x * 18, 4 + y * 18, true, true) - .setBackgroundTexture(GuiTextures.SLOT) - .setIngredientIO(IngredientIO.INPUT)); - } - } - - container.setBackground(GuiTextures.BACKGROUND_INVERSE); - group.addWidget(container); - - return group; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/FancySelectorConfigurator.java b/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/FancySelectorConfigurator.java deleted file mode 100644 index 5b89d526cdc..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/FancySelectorConfigurator.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.gregtechceu.gtceu.api.machine.fancyconfigurator; - -import com.gregtechceu.gtceu.api.gui.fancy.IFancyConfiguratorButton; -import com.gregtechceu.gtceu.api.gui.widget.EnumSelectorWidget; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.util.ClickData; - -import net.minecraft.network.chat.Component; - -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.util.Collections; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; - -public class FancySelectorConfigurator & EnumSelectorWidget.SelectableEnum> - implements IFancyConfiguratorButton { - - private final EnumSelectorWidget widget; - - @Setter - @Accessors(chain = true) - private Function> tooltip = t -> Collections.singletonList(Component.empty()); - - public FancySelectorConfigurator(T[] values, T initialValue, Consumer onChanged) { - this.widget = new EnumSelectorWidget<>(0, 0, 20, 20, values, initialValue, onChanged); - } - - @Override - public IGuiTexture getIcon() { - return widget.getTexture(widget.selected); - } - - @Override - public List getTooltips() { - return this.tooltip.apply(widget.getCurrentValue()); - } - - @Override - public void onClick(ClickData clickData) { - ++widget.selected; - if (widget.selected >= widget.values.size()) { - widget.selected = 0; - } - - widget.buttonWidget.setIndex(widget.selected); - if (widget.onChanged != null) { - widget.onChanged.accept(widget.getCurrentValue()); - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/FancyTankConfigurator.java b/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/FancyTankConfigurator.java deleted file mode 100644 index ffde47feb4c..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/FancyTankConfigurator.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.gregtechceu.gtceu.api.machine.fancyconfigurator; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.IFancyConfigurator; -import com.gregtechceu.gtceu.api.gui.widget.TankWidget; -import com.gregtechceu.gtceu.api.transfer.fluid.CustomFluidTank; - -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - -import net.minecraft.network.chat.Component; - -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; - -import java.util.Collections; -import java.util.List; - -@Accessors(chain = true) -public class FancyTankConfigurator implements IFancyConfigurator { - - private final CustomFluidTank[] tanks; - - @Getter - private final Component title; - - @Getter - @Setter - private List tooltips = Collections.emptyList(); - - public FancyTankConfigurator(CustomFluidTank[] tanks, Component title) { - this.tanks = tanks; - this.title = title; - } - - @Override - public IGuiTexture getIcon() { - return GuiTextures.BUTTON_FLUID_OUTPUT; - } - - @Override - public Widget createConfigurator() { - int rowSize = (int) Math.sqrt(tanks.length); - int colSize = rowSize; - if (tanks.length == 8) { - rowSize = 4; - colSize = 2; - } - - var group = new WidgetGroup(0, 0, 18 * rowSize + 16, 18 * colSize + 16); - var container = new WidgetGroup(4, 4, 18 * rowSize + 8, 18 * colSize + 8); - - int index = 0; - for (int y = 0; y < colSize; y++) { - for (int x = 0; x < rowSize; x++) { - container.addWidget(new TankWidget(tanks[index++], 4 + x * 18, 4 + y * 18, true, true) - .setBackground(GuiTextures.FLUID_SLOT)); - } - } - - container.setBackground(GuiTextures.BACKGROUND_INVERSE); - group.addWidget(container); - - return group; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/MachineModeFancyConfigurator.java b/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/MachineModeFancyConfigurator.java deleted file mode 100644 index ae205e44c95..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/fancyconfigurator/MachineModeFancyConfigurator.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.gregtechceu.gtceu.api.machine.fancyconfigurator; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.FancyMachineUIWidget; -import com.gregtechceu.gtceu.api.gui.fancy.IFancyUIProvider; -import com.gregtechceu.gtceu.api.machine.feature.IRecipeLogicMachine; -import com.gregtechceu.gtceu.common.data.GTItems; - -import com.lowdragmc.lowdraglib.gui.editor.ColorPattern; -import com.lowdragmc.lowdraglib.gui.texture.*; -import com.lowdragmc.lowdraglib.gui.widget.ButtonWidget; -import com.lowdragmc.lowdraglib.gui.widget.ImageWidget; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; - -import java.util.ArrayList; -import java.util.List; - -public class MachineModeFancyConfigurator implements IFancyUIProvider { - - protected IRecipeLogicMachine machine; - - public MachineModeFancyConfigurator(IRecipeLogicMachine machine) { - this.machine = machine; - } - - @Override - public Component getTitle() { - return Component.translatable("gtceu.gui.machinemode.title"); - } - - @Override - public IGuiTexture getTabIcon() { - return new ItemStackTexture(GTItems.ROBOT_ARM_LV.get()); - } - - @Override - public Widget createMainPage(FancyMachineUIWidget widget) { - var group = new MachineModeConfigurator(0, 0, 140, 20 * machine.getRecipeTypes().length + 4); - group.setBackground(GuiTextures.BACKGROUND_INVERSE); - for (int i = 0; i < machine.getRecipeTypes().length; i++) { - int finalI = i; - group.addWidget(new ButtonWidget(2, 2 + i * 20, 136, 20, IGuiTexture.EMPTY, - cd -> setActiveRecipeTypeAndUpdateTickSubs(finalI))); - group.addWidget(new ImageWidget(2, 2 + i * 20, 136, 20, - () -> new GuiTextureGroup( - ResourceBorderTexture.BUTTON_COMMON.copy() - .setColor(machine.getActiveRecipeType() == finalI ? ColorPattern.CYAN.color : -1), - new TextTexture(machine.getRecipeTypes()[finalI].registryName.toLanguageKey()).setWidth(136) - .setType(TextTexture.TextType.ROLL)))); - - } - return group; - } - - @Override - public List getTabTooltips() { - List tooltip = new ArrayList<>(); - tooltip.add(Component.translatable("gtceu.gui.machinemode.tab_tooltip")); - return tooltip; - } - - private void setActiveRecipeTypeAndUpdateTickSubs(int activeRecipeType) { - boolean needUpdateTickSubs = !machine.keepSubscribing() && activeRecipeType != machine.getActiveRecipeType(); - machine.setActiveRecipeType(activeRecipeType); - if (needUpdateTickSubs) { - machine.getRecipeLogic().updateTickSubscription(); - } - } - - public class MachineModeConfigurator extends WidgetGroup { - - public MachineModeConfigurator(int x, int y, int width, int height) { - super(x, y, width, height); - } - - @Override - public void writeInitialData(FriendlyByteBuf buffer) { - buffer.writeVarInt(machine.getActiveRecipeType()); - } - - @Override - public void readInitialData(FriendlyByteBuf buffer) { - machine.setActiveRecipeType(buffer.readVarInt()); - } - - @Override - public void detectAndSendChanges() { - this.writeUpdateInfo(0, buf -> buf.writeVarInt(machine.getActiveRecipeType())); - } - - @Override - public void readUpdateInfo(int id, FriendlyByteBuf buffer) { - if (id == 0) { - machine.setActiveRecipeType(buffer.readVarInt()); - } - } - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IFancyUIMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IFancyUIMachine.java deleted file mode 100644 index d7dc3b46867..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IFancyUIMachine.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.gregtechceu.gtceu.api.machine.feature; - -import com.gregtechceu.gtceu.api.capability.IControllable; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.*; -import com.gregtechceu.gtceu.api.machine.MetaMachine; -import com.gregtechceu.gtceu.api.machine.fancyconfigurator.CombinedDirectionalFancyConfigurator; -import com.gregtechceu.gtceu.api.machine.fancyconfigurator.MachineModeFancyConfigurator; - -import com.lowdragmc.lowdraglib.gui.modular.ModularUI; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.texture.ItemStackTexture; -import com.lowdragmc.lowdraglib.gui.widget.ImageWidget; -import com.lowdragmc.lowdraglib.gui.widget.SceneWidget; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.utils.BlockInfo; -import com.lowdragmc.lowdraglib.utils.TrackedDummyWorld; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; - -public interface IFancyUIMachine extends IUIMachine, IFancyUIProvider { - - @Override - default ModularUI createUI(Player entityPlayer) { - return new ModularUI(176, 166, this, entityPlayer).widget(new FancyMachineUIWidget(this, 176, 166)); - } - - /** - * We should not override this method in general, and use {@link IFancyUIMachine#createUIWidget()} instead, - */ - @Override - default Widget createMainPage(FancyMachineUIWidget widget) { - var editableUI = self().getDefinition().getEditableUI(); - if (editableUI != null) { - var template = editableUI.createCustomUI(); - if (template == null) { - template = editableUI.createDefault(); - } - editableUI.setupUI(template, self()); - return template; - } - return createUIWidget(); - } - - /** - * Create the core widget of this machine. - */ - default Widget createUIWidget() { - var group = new WidgetGroup(0, 0, 100, 100); - if (isRemote()) { - group.addWidget(new ImageWidget((100 - 48) / 2, 60, 48, 16, GuiTextures.SCENE)); - TrackedDummyWorld world = new TrackedDummyWorld(); - world.addBlock(BlockPos.ZERO, BlockInfo.fromBlockState(self().getBlockState())); - SceneWidget sceneWidget = new SceneWidget(0, 0, 100, 100, world) { - - @Override - @OnlyIn(Dist.CLIENT) - public void drawInBackground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, - float partialTicks) { - // AUTO ROTATION - if (renderer != null) { - this.rotationPitch = (partialTicks + getGui().getTickCount()) * 2; - renderer.setCameraLookAt(this.center, 0.1f, Math.toRadians(this.rotationPitch), - Math.toRadians(this.rotationYaw)); - } - super.drawInBackground(graphics, mouseX, mouseY, partialTicks); - } - }; - sceneWidget.useOrtho(true) - .setOrthoRange(0.5f) - .setScalable(false) - .setDraggable(false) - .setRenderFacing(false) - .setRenderSelect(false); - sceneWidget.getRenderer().setFov(30); - group.addWidget(sceneWidget); - sceneWidget.setRenderedCore(List.of(BlockPos.ZERO), null); - } - return group; - } - - @Override - default IGuiTexture getTabIcon() { - return new ItemStackTexture(self().getDefinition().getItem()); - } - - @Override - default void attachSideTabs(TabsWidget sideTabs) { - sideTabs.setMainTab(this); - - if (this instanceof IRecipeLogicMachine rLMachine && rLMachine.getRecipeTypes().length > 1) { - sideTabs.attachSubTab(new MachineModeFancyConfigurator(rLMachine)); - } - var directionalConfigurator = CombinedDirectionalFancyConfigurator.of(self(), self()); - if (directionalConfigurator != null) - sideTabs.attachSubTab(directionalConfigurator); - } - - @Override - default void attachConfigurators(ConfiguratorPanel configuratorPanel) { - if (this instanceof IControllable controllable) { - configuratorPanel.attachConfigurators(new IFancyConfiguratorButton.Toggle( - GuiTextures.BUTTON_POWER.getSubTexture(0, 0, 1, 0.5), - GuiTextures.BUTTON_POWER.getSubTexture(0, 0.5, 1, 0.5), - controllable::isWorkingEnabled, (clickData, pressed) -> controllable.setWorkingEnabled(pressed)) - .setTooltipsSupplier(pressed -> List.of( - Component.translatable( - pressed ? "behaviour.soft_hammer.enabled" : "behaviour.soft_hammer.disabled")))); - } - if (this instanceof MetaMachine machine) { - for (var direction : Direction.values()) { - if (machine.getCoverContainer().hasCover(direction)) { - var configurator = machine.getCoverContainer().getCoverAtSide(direction).getConfigurator(); - if (configurator != null) - configuratorPanel.attachConfigurators(configurator); - } - } - } - } - - @Override - default void attachTooltips(TooltipsPanel tooltipsPanel) { - tooltipsPanel.attachTooltips(self()); - self().getTraitHolder().getAllTraits().stream().filter(IFancyTooltip.class::isInstance) - .map(IFancyTooltip.class::cast) - .forEach(tooltipsPanel::attachTooltips); - } - - @Override - default List getTabTooltips() { - var list = new ArrayList(); - list.add(Component.translatable(self().getDefinition().getDescriptionId())); - return list; - } - - @Override - default Component getTitle() { - return Component.translatable(self().getDefinition().getDescriptionId()); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IHasBatterySlot.java b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IHasBatterySlot.java new file mode 100644 index 00000000000..9ff7e106831 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IHasBatterySlot.java @@ -0,0 +1,8 @@ +package com.gregtechceu.gtceu.api.machine.feature; + +import com.gregtechceu.gtceu.api.transfer.item.CustomItemStackHandler; + +public interface IHasBatterySlot extends IMachineFeature { + + CustomItemStackHandler getChargerInventory(); +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IMuiMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IMuiMachine.java new file mode 100644 index 00000000000..89bbf9ec13a --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IMuiMachine.java @@ -0,0 +1,59 @@ +package com.gregtechceu.gtceu.api.machine.feature; + +import com.gregtechceu.gtceu.api.machine.mui.MachineUIPanelBuilder; +import com.gregtechceu.gtceu.api.mui.GTGuiScreen; +import com.gregtechceu.gtceu.api.mui.factory.MachineUIFactory; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import brachy.modularui.api.IUIHolder; +import brachy.modularui.factory.PosGuiData; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.ModularScreen; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.sync.PanelSyncManager; +import brachy.modularui.widget.ParentWidget; + +public interface IMuiMachine extends IUIHolder, IMachineFeature { + + @Override + default ModularPanel buildUI(PosGuiData data, PanelSyncManager syncManager, UISettings settings) { + var panelBuilder = getPanelBuilder(data, syncManager, settings); + panelBuilder.mainContents(parent -> buildMainUI(parent, data, syncManager, settings)); + return panelBuilder.build(syncManager, settings); + } + + default MachineUIPanelBuilder getPanelBuilder(PosGuiData data, PanelSyncManager syncManager, UISettings settings) { + return MachineUIPanelBuilder.defaultPanelBuilder(self()); + } + + default void buildMainUI(ParentWidget mainWidget, PosGuiData guiData, PanelSyncManager syncManager, + UISettings settings) {} + + default boolean shouldOpenUI(Player player, InteractionHand hand, BlockHitResult hit) { + return true; + } + + @Override + @OnlyIn(Dist.CLIENT) + default ModularScreen createScreen(PosGuiData data, ModularPanel mainPanel) { + return new GTGuiScreen(mainPanel); + } + + default InteractionResult tryToOpenUI(Player player, InteractionHand hand, BlockHitResult hit) { + if (this.shouldOpenUI(player, hand, hit)) { + if (player instanceof ServerPlayer serverPlayer) { + MachineUIFactory.INSTANCE.open(serverPlayer, this); + } + return InteractionResult.sidedSuccess(player.level().isClientSide); + } else { + return InteractionResult.PASS; + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IUIMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IUIMachine.java deleted file mode 100644 index 074723db931..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IUIMachine.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.gregtechceu.gtceu.api.machine.feature; - -import com.gregtechceu.gtceu.api.gui.factory.MachineUIFactory; - -import com.lowdragmc.lowdraglib.gui.modular.IUIHolder; - -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.phys.BlockHitResult; - -/** - * A machine that has gui. can be opened via right click. - */ -public interface IUIMachine extends IUIHolder, IMachineFeature { - - default boolean shouldOpenUI(Player player, InteractionHand hand, BlockHitResult hit) { - return true; - } - - default InteractionResult tryToOpenUI(Player player, InteractionHand hand, BlockHitResult hit) { - if (this.shouldOpenUI(player, hand, hit)) { - if (player instanceof ServerPlayer serverPlayer) { - MachineUIFactory.INSTANCE.openUI(self(), serverPlayer); - } - } else { - return InteractionResult.PASS; - } - return InteractionResult.sidedSuccess(player.level().isClientSide); - } - - @Override - default boolean isInvalid() { - return self().isRemoved(); - } - - @Override - default boolean isRemote() { - return self().isRemote(); - } - - @Override - default void markAsDirty() {}; -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IVoidable.java b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IVoidable.java index 72e6f1941ef..2b77a95e04a 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IVoidable.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/IVoidable.java @@ -3,21 +3,13 @@ import com.gregtechceu.gtceu.api.capability.recipe.FluidRecipeCapability; import com.gregtechceu.gtceu.api.capability.recipe.ItemRecipeCapability; import com.gregtechceu.gtceu.api.capability.recipe.RecipeCapability; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.ConfiguratorPanel; -import com.gregtechceu.gtceu.api.gui.widget.EnumSelectorWidget; -import com.gregtechceu.gtceu.api.machine.fancyconfigurator.FancySelectorConfigurator; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; - -import net.minecraft.network.chat.Component; import net.minecraft.util.StringRepresentable; import it.unimi.dsi.fastutil.objects.Reference2IntMap; import lombok.Getter; import org.jetbrains.annotations.NotNull; -import java.util.List; import java.util.function.Predicate; public interface IVoidable extends IMachineFeature { @@ -37,15 +29,7 @@ default VoidingMode getVoidingMode() { return VoidingMode.VOID_NONE; } - static void attachConfigurators(ConfiguratorPanel configuratorPanel, IVoidable controller) { - configuratorPanel - .attachConfigurators(new FancySelectorConfigurator<>(VoidingMode.VALUES, controller.getVoidingMode(), - controller::setVoidingMode) - .setTooltip(m -> List.of(Component.translatable("gtceu.gui.multiblock.voiding_mode"), - Component.translatable(m.localeName)))); - } - - enum VoidingMode implements StringRepresentable, EnumSelectorWidget.SelectableEnum { + enum VoidingMode implements StringRepresentable { VOID_NONE("gtceu.gui.no_voiding", cap -> false), VOID_ITEMS("gtceu.gui.item_voiding", cap -> cap == ItemRecipeCapability.CAP), @@ -55,30 +39,22 @@ enum VoidingMode implements StringRepresentable, EnumSelectorWidget.SelectableEn public static final VoidingMode[] VALUES = values(); - private final String localeName; @Getter - private final IGuiTexture icon; + private final String tooltip; private final Predicate> canVoid; VoidingMode(String name, Predicate> canVoid) { - this.localeName = name; + this.tooltip = name; this.canVoid = canVoid; - this.icon = GuiTextures.BUTTON_VOID_MULTIBLOCK.getSubTexture(0, ordinal() * 0.25, 1, 0.25); } public boolean canVoid(RecipeCapability capability) { return canVoid.test(capability); } - @NotNull - @Override - public String getSerializedName() { - return localeName; - } - @Override - public @NotNull String getTooltip() { - return localeName; + public @NotNull String getSerializedName() { + return tooltip; } } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IDisplayUIMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IDisplayUIMachine.java deleted file mode 100644 index d6bfdb6b5fa..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IDisplayUIMachine.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.gregtechceu.gtceu.api.machine.feature.multiblock; - -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.UITemplate; -import com.gregtechceu.gtceu.api.machine.feature.IUIMachine; -import com.gregtechceu.gtceu.api.machine.multiblock.MultiblockControllerMachine; - -import com.lowdragmc.lowdraglib.gui.modular.ModularUI; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; -import com.lowdragmc.lowdraglib.gui.util.ClickData; -import com.lowdragmc.lowdraglib.gui.widget.ComponentPanelWidget; -import com.lowdragmc.lowdraglib.gui.widget.DraggableScrollableWidgetGroup; -import com.lowdragmc.lowdraglib.gui.widget.LabelWidget; - -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.player.Player; - -import java.util.List; - -public interface IDisplayUIMachine extends IUIMachine { - - default void addDisplayText(List textList) { - for (var part : self().getParts()) { - part.addMultiText(textList); - } - } - - default void handleDisplayClick(String componentData, ClickData clickData) {} - - default IGuiTexture getScreenTexture() { - return GuiTextures.DISPLAY; - } - - @Override - default ModularUI createUI(Player entityPlayer) { - var screen = new DraggableScrollableWidgetGroup(7, 4, 162, 121).setBackground(getScreenTexture()); - screen.addWidget(new LabelWidget(4, 5, self().getBlockState().getBlock().getDescriptionId())); - screen.addWidget(new ComponentPanelWidget(4, 17, this::addDisplayText) - .textSupplier(this.self().getLevel().isClientSide ? null : this::addDisplayText) - .setMaxWidthLimit(150) - .clickHandler(this::handleDisplayClick)); - return new ModularUI(176, 216, this, entityPlayer) - .background(GuiTextures.BACKGROUND) - .widget(screen) - .widget(UITemplate.bindPlayerInventory(entityPlayer.getInventory(), GuiTextures.SLOT, 7, 134, true)); - } - - @Override - default MultiblockControllerMachine self() { - return (MultiblockControllerMachine) this; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IDistinctPart.java b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IDistinctPart.java index 1c1947d7ed3..06e4d1d7566 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IDistinctPart.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IDistinctPart.java @@ -1,36 +1,8 @@ package com.gregtechceu.gtceu.api.machine.feature.multiblock; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.ConfiguratorPanel; -import com.gregtechceu.gtceu.api.gui.fancy.IFancyConfiguratorButton; - -import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.Style; - -import java.util.List; - public interface IDistinctPart extends IMultiPart { boolean isDistinct(); void setDistinct(boolean isDistinct); - - @Override - default void attachConfigurators(ConfiguratorPanel configuratorPanel) { - superAttachConfigurators(configuratorPanel); - configuratorPanel.attachConfigurators(new IFancyConfiguratorButton.Toggle( - GuiTextures.BUTTON_DISTINCT_BUSES.getSubTexture(0, 0.5, 1, 0.5), - GuiTextures.BUTTON_DISTINCT_BUSES.getSubTexture(0, 0, 1, 0.5), - this::isDistinct, (clickData, pressed) -> setDistinct(pressed)) - .setTooltipsSupplier(pressed -> List.of( - Component.translatable("gtceu.multiblock.universal.distinct") - .setStyle(Style.EMPTY.withColor(ChatFormatting.YELLOW)) - .append(Component.translatable(pressed ? "gtceu.multiblock.universal.distinct.yes" : - "gtceu.multiblock.universal.distinct.no"))))); - } - - default void superAttachConfigurators(ConfiguratorPanel configuratorPanel) { - IMultiPart.super.attachConfigurators(configuratorPanel); - } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IMaintenanceMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IMaintenanceMachine.java index 3216cc9850e..81fb6fbd40b 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IMaintenanceMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IMaintenanceMachine.java @@ -1,21 +1,12 @@ package com.gregtechceu.gtceu.api.machine.feature.multiblock; import com.gregtechceu.gtceu.api.GTValues; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.IFancyTooltip; -import com.gregtechceu.gtceu.api.gui.fancy.TooltipsPanel; -import com.gregtechceu.gtceu.api.machine.multiblock.MultiblockControllerMachine; import com.gregtechceu.gtceu.api.machine.property.GTMachineModelProperties; import com.gregtechceu.gtceu.api.recipe.GTRecipe; import com.gregtechceu.gtceu.config.ConfigHolder; -import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.Style; import net.minecraft.world.level.block.state.properties.BooleanProperty; -import java.util.ArrayList; - public interface IMaintenanceMachine extends IMultiPart { BooleanProperty MAINTENANCE_TAPED_PROPERTY = GTMachineModelProperties.IS_TAPED; @@ -153,39 +144,43 @@ default GTRecipe modifyRecipe(GTRecipe recipe) { // ******* FANCY GUI ********// ////////////////////////////////////// - @Override - default void attachFancyTooltipsToController(MultiblockControllerMachine controller, TooltipsPanel tooltipsPanel) { - attachTooltips(tooltipsPanel); - } - - @Override - default void attachTooltips(TooltipsPanel tooltipsPanel) { - if (ConfigHolder.INSTANCE.machines.enableMaintenance) { - tooltipsPanel.attachTooltips(new IFancyTooltip.Basic(() -> GuiTextures.MAINTENANCE_ICON, () -> { - var tooltips = new ArrayList(); - tooltips.add(Component.translatable("gtceu.multiblock.universal.has_problems_header") - .setStyle(Style.EMPTY.withColor(ChatFormatting.RED))); - - if ((getMaintenanceProblems() & 1) == 0) - tooltips.add(Component.translatable("gtceu.multiblock.universal.problem.wrench")); - - if (((getMaintenanceProblems() >> 1) & 1) == 0) - tooltips.add(Component.translatable("gtceu.multiblock.universal.problem.screwdriver")); - - if (((getMaintenanceProblems() >> 2) & 1) == 0) - tooltips.add(Component.translatable("gtceu.multiblock.universal.problem.soft_mallet")); - - if (((getMaintenanceProblems() >> 3) & 1) == 0) - tooltips.add(Component.translatable("gtceu.multiblock.universal.problem.hard_hammer")); - - if (((getMaintenanceProblems() >> 4) & 1) == 0) - tooltips.add(Component.translatable("gtceu.multiblock.universal.problem.wire_cutter")); - - if (((getMaintenanceProblems() >> 5) & 1) == 0) - tooltips.add(Component.translatable("gtceu.multiblock.universal.problem.crowbar")); + /* + * @Override + * default void attachFancyTooltipsToController(IMultiController controller, TooltipsPanel tooltipsPanel) { + * attachTooltips(tooltipsPanel); + * } + */ - return tooltips; - }, this::hasMaintenanceProblems, () -> null)); - } - } + /* + * @Override + * default void attachTooltips(TooltipsPanel tooltipsPanel) { + * if (ConfigHolder.INSTANCE.machines.enableMaintenance) { + * tooltipsPanel.attachTooltips(new IFancyTooltip.Basic(() -> GuiTextures.MAINTENANCE_ICON, () -> { + * var tooltips = new ArrayList(); + * tooltips.add(Component.translatable("gtceu.multiblock.universal.has_problems_header") + * .setStyle(Style.EMPTY.withColor(ChatFormatting.RED))); + * + * if ((getMaintenanceProblems() & 1) == 0) + * tooltips.add(Component.translatable("gtceu.multiblock.universal.problem.wrench")); + * + * if (((getMaintenanceProblems() >> 1) & 1) == 0) + * tooltips.add(Component.translatable("gtceu.multiblock.universal.problem.screwdriver")); + * + * if (((getMaintenanceProblems() >> 2) & 1) == 0) + * tooltips.add(Component.translatable("gtceu.multiblock.universal.problem.soft_mallet")); + * + * if (((getMaintenanceProblems() >> 3) & 1) == 0) + * tooltips.add(Component.translatable("gtceu.multiblock.universal.problem.hard_hammer")); + * + * if (((getMaintenanceProblems() >> 4) & 1) == 0) + * tooltips.add(Component.translatable("gtceu.multiblock.universal.problem.wire_cutter")); + * + * if (((getMaintenanceProblems() >> 5) & 1) == 0) + * tooltips.add(Component.translatable("gtceu.multiblock.universal.problem.crowbar")); + * + * return tooltips; + * }, this::hasMaintenanceProblems, () -> null)); + * } + * } + */ } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IMultiPart.java b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IMultiPart.java index ec75796b409..1fa24b84022 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IMultiPart.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IMultiPart.java @@ -1,9 +1,8 @@ package com.gregtechceu.gtceu.api.machine.feature.multiblock; -import com.gregtechceu.gtceu.api.gui.fancy.TooltipsPanel; import com.gregtechceu.gtceu.api.machine.MetaMachine; -import com.gregtechceu.gtceu.api.machine.feature.IFancyUIMachine; import com.gregtechceu.gtceu.api.machine.feature.IMachineFeature; +import com.gregtechceu.gtceu.api.machine.feature.IMuiMachine; import com.gregtechceu.gtceu.api.machine.multiblock.MultiblockControllerMachine; import com.gregtechceu.gtceu.api.machine.multiblock.WorkableMultiblockMachine; import com.gregtechceu.gtceu.api.machine.trait.RecipeHandlerList; @@ -12,7 +11,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.network.chat.Component; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.state.BlockState; @@ -22,7 +20,7 @@ import java.util.List; import java.util.SortedSet; -public interface IMultiPart extends IMachineFeature, IFancyUIMachine { +public interface IMultiPart extends IMachineFeature, IMuiMachine { /** * @return If this multi part can be shared between multiple multiblocks. @@ -33,7 +31,7 @@ default boolean canShared() { /** * If this multi part belongs to a controller at the given position - * + * * @param controllerPos Controller position * @return If this multi part belongs to a controller at the given position */ @@ -54,14 +52,14 @@ default boolean canShared() { /** * Called when this part is removed from a multiblock. - * + * * @param controller The controller which this part has been removed from. */ void removedFromController(MultiblockControllerMachine controller); /** * Called when this part is added to a multiblock. - * + * * @param controller The controller which this part has been added to */ void addedToController(MultiblockControllerMachine controller); @@ -80,7 +78,7 @@ default boolean replacePartModelWhenFormed() { /** * Called to get block appearance when this multi part is in a formed multiblock. - * + * * @see MetaMachine#getBlockAppearance(BlockState, BlockAndTintGetter, BlockPos, Direction, BlockState, BlockPos) */ @Nullable @@ -137,16 +135,4 @@ default boolean beforeWorking(IWorkableMultiController controller) { default GTRecipe modifyRecipe(GTRecipe recipe) { return recipe; } - - /** - * Add text to the multiblock's screen. - * - * @param textList the text list to add to. - */ - default void addMultiText(List textList) {} - - /** - * Attach part's tooltips to the controller. - */ - default void attachFancyTooltipsToController(MultiblockControllerMachine controller, TooltipsPanel tooltipsPanel) {} } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IRotorHolderMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IRotorHolderMachine.java new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IRotorHolderMachine.java @@ -0,0 +1 @@ + diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/mui/MachineUIPanel.java b/src/main/java/com/gregtechceu/gtceu/api/machine/mui/MachineUIPanel.java new file mode 100644 index 00000000000..beb944f924a --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/mui/MachineUIPanel.java @@ -0,0 +1,88 @@ +package com.gregtechceu.gtceu.api.machine.mui; + +import com.gregtechceu.gtceu.api.machine.MetaMachine; +import com.gregtechceu.gtceu.common.mui.GTGuiTextures; +import com.gregtechceu.gtceu.common.mui.GTMuiWidgets; + +import brachy.modularui.api.drawable.IDrawable; +import brachy.modularui.drawable.UITexture; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.UISettings; +import brachy.modularui.theme.ThemeAPI; +import brachy.modularui.utils.Alignment; +import brachy.modularui.widget.ParentWidget; +import brachy.modularui.widgets.SlotGroupWidget; +import brachy.modularui.widgets.layout.Flow; +import lombok.Getter; + +public class MachineUIPanel extends ModularPanel { + + public static final int DEFAULT_CONTENT_WIDTH = 169; + public static final int DEFAULT_CONTENT_HEIGHT = 77; + + @Getter + protected final Flow leftConfiguratorPanel, rightConfiguratorPanel; + @Getter + protected final ParentWidget mainContents; + + public MachineUIPanel(MetaMachine machine, UISettings settings, boolean attachPlayerInventory, + boolean addTitleBar, boolean drawGTLogo, UITexture gtLogoTexture) { + super(machine.getDefinition().getId().getPath()); + + UITexture themeBackground = (UITexture) ThemeAPI.INSTANCE.getTheme(settings.getTheme()).getPanelTheme() + .theme().getBackground(); + if (themeBackground == null) themeBackground = GTGuiTextures.BACKGROUND; + leftConfiguratorPanel = Flow.col() + .coverChildren() + .rightRel(1.0f) + .reverseLayout(true) + .padding(4, 2, 4, 4) + .bottom(16) + .crossAxisAlignment(Alignment.CrossAxis.CENTER) + .childPadding(2) + .excludeAreaInRecipeViewer() + .background(themeBackground.getSubArea(0f, 0f, 0.75f, 1.0f)) + .setEnabledIf(f -> !f.getChildren().isEmpty()) + .decoration(); + + rightConfiguratorPanel = Flow.col() + .coverChildren() + .leftRel(1.0f) + .reverseLayout(true) + .padding(2, 4, 4, 4) + .bottom(16) + .crossAxisAlignment(Alignment.CrossAxis.CENTER) + .childPadding(2) + .excludeAreaInRecipeViewer() + .background(themeBackground.getSubArea(0.25f, 0f, 1.0f, 1.0f)) + .setEnabledIf(f -> !f.getChildren().isEmpty()) + .decoration(); + + Flow panelContents = Flow.col().coverChildren(); + panelContents.margin(4); + mainContents = new ParentWidget<>().coverChildren(DEFAULT_CONTENT_WIDTH, DEFAULT_CONTENT_HEIGHT); + + panelContents.child(mainContents); + + if (attachPlayerInventory) { + var inventory = SlotGroupWidget.playerInventory((index, slot) -> slot) + .marginTop(1) + .marginBottom(3); + panelContents.child(inventory); + } + + if (addTitleBar) { + child(GTMuiWidgets.createTitleBar(machine.getDefinition(), 172).decoration()); + } + + if (drawGTLogo) { + child(new IDrawable.DrawableWidget(gtLogoTexture) + .right(7).bottom(7 + (attachPlayerInventory ? 78 : 0)).decoration()); + } + + child(leftConfiguratorPanel); + child(rightConfiguratorPanel); + child(panelContents); + coverChildren(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/mui/MachineUIPanelBuilder.java b/src/main/java/com/gregtechceu/gtceu/api/machine/mui/MachineUIPanelBuilder.java new file mode 100644 index 00000000000..281b261be04 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/mui/MachineUIPanelBuilder.java @@ -0,0 +1,113 @@ +package com.gregtechceu.gtceu.api.machine.mui; + +import com.gregtechceu.gtceu.api.capability.IControllable; +import com.gregtechceu.gtceu.api.machine.MetaMachine; +import com.gregtechceu.gtceu.api.machine.feature.IHasBatterySlot; +import com.gregtechceu.gtceu.api.machine.feature.IHasCircuitSlot; +import com.gregtechceu.gtceu.api.machine.feature.IVoidable; +import com.gregtechceu.gtceu.api.machine.feature.multiblock.IDistinctPart; +import com.gregtechceu.gtceu.api.machine.trait.feature.IAttachConfiguratorsTrait; +import com.gregtechceu.gtceu.common.mui.GTGuiTextures; +import com.gregtechceu.gtceu.common.mui.GTMuiWidgets; + +import brachy.modularui.drawable.UITexture; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.sync.PanelSyncManager; +import brachy.modularui.widget.ParentWidget; +import brachy.modularui.widgets.layout.Flow; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.util.function.Consumer; + +@Accessors(fluent = true) +@Setter +public class MachineUIPanelBuilder { + + /** + * Should the GregTech logo be drawn in the bottom right corner of the panel. + */ + private boolean drawGTLogo = false; + private UITexture gtLogoTexture = GTGuiTextures.GREGTECH_LOGO; + /** + * Should the player inventory be attached to the bottom of the panel. + */ + private boolean attachInventory = true; + /** + * Should a fancy title bar be created for this panel. + */ + private boolean addTitleBar = true; + /** + * If machine traits should be allowed to attach configurators to the sides of the panel. + */ + private boolean addTraitConfigurators = true; + /** + * If the default configurators (circuit slot, battery slot, power button) should be added to this machine, provided + * the machine supports them. + */ + private boolean addDefaultConfigurators = true; + private final MetaMachine machine; + + private Consumer leftConfigurators = (f) -> {}; + private Consumer rightConfigurators = (f) -> {}; + private Consumer> mainContents = (p) -> {}; + + protected MachineUIPanelBuilder(MetaMachine machine) { + this.machine = machine; + } + + public MachineUIPanel build(PanelSyncManager syncManager, UISettings settings) { + var panel = new MachineUIPanel(machine, settings, attachInventory, addTitleBar, drawGTLogo, gtLogoTexture); + + var attachLeft = panel.getLeftConfiguratorPanel(); + var attachRight = panel.getRightConfiguratorPanel(); + var attachMain = panel.getMainContents(); + + if (addDefaultConfigurators) { + if (machine instanceof IHasCircuitSlot circuitSlot && circuitSlot.isCircuitSlotEnabled()) { + attachLeft.child(GTMuiWidgets.createCircuitSlotPanel(circuitSlot, panel, syncManager)); + } + + if (machine instanceof IControllable controllable) { + attachRight.child(GTMuiWidgets.createPowerButton(controllable)); + } + if (machine instanceof IHasBatterySlot batterySlot) { + attachRight.child(GTMuiWidgets.createBatterySlot(batterySlot, syncManager)); + } + if (machine instanceof IVoidable voidable) { + attachRight.child(GTMuiWidgets.createVoidingButton(voidable)); + } + if (machine instanceof IDistinctPart distinctPart) { + attachRight.child(GTMuiWidgets.createDistinctnessButton(distinctPart)); + } + } + + leftConfigurators.accept(attachLeft); + rightConfigurators.accept(attachRight); + mainContents.accept(attachMain); + + if (addTraitConfigurators) { + for (var trait : machine.getTraitHolder().getAllTraits()) { + if (trait instanceof IAttachConfiguratorsTrait attachConfiguratorsTrait) { + attachConfiguratorsTrait.attachLeftConfigurators(attachLeft, panel, syncManager); + attachConfiguratorsTrait.attachRightConfigurators(attachRight, panel, syncManager); + } + } + } + + return panel; + } + + public static MachineUIPanelBuilder defaultSimpleSingleblockPanelBuilder(MetaMachine machine) { + return new MachineUIPanelBuilder(machine).drawGTLogo(true); + } + + public static MachineUIPanelBuilder defaultPanelBuilder(MetaMachine machine) { + return new MachineUIPanelBuilder(machine); + } + + public static MachineUIPanelBuilder defaultSteamMachineBuilder(MetaMachine machine) { + return new MachineUIPanelBuilder(machine).drawGTLogo(true).addDefaultConfigurators(false) + .addTraitConfigurators(false); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/CoilWorkableElectricMultiblockMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/CoilWorkableElectricMultiblockMachine.java index a4ea83d5a11..3d851717c1b 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/CoilWorkableElectricMultiblockMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/CoilWorkableElectricMultiblockMachine.java @@ -2,10 +2,18 @@ import com.gregtechceu.gtceu.api.block.ICoilType; import com.gregtechceu.gtceu.api.blockentity.BlockEntityCreationInfo; +import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; import com.gregtechceu.gtceu.common.block.CoilBlock; import net.minecraft.MethodsReturnNonnullByDefault; +import brachy.modularui.api.drawable.IDrawable; +import brachy.modularui.drawable.*; +import brachy.modularui.factory.PosGuiData; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.sync.PanelSyncManager; +import brachy.modularui.widget.ParentWidget; +import brachy.modularui.widgets.layout.Flow; import lombok.Getter; import javax.annotation.ParametersAreNonnullByDefault; @@ -16,6 +24,9 @@ public class CoilWorkableElectricMultiblockMachine extends WorkableElectricMulti @Getter private ICoilType coilType = CoilBlock.CoilType.CUPRONICKEL; + @SyncToClient + @Getter + private int coilTier = 1; public CoilWorkableElectricMultiblockMachine(BlockEntityCreationInfo info) { super(info); @@ -30,10 +41,24 @@ public void onStructureFormed() { var type = getMultiblockState().getMatchContext().get("CoilType"); if (type instanceof ICoilType coil) { this.coilType = coil; + this.coilTier = coil.getTier(); + getSyncDataHolder().markClientSyncFieldDirty("coilTier"); } } - public int getCoilTier() { - return coilType.getTier(); + @Override + public void buildMainUI(ParentWidget mainWidget, PosGuiData guiData, PanelSyncManager syncManager, + UISettings settings) { + IDrawable coilTexture = new UITexture.Builder() + .location(CoilBlock.CoilType.values()[coilTier].getTexture()) + .imageSize(16, 16) + .colorType(ColorType.DEFAULT) + .tiled().build(); + + mainWidget + .child(Flow.row().height(MULTI_UI_TEXT_PANEL_HEIGHT).coverChildrenWidth() + .child(new IDrawable.DrawableWidget(coilTexture).size(4, MULTI_UI_TEXT_PANEL_HEIGHT)) + .child(getMainTextPanel(syncManager)) + .child(new IDrawable.DrawableWidget(coilTexture).size(4, MULTI_UI_TEXT_PANEL_HEIGHT))); } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockControllerMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockControllerMachine.java index 8e1ad857077..1d109f7d7ff 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockControllerMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockControllerMachine.java @@ -28,6 +28,8 @@ import net.minecraft.world.InteractionResult; import net.minecraft.world.level.block.state.BlockState; +import brachy.modularui.api.widget.IWidget; +import brachy.modularui.value.sync.PanelSyncManager; import lombok.Getter; import org.jetbrains.annotations.Nullable; @@ -160,7 +162,7 @@ public void onPartUnload() { ////////////////////////////////////// // ***** Getters ******// - /// /////////////////////////////////// + ////////////////////////////////////// /** * The {@link MultiblockMachineDefinition} of this multiblock. @@ -413,4 +415,15 @@ public boolean checkPatternWithTryLock() { return false; } } + + /** + * Can be overridden to just add widgets to the black box in the middle instead of overriding the whole UI. + * Don't forget to invoke {@code super.getWidgetsForDisplay} to add the default lines (progress, voltage, etc.). + * + * @param syncManager the sync manager + * @return list of widgets to be displayed inside the black box in the middle of a standard multiblock UI + */ + public List getWidgetsForDisplay(PanelSyncManager syncManager) { + return new ArrayList<>(); + } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableElectricMultiblockMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableElectricMultiblockMachine.java index a96213a0e87..69a335f03ae 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableElectricMultiblockMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableElectricMultiblockMachine.java @@ -6,43 +6,40 @@ import com.gregtechceu.gtceu.api.capability.recipe.EURecipeCapability; import com.gregtechceu.gtceu.api.capability.recipe.IO; import com.gregtechceu.gtceu.api.capability.recipe.IRecipeHandler; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.*; -import com.gregtechceu.gtceu.api.machine.feature.IFancyUIMachine; +import com.gregtechceu.gtceu.api.machine.feature.IMuiMachine; import com.gregtechceu.gtceu.api.machine.feature.IOverclockMachine; import com.gregtechceu.gtceu.api.machine.feature.ITieredMachine; import com.gregtechceu.gtceu.api.machine.feature.IVoidable; -import com.gregtechceu.gtceu.api.machine.feature.multiblock.IDisplayUIMachine; -import com.gregtechceu.gtceu.api.machine.feature.multiblock.IMultiPart; import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic; import com.gregtechceu.gtceu.api.misc.EnergyContainerList; -import com.gregtechceu.gtceu.api.recipe.modifier.RecipeModifierList; import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField; -import com.gregtechceu.gtceu.common.data.GTRecipeModifiers; -import com.gregtechceu.gtceu.common.machine.multiblock.part.ParallelHatchPartMachine; +import com.gregtechceu.gtceu.common.mui.GTMultiblockTextUtil; import com.gregtechceu.gtceu.utils.GTUtil; -import com.lowdragmc.lowdraglib.gui.modular.ModularUI; -import com.lowdragmc.lowdraglib.gui.widget.*; - import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.player.Player; +import brachy.modularui.api.widget.IWidget; +import brachy.modularui.drawable.GuiTextures; +import brachy.modularui.drawable.Icon; +import brachy.modularui.factory.PosGuiData; +import brachy.modularui.screen.UISettings; +import brachy.modularui.utils.Alignment; +import brachy.modularui.value.sync.PanelSyncManager; +import brachy.modularui.widget.ParentWidget; +import brachy.modularui.widget.Widget; +import brachy.modularui.widgets.ListWidget; import lombok.Getter; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import java.util.Objects; -import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -public class WorkableElectricMultiblockMachine extends WorkableMultiblockMachine implements IFancyUIMachine, - IDisplayUIMachine, ITieredMachine, IOverclockMachine { +public class WorkableElectricMultiblockMachine extends WorkableMultiblockMachine + implements IMuiMachine, ITieredMachine, IOverclockMachine, IVoidable { // runtime protected @Nullable EnergyContainerList energyContainer; @@ -98,91 +95,37 @@ public void setBatchEnabled(boolean batch) { // ********** GUI ***********// ////////////////////////////////////// - @Override - public void addDisplayText(List textList) { - int numParallels; - int subtickParallels; - int batchParallels; - int totalRuns; - boolean exact = false; - if (recipeLogic.isActive() && recipeLogic.getLastRecipe() != null) { - numParallels = recipeLogic.getLastRecipe().parallels; - subtickParallels = recipeLogic.getLastRecipe().subtickParallels; - batchParallels = recipeLogic.getLastRecipe().batchParallels; - totalRuns = recipeLogic.getLastRecipe().getTotalRuns(); - exact = true; - } else { - numParallels = getParallelHatch() - .map(ParallelHatchPartMachine::getCurrentParallel) - .orElse(0); - subtickParallels = 0; - batchParallels = 0; - totalRuns = 0; - } + public static final int MULTI_UI_TEXT_PANEL_WIDTH = 172; + public static final int MULTI_UI_TEXT_PANEL_HEIGHT = 136; - MultiblockDisplayText.builder(textList, isFormed()) - .setWorkingStatus(recipeLogic.isWorkingEnabled(), recipeLogic.isActive()) - .addEnergyUsageLine(energyContainer) - .addEnergyTierLine(tier) - .addMachineModeLine(getRecipeType(), getRecipeTypes().length > 1) - .addTotalRunsLine(totalRuns) - .addParallelsLine(numParallels, exact) - .addSubtickParallelsLine(subtickParallels) - .addBatchModeLine(isBatchEnabled(), batchParallels) - .addWorkingStatusLine() - .addProgressLine(recipeLogic) - .addRecipeFailReasonLine(recipeLogic) - .addOutputLines(recipeLogic.getLastRecipe()); - getDefinition().getAdditionalDisplay().accept(this, textList); - IDisplayUIMachine.super.addDisplayText(textList); - } + public Widget getMainTextPanel(PanelSyncManager syncManager) { + var parentWidget = new ParentWidget<>(); + var listWidget = new ListWidget<>() + .width(MULTI_UI_TEXT_PANEL_WIDTH - 6) + .height(MULTI_UI_TEXT_PANEL_HEIGHT - 6) + .childSeparator(Icon.EMPTY_2PX) + .crossAxisAlignment(Alignment.CrossAxis.START) + .posRel(Alignment.CenterLeft); + parentWidget.size(MULTI_UI_TEXT_PANEL_WIDTH, MULTI_UI_TEXT_PANEL_HEIGHT).background(GuiTextures.DISPLAY); - @Override - public Widget createUIWidget() { - var group = new WidgetGroup(0, 0, 182 + 8, 117 + 8); - group.addWidget(new DraggableScrollableWidgetGroup(4, 4, 182, 117).setBackground(getScreenTexture()) - .addWidget(new LabelWidget(4, 5, self().getBlockState().getBlock().getDescriptionId())) - .addWidget(new ComponentPanelWidget(4, 17, this::addDisplayText) - .textSupplier(this.getLevel().isClientSide ? null : this::addDisplayText) - .setMaxWidthLimit(200) - .clickHandler(this::handleDisplayClick))); - group.setBackground(GuiTextures.BACKGROUND_INVERSE); - return group; + listWidget.children(getWidgetsForDisplay(syncManager)); + parentWidget.child(listWidget.left(3).top(3)); + return parentWidget; } @Override - public ModularUI createUI(Player entityPlayer) { - return new ModularUI(198, 208, this, entityPlayer).widget(new FancyMachineUIWidget(this, 198, 208)); + public void buildMainUI(ParentWidget mainWidget, PosGuiData guiData, PanelSyncManager syncManager, + UISettings settings) { + mainWidget.child(getMainTextPanel(syncManager).margin(4, 2)); } @Override - public List getSubTabs() { - return getParts().stream().filter(Objects::nonNull).map(IFancyUIProvider.class::cast).toList(); - } - - @Override - public void attachConfigurators(ConfiguratorPanel configuratorPanel) { - IVoidable.attachConfigurators(configuratorPanel, this); - if (getDefinition().getRecipeModifier() instanceof RecipeModifierList list && Arrays.stream(list.getModifiers()) - .anyMatch(modifier -> modifier == GTRecipeModifiers.BATCH_MODE)) { - configuratorPanel.attachConfigurators(new IFancyConfiguratorButton.Toggle( - GuiTextures.BUTTON_BATCH.getSubTexture(0, 0, 1, 0.5), - GuiTextures.BUTTON_BATCH.getSubTexture(0, 0.5, 1, 0.5), - this::isBatchEnabled, - (cd, p) -> setBatchEnabled(p)) - .setTooltipsSupplier( - p -> List.of( - Component.translatable("gtceu.machine.batch_" + (p ? "enabled" : "disabled"))))); - } - - IFancyUIMachine.super.attachConfigurators(configuratorPanel); - } - - @Override - public void attachTooltips(TooltipsPanel tooltipsPanel) { - for (IMultiPart part : getParts()) { - part.attachFancyTooltipsToController(this, tooltipsPanel); - } + public List getWidgetsForDisplay(PanelSyncManager syncManager) { + List widgets = new ArrayList<>(); + widgets.add(GTMultiblockTextUtil.addEnergyTierLine(this, syncManager)); + widgets.add(GTMultiblockTextUtil.addEnergyUsageLine(this, syncManager)); + widgets.addAll(super.getWidgetsForDisplay(syncManager)); + return widgets; } ////////////////////////////////////// diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableMultiblockMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableMultiblockMachine.java index 1026e857dba..12ebb955a68 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableMultiblockMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableMultiblockMachine.java @@ -16,11 +16,14 @@ import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; import com.gregtechceu.gtceu.client.model.machine.MachineRenderState; import com.gregtechceu.gtceu.common.machine.trait.CleanroomReceiverTrait; +import com.gregtechceu.gtceu.common.mui.GTMultiblockTextUtil; import com.gregtechceu.gtceu.utils.ISubscription; import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.Block; +import brachy.modularui.api.widget.IWidget; +import brachy.modularui.value.sync.PanelSyncManager; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectMaps; import it.unimi.dsi.fastutil.longs.LongSet; @@ -311,4 +314,17 @@ public void setVoidingMode(VoidingMode mode) { voidingMode = mode; getRecipeLogic().updateTickSubscription(); } + + @Override + public List getWidgetsForDisplay(PanelSyncManager syncManager) { + List widgets = super.getWidgetsForDisplay(syncManager); + widgets.add(GTMultiblockTextUtil.addProgressLine(this, syncManager)); + widgets.add(GTMultiblockTextUtil.addWorkingStatusLine(this, syncManager)); + widgets.add(GTMultiblockTextUtil.addParallelLine(this, syncManager)); + widgets.add(GTMultiblockTextUtil.addBatchModeLine(this, syncManager)); + widgets.add(GTMultiblockTextUtil.addSubtickParallelsLine(this, syncManager)); + widgets.add(GTMultiblockTextUtil.addTotalRunsLine(this, syncManager)); + widgets.add(GTMultiblockTextUtil.addOutputLines(this, syncManager)); + return widgets; + } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/part/TieredIOPartMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/part/TieredIOPartMachine.java index 4656665301e..921d4323823 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/part/TieredIOPartMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/part/TieredIOPartMachine.java @@ -10,7 +10,6 @@ import net.minecraft.MethodsReturnNonnullByDefault; import lombok.Getter; -import org.jetbrains.annotations.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @@ -45,14 +44,17 @@ public void setWorkingEnabled(boolean workingEnabled) { // ***** Initialization ******// ////////////////////////////////////// - @Nullable - @Override - public PageGroupingData getPageGroupingData() { - return switch (this.io) { - case IN -> new PageGroupingData("gtceu.multiblock.page_switcher.io.import", 1); - case OUT -> new PageGroupingData("gtceu.multiblock.page_switcher.io.export", 2); - case BOTH -> new PageGroupingData("gtceu.multiblock.page_switcher.io.both", 3); - case NONE -> null; - }; - } + /* + * @Nullable + * + * @Override + * public PageGroupingData getPageGroupingData() { + * return switch (this.io) { + * case IN -> new PageGroupingData("gtceu.multiblock.page_switcher.io.import", 1); + * case OUT -> new PageGroupingData("gtceu.multiblock.page_switcher.io.export", 2); + * case BOTH -> new PageGroupingData("gtceu.multiblock.page_switcher.io.both", 3); + * case NONE -> null; + * }; + * } + */ } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SimpleSteamMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SimpleSteamMachine.java index e28634e50e4..199ba8cb40e 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SimpleSteamMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SimpleSteamMachine.java @@ -4,12 +4,7 @@ import com.gregtechceu.gtceu.api.blockentity.BlockEntityCreationInfo; import com.gregtechceu.gtceu.api.capability.recipe.IO; import com.gregtechceu.gtceu.api.capability.recipe.ItemRecipeCapability; -import com.gregtechceu.gtceu.api.capability.recipe.RecipeCapability; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.UITemplate; -import com.gregtechceu.gtceu.api.gui.widget.PredicatedImageWidget; import com.gregtechceu.gtceu.api.machine.MetaMachine; -import com.gregtechceu.gtceu.api.machine.feature.IUIMachine; import com.gregtechceu.gtceu.api.machine.property.GTMachineModelProperties; import com.gregtechceu.gtceu.api.machine.trait.NotifiableItemStackHandler; import com.gregtechceu.gtceu.api.machine.trait.RecipeHandlerList; @@ -23,15 +18,8 @@ import com.gregtechceu.gtceu.common.machine.trait.ExhaustVentMachineTrait; import com.gregtechceu.gtceu.common.recipe.condition.VentCondition; -import com.lowdragmc.lowdraglib.gui.modular.ModularUI; -import com.lowdragmc.lowdraglib.gui.widget.LabelWidget; -import com.lowdragmc.lowdraglib.utils.Position; - import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.entity.player.Player; -import com.google.common.collect.Tables; import lombok.Getter; import java.util.*; @@ -39,7 +27,7 @@ /** * A singleblock steam machine with recipe logic and item IO. */ -public class SimpleSteamMachine extends SteamWorkableMachine implements IUIMachine { +public class SimpleSteamMachine extends SteamWorkableMachine { @SaveField public final NotifiableItemStackHandler importItems; @@ -167,35 +155,4 @@ public void afterWorking() { exhaustVentTrait.setNeedsVenting(true); exhaustVentTrait.checkVenting(); } - - ////////////////////////////////////// - // *********** GUI ***********// - ////////////////////////////////////// - - @Override - public ModularUI createUI(Player entityPlayer) { - var storages = Tables.newCustomTable(new EnumMap<>(IO.class), LinkedHashMap, Object>::new); - storages.put(IO.IN, ItemRecipeCapability.CAP, importItems.storage); - storages.put(IO.OUT, ItemRecipeCapability.CAP, exportItems.storage); - - var group = getRecipeType().getRecipeUI().createUITemplate(recipeLogic::getProgressPercent, - storages, - new CompoundTag(), - Collections.emptyList(), - true, - isHighPressure); - Position pos = new Position((Math.max(group.getSize().width + 4 + 8, 176) - 4 - group.getSize().width) / 2 + 4, - 32); - group.setSelfPosition(pos); - return new ModularUI(176, 166, this, entityPlayer) - .background(GuiTextures.BACKGROUND_STEAM.get(isHighPressure)) - .widget(group) - .widget(new LabelWidget(5, 5, getBlockState().getBlock().getDescriptionId())) - .widget(new PredicatedImageWidget(pos.x + group.getSize().width / 2 - 9, - pos.y + group.getSize().height / 2 - 9, 18, 18, - GuiTextures.INDICATOR_NO_STEAM.get(isHighPressure)) - .setPredicate(recipeLogic::isWaiting)) - .widget(UITemplate.bindPlayerInventory(entityPlayer.getInventory(), - GuiTextures.SLOT_STEAM.get(isHighPressure), 7, 84, true)); - } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamBoilerMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamBoilerMachine.java index 08462261a9f..53b62a5a32b 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamBoilerMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamBoilerMachine.java @@ -3,13 +3,10 @@ import com.gregtechceu.gtceu.api.GTValues; import com.gregtechceu.gtceu.api.blockentity.BlockEntityCreationInfo; import com.gregtechceu.gtceu.api.capability.recipe.IO; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.UITemplate; -import com.gregtechceu.gtceu.api.gui.widget.TankWidget; import com.gregtechceu.gtceu.api.machine.MetaMachine; import com.gregtechceu.gtceu.api.machine.TickableSubscription; -import com.gregtechceu.gtceu.api.machine.feature.IDataInfoProvider; -import com.gregtechceu.gtceu.api.machine.feature.IUIMachine; +import com.gregtechceu.gtceu.api.machine.feature.*; +import com.gregtechceu.gtceu.api.machine.mui.MachineUIPanelBuilder; import com.gregtechceu.gtceu.api.machine.trait.NotifiableFluidTank; import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic; import com.gregtechceu.gtceu.api.recipe.GTRecipe; @@ -19,16 +16,10 @@ import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; import com.gregtechceu.gtceu.common.data.GTMaterials; import com.gregtechceu.gtceu.common.item.behavior.PortableScannerBehavior; +import com.gregtechceu.gtceu.common.mui.GTGuiTextures; import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.utils.*; -import com.lowdragmc.lowdraglib.gui.modular.ModularUI; -import com.lowdragmc.lowdraglib.gui.texture.ProgressTexture; -import com.lowdragmc.lowdraglib.gui.widget.ImageWidget; -import com.lowdragmc.lowdraglib.gui.widget.LabelWidget; -import com.lowdragmc.lowdraglib.gui.widget.ProgressWidget; - -import net.minecraft.client.resources.language.I18n; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.ParticleTypes; @@ -39,12 +30,22 @@ import net.minecraft.sounds.SoundSource; import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.block.Block; import net.minecraftforge.fluids.FluidType; import net.minecraftforge.fluids.FluidUtil; import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; +import brachy.modularui.api.drawable.IKey; +import brachy.modularui.drawable.UITexture; +import brachy.modularui.factory.PosGuiData; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.sync.DoubleSyncValue; +import brachy.modularui.value.sync.FluidSlotSyncHandler; +import brachy.modularui.value.sync.PanelSyncManager; +import brachy.modularui.widget.ParentWidget; +import brachy.modularui.widgets.ProgressWidget; +import brachy.modularui.widgets.layout.Flow; +import brachy.modularui.widgets.slot.FluidSlot; import lombok.Getter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -54,7 +55,7 @@ import java.util.List; public abstract class SteamBoilerMachine extends SteamWorkableMachine - implements IUIMachine, IDataInfoProvider { + implements IMuiMachine, IDataInfoProvider { @SaveField public final NotifiableFluidTank waterTank; @@ -169,7 +170,9 @@ protected void updateCurrentTemperature() { currentTemperature -= getCoolDownRate(); timeBeforeCoolingDown = getCooldownInterval(); } - } else--timeBeforeCoolingDown; + } else { + --timeBeforeCoolingDown; + } if (getOffsetTimer() % 10 == 0) { if (currentTemperature >= 100) { @@ -183,7 +186,9 @@ protected void updateCurrentTemperature() { } if (this.hasNoWater && hasDrainedWater) { GTUtil.doExplosion(getLevel(), getBlockPos(), 2.0f); - } else this.hasNoWater = !hasDrainedWater; + } else { + this.hasNoWater = !hasDrainedWater; + } if (filledSteam == 0 && hasDrainedWater && getLevel() instanceof ServerLevel serverLevel) { final float x = getBlockPos().getX() + 0.5F; final float y = getBlockPos().getY() + 0.5F; @@ -206,9 +211,12 @@ protected void updateCurrentTemperature() { // bypass capability check for special case behavior steamTank.drainInternal(FluidType.BUCKET_VOLUME * 4, FluidAction.EXECUTE); } - } else this.hasNoWater = false; + } else { + this.hasNoWater = false; + } } updateSteamSubscription(); + syncDataHolder.markClientSyncFieldDirty("currentTemperature"); } protected int getCooldownInterval() { @@ -296,27 +304,42 @@ public InteractionResult onUseWithItem(ExtendedUseOnContext context) { ////////////////////////////////////// @Override - public ModularUI createUI(Player entityPlayer) { - return new ModularUI(176, 166, this, entityPlayer) - .background(GuiTextures.BACKGROUND_STEAM.get(isHighPressure)) - .widget(new LabelWidget(6, 6, getBlockState().getBlock().getDescriptionId())) - .widget(new ProgressWidget(this::getTemperaturePercent, 96, 26, 10, 54) - .setProgressTexture(GuiTextures.PROGRESS_BAR_BOILER_EMPTY.get(isHighPressure), - GuiTextures.PROGRESS_BAR_BOILER_HEAT) - .setFillDirection(ProgressTexture.FillDirection.DOWN_TO_UP) - .setDynamicHoverTips(pct -> I18n.get("gtceu.multiblock.large_boiler.temperature", - currentTemperature + 274, getMaxTemperature() + 274))) - .widget(new TankWidget(waterTank.getStorages()[0], 83, 26, 10, 54, false, true) - .setShowAmount(false) - .setFillDirection(ProgressTexture.FillDirection.DOWN_TO_UP) - .setBackground(GuiTextures.PROGRESS_BAR_BOILER_EMPTY.get(isHighPressure))) - .widget(new TankWidget(steamTank.getStorages()[0], 70, 26, 10, 54, true, false) - .setShowAmount(false) - .setFillDirection(ProgressTexture.FillDirection.DOWN_TO_UP) - .setBackground(GuiTextures.PROGRESS_BAR_BOILER_EMPTY.get(isHighPressure))) - .widget(new ImageWidget(43, 44, 18, 18, GuiTextures.CANISTER_OVERLAY_STEAM.get(isHighPressure))) - .widget(UITemplate.bindPlayerInventory(entityPlayer.getInventory(), - GuiTextures.SLOT_STEAM.get(isHighPressure), 7, 84, true)); + public MachineUIPanelBuilder getPanelBuilder(PosGuiData data, PanelSyncManager syncManager, UISettings settings) { + return MachineUIPanelBuilder.defaultSteamMachineBuilder(this); + } + + @Override + public void buildMainUI(ParentWidget mainWidget, PosGuiData guiData, PanelSyncManager syncManager, + UISettings settings) { + UITexture progressTexture = isHighPressure() ? GTGuiTextures.PROGRESS_BAR_BOILER_EMPTY_STEEL : + GTGuiTextures.PROGRESS_BAR_BOILER_EMPTY_BRONZE; + + DoubleSyncValue tempPercentage = syncManager.getOrCreateSyncHandler("tempPercentage", DoubleSyncValue.class, + () -> new DoubleSyncValue(this::getTemperaturePercent)); + + mainWidget.child(Flow.row() + .top(12) + .left(50) + .coverChildren() + .childPadding(10) + .child(new FluidSlot() + .syncHandler(new FluidSlotSyncHandler(waterTank.getStorages()[0])) + .size(14, 54) + .alwaysShowFull(true)) + .child(new FluidSlot() + .syncHandler(new FluidSlotSyncHandler(steamTank.getStorages()[0]) + .canFillSlot(false).canDrainSlot(true)) + .alwaysShowFull(true) + .size(14, 54)) + .child(new ProgressWidget() + .texture(progressTexture, + GTGuiTextures.PROGRESS_BAR_BOILER_HEAT, 54) + .size(14, 54) + .value(tempPercentage) + .direction(ProgressWidget.Direction.UP) + .tooltipAutoUpdate(true) + .tooltipBuilder((r) -> r.addLine(IKey + .lang(Component.translatable("gtceu.fluid.temperature", getCurrentTemperature())))))); } ////////////////////////////////////// diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamEnergyRecipeHandler.java b/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamEnergyRecipeHandler.java index ab2e69cb39a..5b99437bc4b 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamEnergyRecipeHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamEnergyRecipeHandler.java @@ -13,6 +13,7 @@ import net.minecraftforge.fluids.FluidStack; +import lombok.Getter; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -20,6 +21,7 @@ public class SteamEnergyRecipeHandler implements IRecipeHandler { + @Getter private final NotifiableFluidTank steamTank; private final double conversionRate; // mB steam per EU diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamWorkableMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamWorkableMachine.java index 68a90d4de2b..2f90f65552b 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamWorkableMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/steam/SteamWorkableMachine.java @@ -4,7 +4,6 @@ import com.gregtechceu.gtceu.api.capability.recipe.IO; import com.gregtechceu.gtceu.api.capability.recipe.IRecipeHandler; import com.gregtechceu.gtceu.api.capability.recipe.RecipeCapability; -import com.gregtechceu.gtceu.api.gui.GuiTextures; import com.gregtechceu.gtceu.api.item.tool.GTToolType; import com.gregtechceu.gtceu.api.machine.feature.IMufflableMachine; import com.gregtechceu.gtceu.api.machine.feature.IRecipeLogicMachine; @@ -14,11 +13,10 @@ import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField; import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; import com.gregtechceu.gtceu.common.machine.trait.CleanroomReceiverTrait; +import com.gregtechceu.gtceu.common.mui.GTGuiTextures; import com.gregtechceu.gtceu.utils.ExtendedUseOnContext; import com.gregtechceu.gtceu.utils.ISubscription; -import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; - import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.InteractionResult; @@ -26,6 +24,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.fluids.FluidType; +import brachy.modularui.drawable.UITexture; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; import lombok.Setter; @@ -186,12 +185,12 @@ public void clientTick() { // ******* Rendering ********// ////////////////////////////////////// @Override - public @Nullable ResourceTexture sideTips(Player player, BlockPos pos, BlockState state, Set toolTypes, - Direction side) { + public @Nullable UITexture sideTips(Player player, BlockPos pos, BlockState state, Set toolTypes, + Direction side) { if (toolTypes.contains(GTToolType.WRENCH)) { if (!player.isShiftKeyDown()) { if (!hasFrontFacing() || side != getFrontFacing()) { - return GuiTextures.TOOL_IO_FACING_ROTATION; + return GTGuiTextures.TOOL_IO_FACING_ROTATION; } } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/RecipeLogic.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/RecipeLogic.java index 2b8365e1536..91ebc16a6cc 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/RecipeLogic.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/RecipeLogic.java @@ -5,8 +5,6 @@ import com.gregtechceu.gtceu.api.capability.recipe.EURecipeCapability; import com.gregtechceu.gtceu.api.capability.recipe.IO; import com.gregtechceu.gtceu.api.capability.recipe.RecipeCapability; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.IFancyTooltip; import com.gregtechceu.gtceu.api.machine.MetaMachine; import com.gregtechceu.gtceu.api.machine.TickableSubscription; import com.gregtechceu.gtceu.api.machine.feature.IRecipeLogicMachine; @@ -27,8 +25,6 @@ import com.gregtechceu.gtceu.common.cover.MachineControllerCover; import com.gregtechceu.gtceu.utils.GTMath; -import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; - import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; @@ -47,7 +43,7 @@ import java.util.*; -public class RecipeLogic extends MachineTrait implements IWorkable, IFancyTooltip { +public class RecipeLogic extends MachineTrait implements IWorkable { public static final MachineTraitType TYPE = new MachineTraitType<>(RecipeLogic.class, false); @@ -304,6 +300,7 @@ public void handleRecipeWorking() { } progress++; totalContinuousRunningTime++; + syncDataHolder.markClientSyncFieldDirty("progress"); } else { setWaiting(handleTick.reason()); @@ -344,6 +341,7 @@ public void handleRecipeWorking() { protected void regressRecipe() { if (progress > 0 && getRLMachine().regressWhenWaiting()) { this.progress = 1; + syncDataHolder.markClientSyncFieldDirty("progress"); } } @@ -367,6 +365,7 @@ public void findAndHandleRecipe() { lastOriginRecipe = null; handleSearchingRecipes(searchRecipe()); } + syncDataHolder.markClientSyncFieldDirty("lastRecipe"); recipeDirty = false; } @@ -410,6 +409,7 @@ public void setupRecipe(GTRecipe recipe) { progress = 0; duration = 0; isActive = false; + syncDataHolder.resyncAllFields(); return; } var handledIO = handleRecipeIO(recipe, IO.IN); @@ -424,6 +424,7 @@ public void setupRecipe(GTRecipe recipe) { progress = 0; duration = recipe.duration; isActive = true; + syncDataHolder.resyncAllFields(); } } @@ -443,6 +444,7 @@ public void setStatus(Status status) { updateTickSubscription(); if (this.status != Status.WAITING) { waitingReason = null; + syncDataHolder.markClientSyncFieldDirty("waitingReason"); } } } @@ -450,6 +452,7 @@ public void setStatus(Status status) { public void setWaiting(@Nullable Component reason) { setStatus(Status.WAITING); waitingReason = reason; + syncDataHolder.markClientSyncFieldDirty("waitingReason"); getRLMachine().onWaiting(); } @@ -538,6 +541,7 @@ public void onRecipeFinish() { isActive = false; // Force a recipe recheck. lastRecipe = null; + syncDataHolder.resyncAllFields(); return; } if (getRLMachine().alwaysTryModifyRecipe()) { @@ -547,6 +551,7 @@ public void onRecipeFinish() { markLastRecipeDirty(); } else { lastRecipe = modified; + syncDataHolder.markClientSyncFieldDirty("lastRecipe"); } } else { markLastRecipeDirty(); @@ -562,6 +567,7 @@ public void onRecipeFinish() { progress = 0; duration = 0; isActive = false; + syncDataHolder.resyncAllFields(); } } } @@ -583,6 +589,8 @@ public void interruptRecipe() { setStatus(Status.IDLE); progress = 0; duration = 0; + syncDataHolder.markClientSyncFieldDirty("progress"); + syncDataHolder.markClientSyncFieldDirty("duration"); } } @@ -614,16 +622,7 @@ public void updateSound() { } } - @Override - public IGuiTexture getFancyTooltipIcon() { - if (showFancyTooltip()) { - return GuiTextures.INSUFFICIENT_INPUT; - } - return IGuiTexture.EMPTY; - } - - @Override - public List getFancyTooltip() { + public List getWaitingReasons() { if (isWaiting() && waitingReason != null) { return List.of(waitingReason); } @@ -633,11 +632,6 @@ public List getFancyTooltip() { return Collections.emptyList(); } - @Override - public boolean showFancyTooltip() { - return waitingReason != null || !failureReasons.isEmpty(); - } - protected ChanceCacheMap makeChanceCaches() { ChanceCacheMap map = new ChanceCacheMap(); for (RecipeCapability cap : GTRegistries.RECIPE_CAPABILITIES.values()) { diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IAttachConfiguratorsTrait.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IAttachConfiguratorsTrait.java new file mode 100644 index 00000000000..10897a81b09 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IAttachConfiguratorsTrait.java @@ -0,0 +1,12 @@ +package com.gregtechceu.gtceu.api.machine.trait.feature; + +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.value.sync.PanelSyncManager; +import brachy.modularui.widgets.layout.Flow; + +public interface IAttachConfiguratorsTrait { + + default void attachLeftConfigurators(Flow flow, ModularPanel panel, PanelSyncManager syncManager) {} + + default void attachRightConfigurators(Flow flow, ModularPanel panel, PanelSyncManager syncManager) {} +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IRenderingTrait.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IRenderingTrait.java index 6a2dc1a9296..a5d708c3d34 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IRenderingTrait.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/feature/IRenderingTrait.java @@ -2,14 +2,13 @@ import com.gregtechceu.gtceu.api.item.tool.GTToolType; -import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; - import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; +import brachy.modularui.drawable.UITexture; import org.jetbrains.annotations.Nullable; import java.util.Set; @@ -21,7 +20,7 @@ public interface IRenderingTrait { /** * Called to determine if the grid overlay should be rendered on this machine. - * + * * @param player Player looking at this machine * @param pos Block pos * @param state Block state @@ -37,7 +36,7 @@ default boolean shouldRenderGridOverlay(Player player, BlockPos pos, BlockState /** * Called when the machine grid overlay is being rendered to determine the icon to be rendered within the grid * segment on a specifc side. - * + * * @param player Player looking at this machine * @param pos Block pos * @param state Block state @@ -45,9 +44,9 @@ default boolean shouldRenderGridOverlay(Player player, BlockPos pos, BlockState * @param side The machine side which this grid segment correspond to * @return The icon to be rendered, or null */ - default @Nullable ResourceTexture getGridOverlayIcon(Player player, BlockPos pos, BlockState state, - Set toolTypes, - Direction side) { + default @Nullable UITexture getGridOverlayIcon(Player player, BlockPos pos, BlockState state, + Set toolTypes, + Direction side) { return null; } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/misc/forge/FluidTankHandler.java b/src/main/java/com/gregtechceu/gtceu/api/misc/forge/FluidTankHandler.java new file mode 100644 index 00000000000..7c2e533a3ce --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/misc/forge/FluidTankHandler.java @@ -0,0 +1,62 @@ +package com.gregtechceu.gtceu.api.misc.forge; + +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidTank; +import net.minecraftforge.fluids.capability.IFluidHandler; + +import org.jetbrains.annotations.NotNull; + +public class FluidTankHandler implements IFluidHandler { + + public static IFluidHandler getTankFluidHandler(IFluidTank tank) { + if (tank instanceof IFluidHandler fluidHandler) { + return fluidHandler; + } + return new FluidTankHandler(tank); + } + + private final IFluidTank fluidTank; + + public FluidTankHandler(IFluidTank tank) { + this.fluidTank = tank; + } + + @Override + public int fill(FluidStack resource, FluidAction action) { + return this.fluidTank.fill(resource, action); + } + + @Override + public @NotNull FluidStack drain(FluidStack resource, FluidAction action) { + FluidStack currentFluid = this.fluidTank.getFluid(); + if (currentFluid.isEmpty() || !currentFluid.isFluidEqual(resource)) { + return FluidStack.EMPTY; + } + return this.fluidTank.drain(resource, action); + } + + @Override + public @NotNull FluidStack drain(int maxDrain, FluidAction action) { + return this.fluidTank.drain(maxDrain, action); + } + + @Override + public int getTanks() { + return 1; + } + + @Override + public @NotNull FluidStack getFluidInTank(int tank) { + return this.fluidTank.getFluid(); + } + + @Override + public int getTankCapacity(int tank) { + return this.fluidTank.getCapacity(); + } + + @Override + public boolean isFluidValid(int tank, @NotNull FluidStack stack) { + return this.fluidTank.isFluidValid(stack); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/EntryTypes.java b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/EntryTypes.java index a2b274cfc11..524effb6f65 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/EntryTypes.java +++ b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/EntryTypes.java @@ -31,14 +31,9 @@ private EntryTypes(ResourceLocation location, Supplier supplier) { this.factory = supplier; } - @Nullable - public static EntryTypes fromString(String name) { - return TYPES_MAP.getOrDefault(GTCEu.id(name), null); - } - @Nullable public static EntryTypes fromLocation(ResourceLocation location) { - return TYPES_MAP.getOrDefault(location, null); + return TYPES_MAP.get(location); } public static EntryTypes addEntryType(ResourceLocation location, Supplier supplier) { diff --git a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/VirtualEnderRegistry.java b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/VirtualEnderRegistry.java index d76b54600b8..00a9d6203ba 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/VirtualEnderRegistry.java +++ b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/VirtualEnderRegistry.java @@ -3,24 +3,20 @@ import com.gregtechceu.gtceu.GTCEu; import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.saveddata.SavedData; -import net.minecraftforge.server.ServerLifecycleHooks; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.function.Predicate; +import java.util.*; public class VirtualEnderRegistry extends SavedData { private static final String DATA_ID = GTCEu.MOD_ID + ".virtual_entry_data"; private static final String PUBLIC_KEY = "Public"; private static final String PRIVATE_KEY = "Private"; - private static volatile VirtualEnderRegistry data; + + private VirtualRegistryMap PUBLIC_REGISTRY = new VirtualRegistryMap(); private final Map VIRTUAL_REGISTRIES = new HashMap<>(); public VirtualEnderRegistry() {} @@ -29,43 +25,34 @@ public VirtualEnderRegistry(CompoundTag name) { readFromNBT(name); } - public static VirtualEnderRegistry getInstance() { - if (data == null) { - var server = ServerLifecycleHooks.getCurrentServer(); - if (server != null) { - data = server.overworld().getDataStorage() - .computeIfAbsent(VirtualEnderRegistry::new, VirtualEnderRegistry::new, DATA_ID); - } - } - - return data; + public static VirtualEnderRegistry get(ServerLevel sLvl) { + return sLvl.getServer().overworld().getDataStorage() + .computeIfAbsent(VirtualEnderRegistry::new, VirtualEnderRegistry::new, DATA_ID); } - /** - * To be called on server stopped event - */ - public static void release() { - if (data != null) { - data = null; - GTCEu.LOGGER.debug("VirtualEnderRegistry has been unloaded"); - } + public @Nullable T getEntry(@Nullable UUID owner, EntryTypes type, String name) { + if (owner == null) return PUBLIC_REGISTRY.getEntry(type, name); + return getRegistry(owner).getEntry(type, name); } - public T getEntry(@Nullable UUID owner, EntryTypes type, String name) { - return getRegistry(owner).getEntry(type, name); + public Map getEntries(@Nullable UUID owner, EntryTypes type) { + if (owner == null) return PUBLIC_REGISTRY.getEntries(type); + return VIRTUAL_REGISTRIES.get(owner).getEntries(type); } public void addEntry(@Nullable UUID owner, String name, VirtualEntry entry) { - getRegistry(owner).addEntry(name, entry); + if (owner == null) PUBLIC_REGISTRY.addEntry(name, entry); + else getRegistry(owner).addEntry(name, entry); } public boolean hasEntry(@Nullable UUID owner, EntryTypes type, String name) { + if (owner == null) return PUBLIC_REGISTRY.contains(type, name); return getRegistry(owner).contains(type, name); } - public @NotNull T getOrCreateEntry(@Nullable UUID owner, EntryTypes type, String name) { + public T getOrCreateEntry(@Nullable UUID owner, EntryTypes type, String name) { if (!hasEntry(owner, type, name)) addEntry(owner, name, type.createInstance()); - return getEntry(owner, type, name); + return Objects.requireNonNull(getEntry(owner, type, name)); } /** @@ -75,35 +62,33 @@ public boolean hasEntry(@Nullable UUID owner, EntryTypes type, String name) { * @param type Type of the registry to remove from * @param name The name of the entry */ - public void deleteEntry(@Nullable UUID owner, EntryTypes type, String name) { + public void forceDeleteEntry(@Nullable UUID owner, EntryTypes type, String name) { + if (owner == null) { + PUBLIC_REGISTRY.deleteEntry(type, name); + return; + } + var registry = getRegistry(owner); if (registry.contains(type, name)) { registry.deleteEntry(type, name); - return; } - GTCEu.LOGGER.warn("Attempted to delete {} entry {} of type {}, which does not exist", - owner == null ? "public" : String.format("private [%s]", owner), name, type); } - public void deleteEntryIf(@Nullable UUID owner, EntryTypes type, String name, - Predicate shouldDelete) { + public void tryDeleteEntry(@Nullable UUID owner, EntryTypes type, String name) { T entry = getEntry(owner, type, name); - if (entry != null && shouldDelete.test(entry)) deleteEntry(owner, type, name); - } - - public Set getEntryNames(UUID owner, EntryTypes type) { - return getRegistry(owner).getEntryNames(type); + if (entry == null) return; + if (entry.canRemove()) forceDeleteEntry(owner, type, name); } private VirtualRegistryMap getRegistry(UUID owner) { - if (data == null) getInstance(); - return data.VIRTUAL_REGISTRIES.computeIfAbsent(owner, key -> new VirtualRegistryMap()); + return VIRTUAL_REGISTRIES.computeIfAbsent(owner, key -> new VirtualRegistryMap()); } public final void readFromNBT(CompoundTag nbt) { if (nbt.contains(PUBLIC_KEY)) { - VIRTUAL_REGISTRIES.put(null, new VirtualRegistryMap(nbt.getCompound(PUBLIC_KEY))); + PUBLIC_REGISTRY = new VirtualRegistryMap(nbt.getCompound(PUBLIC_KEY)); } + if (nbt.contains(PRIVATE_KEY)) { CompoundTag privateEntries = nbt.getCompound(PRIVATE_KEY); for (String owner : privateEntries.getAllKeys()) { @@ -113,17 +98,14 @@ public final void readFromNBT(CompoundTag nbt) { } } - @NotNull @Override - public final CompoundTag save(@NotNull CompoundTag tag) { + public final CompoundTag save(CompoundTag tag) { var privateTag = new CompoundTag(); + tag.put(PUBLIC_KEY, PUBLIC_REGISTRY.serializeNBT()); for (var owner : VIRTUAL_REGISTRIES.keySet()) { + if (VIRTUAL_REGISTRIES.get(owner).isEmpty()) continue; var mapTag = VIRTUAL_REGISTRIES.get(owner).serializeNBT(); - if (owner != null) { - privateTag.put(owner.toString(), mapTag); - } else { - tag.put(PUBLIC_KEY, mapTag); - } + privateTag.put(owner.toString(), mapTag); } tag.put(PRIVATE_KEY, privateTag); return tag; diff --git a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/VirtualEntry.java b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/VirtualEntry.java index b4f8c322012..38851cc9fa1 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/VirtualEntry.java +++ b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/VirtualEntry.java @@ -6,7 +6,6 @@ import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; -import org.jetbrains.annotations.NotNull; import java.util.Locale; @@ -19,8 +18,8 @@ public abstract class VirtualEntry implements INBTSerializable { protected static final String DESC_KEY = "description"; @Setter - @NotNull private String description = ""; + @Getter private int color = 0xFFFFFFFF; private String colorStr = DEFAULT_COLOR; @@ -76,6 +75,6 @@ public void deserializeNBT(CompoundTag nbt) { } public boolean canRemove() { - return this.description.isEmpty(); + return this.description.isBlank(); } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/VirtualRegistryMap.java b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/VirtualRegistryMap.java index 3d48f8b0200..3601c71e247 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/VirtualRegistryMap.java +++ b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/VirtualRegistryMap.java @@ -1,21 +1,19 @@ package com.gregtechceu.gtceu.api.misc.virtualregistry; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.common.util.INBTSerializable; -import org.jetbrains.annotations.NotNull; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.Nullable; -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; +import java.util.*; public class VirtualRegistryMap implements INBTSerializable { - private final Map, Map> registryMap = new ConcurrentHashMap<>(); + private final Map, Map> registryMap = new Object2ObjectOpenHashMap<>(); public VirtualRegistryMap() {} @@ -29,7 +27,11 @@ public VirtualRegistryMap(CompoundTag tag) { } public void addEntry(String name, VirtualEntry entry) { - registryMap.computeIfAbsent(entry.getType(), k -> new ConcurrentHashMap<>()).put(name, entry); + registryMap.computeIfAbsent(entry.getType(), k -> new Object2ObjectOpenHashMap<>()).put(name, entry); + } + + public Map getEntries(EntryTypes type) { + return registryMap.getOrDefault(type, new Object2ObjectOpenHashMap<>()); } public boolean contains(EntryTypes type, String name) { @@ -50,17 +52,18 @@ public void clear() { registryMap.clear(); } - public Set getEntryNames(EntryTypes type) { - return new HashSet<>(registryMap.getOrDefault(type, Collections.emptyMap()).keySet()); + public boolean isEmpty() { + return registryMap.isEmpty(); } @Override - public @NotNull CompoundTag serializeNBT() { + public CompoundTag serializeNBT() { CompoundTag tag = new CompoundTag(); for (Map.Entry, Map> entry : registryMap.entrySet()) { - CompoundTag entriesTag = new CompoundTag(); - for (Map.Entry subEntry : entry.getValue().entrySet()) { - entriesTag.put(subEntry.getKey(), subEntry.getValue().serializeNBT()); + ListTag entriesTag = new ListTag(); + for (VirtualEntry innerEntry : entry.getValue().values()) { + if (innerEntry.canRemove()) continue; + entriesTag.add(innerEntry.serializeNBT()); } tag.put(entry.getKey().toString(), entriesTag); } @@ -70,17 +73,30 @@ public Set getEntryNames(EntryTypes type) { @Override public void deserializeNBT(CompoundTag nbt) { for (String entryTypeString : nbt.getAllKeys()) { - EntryTypes type = entryTypeString.contains(":") ? - EntryTypes.fromLocation(ResourceLocation.tryParse(entryTypeString)) : - EntryTypes.fromString(entryTypeString); - + ResourceLocation entryTypeLoc = ResourceLocation.tryParse(entryTypeString); + if (entryTypeLoc == null) continue; + EntryTypes type = EntryTypes.fromLocation(entryTypeLoc); if (type == null) continue; - CompoundTag virtualEntries = nbt.getCompound(entryTypeString); - for (String name : virtualEntries.getAllKeys()) { - CompoundTag entryTag = virtualEntries.getCompound(name); - addEntry(name, type.createInstance(entryTag)); + Tag virtualEntries = nbt.get(entryTypeString); + + // backwards compat + if (virtualEntries instanceof CompoundTag compoundTag) { + for (String name : compoundTag.getAllKeys()) { + CompoundTag entryTag = compoundTag.getCompound(name); + VirtualEntry entry = type.createInstance(entryTag); + if (entry.canRemove()) continue; + addEntry(entry.getColorStr(), type.createInstance(entryTag)); + } + } else { + ListTag listTag = (ListTag) virtualEntries; + for (int i = 0; i < Objects.requireNonNull(listTag).size(); i++) { + var entry = type.createInstance(listTag.getCompound(i)); + if (entry.canRemove()) continue; + addEntry(entry.getColorStr(), entry); + } } + } } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualItemStorage.java b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualItemStorage.java index 755964107b0..80296879c10 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualItemStorage.java +++ b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualItemStorage.java @@ -8,7 +8,6 @@ import net.minecraft.nbt.CompoundTag; import lombok.Getter; -import org.jetbrains.annotations.NotNull; import javax.annotation.ParametersAreNonnullByDefault; @@ -18,7 +17,6 @@ public class VirtualItemStorage extends VirtualEntry { protected static final int DEFAULT_SLOT_AMOUNT = 1; - @NotNull @Getter private final CustomItemStackHandler handler; diff --git a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualRedstone.java b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualRedstone.java index 74a1cfc7987..ac6c1437540 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualRedstone.java +++ b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualRedstone.java @@ -2,21 +2,16 @@ import com.gregtechceu.gtceu.api.misc.virtualregistry.EntryTypes; import com.gregtechceu.gtceu.api.misc.virtualregistry.VirtualEntry; - -import net.minecraft.nbt.CompoundTag; +import com.gregtechceu.gtceu.common.cover.ender.EnderRedstoneLinkCover; import it.unimi.dsi.fastutil.objects.Object2ShortMap; import it.unimi.dsi.fastutil.objects.Object2ShortOpenHashMap; import lombok.Getter; -import java.util.UUID; - public class VirtualRedstone extends VirtualEntry { - private static final String MEMBERS_KEY = "members"; - @Getter - private final Object2ShortMap members = new Object2ShortOpenHashMap<>(); + private final Object2ShortMap members = new Object2ShortOpenHashMap<>(); public VirtualRedstone() {} @@ -24,17 +19,17 @@ public int getSignal() { return members.values().intStream().max().orElse(0); } - public void addMember(UUID uuid) { - members.put(uuid, (short) 0); + public void addMember(EnderRedstoneLinkCover cover) { + members.put(cover, (short) 0); } - public void setSignal(UUID uuid, int signal) { - if (!members.containsKey(uuid)) return; - members.put(uuid, (short) signal); + public void setSignal(EnderRedstoneLinkCover cover, int signal) { + if (!members.containsKey(cover)) return; + members.put(cover, (short) signal); } - public void removeMember(UUID uuid) { - members.removeShort(uuid); + public void removeMember(EnderRedstoneLinkCover cover) { + members.removeShort(cover); } @Override @@ -42,25 +37,6 @@ public EntryTypes getType() { return EntryTypes.ENDER_REDSTONE; } - @Override - public CompoundTag serializeNBT() { - CompoundTag tag = super.serializeNBT(); - CompoundTag tag2 = new CompoundTag(); - for (var entry : members.object2ShortEntrySet()) - tag2.putShort(entry.getKey().toString(), entry.getShortValue()); - tag.put(MEMBERS_KEY, tag2); - return tag; - } - - @Override - public void deserializeNBT(CompoundTag nbt) { - super.deserializeNBT(nbt); - CompoundTag tag = nbt.getCompound(MEMBERS_KEY); - for (String uuid : tag.getAllKeys()) { - members.put(UUID.fromString(uuid), tag.getShort(uuid)); - } - } - @Override public boolean equals(Object o) { if (!(o instanceof VirtualRedstone other)) return false; diff --git a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualTank.java b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualTank.java index b142de09b9a..cc0c8d95ea4 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualTank.java +++ b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualTank.java @@ -8,14 +8,12 @@ import net.minecraftforge.fluids.capability.templates.FluidTank; import lombok.Getter; -import org.jetbrains.annotations.NotNull; public class VirtualTank extends VirtualEntry { public static final int DEFAULT_CAPACITY = 160_000; // 160B for per second transfer protected static final String CAPACITY_KEY = "capacity"; protected static final String FLUID_KEY = "fluid"; - @NotNull @Getter private final FluidTank fluidTank; private int capacity; diff --git a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/package-info.java b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/package-info.java new file mode 100644 index 00000000000..d5df35c7c58 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/package-info.java @@ -0,0 +1,4 @@ +@NotNullByDefault +package com.gregtechceu.gtceu.api.misc.virtualregistry.entries; + +import org.jetbrains.annotations.NotNullByDefault; diff --git a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/package-info.java b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/package-info.java new file mode 100644 index 00000000000..d99aeae2306 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/package-info.java @@ -0,0 +1,4 @@ +@NotNullByDefault +package com.gregtechceu.gtceu.api.misc.virtualregistry; + +import org.jetbrains.annotations.NotNullByDefault; diff --git a/src/main/java/com/gregtechceu/gtceu/api/mui/GTGuiScreen.java b/src/main/java/com/gregtechceu/gtceu/api/mui/GTGuiScreen.java new file mode 100644 index 00000000000..f4a84a9d66a --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/mui/GTGuiScreen.java @@ -0,0 +1,39 @@ +package com.gregtechceu.gtceu.api.mui; + +import com.gregtechceu.gtceu.common.mui.GTGuiTheme; + +import net.minecraft.client.gui.navigation.ScreenRectangle; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.ModularScreen; +import org.jetbrains.annotations.NotNull; + +import static com.gregtechceu.gtceu.GTCEu.MOD_ID; + +@OnlyIn(Dist.CLIENT) +public class GTGuiScreen extends ModularScreen { + + public GTGuiScreen(@NotNull ModularPanel mainPanel) { + this(mainPanel, GTGuiTheme.STANDARD); + } + + public GTGuiScreen(@NotNull ModularPanel mainPanel, GTGuiTheme theme) { + this(MOD_ID, mainPanel, theme); + } + + public GTGuiScreen(@NotNull String owner, @NotNull ModularPanel mainPanel, GTGuiTheme theme) { + this(owner, mainPanel, theme.getId()); + } + + public GTGuiScreen(String owner, ModularPanel mainPanel, String themeId) { + super(owner, mainPanel); + useTheme(themeId); + } + + @Override + public @NotNull ScreenRectangle getRectangle() { + return super.getRectangle(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/mui/IItemUIHolder.java b/src/main/java/com/gregtechceu/gtceu/api/mui/IItemUIHolder.java new file mode 100644 index 00000000000..21a2154c7a5 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/mui/IItemUIHolder.java @@ -0,0 +1,51 @@ +package com.gregtechceu.gtceu.api.mui; + +import com.gregtechceu.gtceu.api.item.component.IInteractionItem; + +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import brachy.modularui.api.IUIHolder; +import brachy.modularui.factory.PlayerInventoryGuiData; +import brachy.modularui.factory.PlayerInventoryUIFactory; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.ModularScreen; + +public interface IItemUIHolder extends IUIHolder>, IInteractionItem { + + default boolean shouldOpenUI() { + return true; + } + + @Override + default InteractionResultHolder use(Item item, Level level, Player player, InteractionHand usedHand) { + if (!shouldOpenUI()) + return IInteractionItem.super.use(item, level, player, usedHand); + if (level.isClientSide) + PlayerInventoryUIFactory.INSTANCE.openFromHandClient(usedHand); + return InteractionResultHolder.sidedSuccess(player.getItemInHand(usedHand), level.isClientSide); + } + + @Override + default InteractionResult useOn(UseOnContext context) { + if (!shouldOpenUI()) + return IInteractionItem.super.useOn(context); + if (context.getLevel().isClientSide) + PlayerInventoryUIFactory.INSTANCE.openFromHandClient(context.getHand()); + return InteractionResult.SUCCESS; + } + + @Override + @OnlyIn(Dist.CLIENT) + default ModularScreen createScreen(PlayerInventoryGuiData data, ModularPanel mainPanel) { + return new GTGuiScreen(mainPanel); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/mui/factory/CoverUIFactory.java b/src/main/java/com/gregtechceu/gtceu/api/mui/factory/CoverUIFactory.java new file mode 100644 index 00000000000..b426f33934e --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/mui/factory/CoverUIFactory.java @@ -0,0 +1,84 @@ +package com.gregtechceu.gtceu.api.mui.factory; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.api.capability.GTCapability; +import com.gregtechceu.gtceu.api.capability.ICoverable; +import com.gregtechceu.gtceu.api.cover.CoverBehavior; +import com.gregtechceu.gtceu.api.cover.IMuiCover; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.entity.BlockEntity; + +import brachy.modularui.api.IUIHolder; +import brachy.modularui.factory.AbstractUIFactory; +import brachy.modularui.factory.GuiManager; +import brachy.modularui.factory.SidedPosGuiData; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public class CoverUIFactory extends AbstractUIFactory { + + public static final CoverUIFactory INSTANCE = new CoverUIFactory(); + + private CoverUIFactory() { + super(GTCEu.id("cover")); + } + + public void open(ServerPlayer player, IMuiCover cover) { + Objects.requireNonNull(player); + Objects.requireNonNull(cover); + if (cover.isRemoved()) { + throw new IllegalArgumentException("Can't open Cover GUI on invalid cover holder!"); + } + if (player.level() != cover.self().coverHolder.getLevel()) { + throw new IllegalArgumentException("Cover must be in same dimension as the player!"); + } + BlockPos pos = cover.self().coverHolder.getBlockPos(); + Direction side = cover.self().attachedSide; + SidedPosGuiData data = new SidedPosGuiData(player, pos, side); + GuiManager.open(this, data, player); + } + + @Override + public @NotNull IUIHolder getGuiHolder(SidedPosGuiData data) { + BlockEntity be = data.getBlockEntity(); + if (be == null) { + throw new IllegalStateException("Could not get gui for null BlockEntity!"); + } + ICoverable coverHolder = be.getCapability(GTCapability.CAPABILITY_COVERABLE, data.getSide()) + .resolve().orElse(null); + if (coverHolder == null) { + throw new IllegalStateException("Could not get CoverHolder for found BlockEntity!"); + } + CoverBehavior cover = coverHolder.getCoverAtSide(data.getSide()); + if (cover == null) { + throw new IllegalStateException("Could not find cover at side " + data.getSide() + + " for found CoverHolder!"); + } + if (!(cover instanceof IMuiCover uiCover)) { + throw new IllegalStateException("Cover at side " + data.getSide() + " is not a gui holder!"); + } + return uiCover; + } + + @Override + public boolean canInteractWith(Player player, SidedPosGuiData guiData) { + return guiData.getSquaredDistance(player) <= 8 * 8; + } + + @Override + public void writeGuiData(SidedPosGuiData guiData, FriendlyByteBuf buffer) { + buffer.writeBlockPos(guiData.getBlockPos()); + buffer.writeByte(guiData.getSide().get3DDataValue()); + } + + @Override + public @NotNull SidedPosGuiData readGuiData(Player player, FriendlyByteBuf buffer) { + return new SidedPosGuiData(player, buffer.readBlockPos(), Direction.from3DDataValue(buffer.readByte())); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/mui/factory/MachineUIFactory.java b/src/main/java/com/gregtechceu/gtceu/api/mui/factory/MachineUIFactory.java new file mode 100644 index 00000000000..beaedb6ed98 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/mui/factory/MachineUIFactory.java @@ -0,0 +1,94 @@ +package com.gregtechceu.gtceu.api.mui.factory; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.api.machine.MetaMachine; +import com.gregtechceu.gtceu.api.machine.feature.IMuiMachine; +import com.gregtechceu.gtceu.api.mui.GTGuiScreen; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import brachy.modularui.api.IUIHolder; +import brachy.modularui.factory.AbstractUIFactory; +import brachy.modularui.factory.GuiManager; +import brachy.modularui.factory.PosGuiData; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.ModularScreen; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +import static com.gregtechceu.gtceu.GTCEu.MOD_ID; + +public class MachineUIFactory extends AbstractUIFactory { + + public static final MachineUIFactory INSTANCE = new MachineUIFactory(); + + private MachineUIFactory() { + super(GTCEu.id("machine")); + } + + public void open(ServerPlayer player, IMuiMachine machine) { + Objects.requireNonNull(player); + Objects.requireNonNull(machine); + if (machine.self().isRemoved()) { + throw new IllegalArgumentException("Can't open invalid MetaMachine GUI!"); + } + if (player.level() != machine.self().getLevel()) { + throw new IllegalArgumentException("MetaMachine must be in same dimension as the player!"); + } + BlockPos pos = machine.self().getBlockPos(); + PosGuiData data = new PosGuiData(player, pos); + GuiManager.open(this, data, player); + } + + public void open(Player player, BlockPos pos) { + Objects.requireNonNull(player); + Objects.requireNonNull(pos); + PosGuiData data = new PosGuiData(player, pos); + GuiManager.open(this, data, (ServerPlayer) player); + } + + @Override + public @NotNull IUIHolder getGuiHolder(PosGuiData data) { + MetaMachine machine = getMachine(data); + if (machine.getDefinition().getUI() != null) { + return machine.getDefinition().getUI(); + } + return Objects.requireNonNull(castUIHolder(machine), "Found MetaMachine is not a gui holder!"); + } + + @Override + public boolean canInteractWith(Player player, PosGuiData guiData) { + return player == guiData.getPlayer() && getMachine(guiData) != null && + guiData.getSquaredDistance(player) <= 8 * 8; + } + + @Override + public void writeGuiData(PosGuiData guiData, FriendlyByteBuf buffer) { + buffer.writeBlockPos(guiData.getBlockPos()); + } + + @Override + public @NotNull PosGuiData readGuiData(Player player, FriendlyByteBuf buffer) { + return new PosGuiData(player, buffer.readBlockPos()); + } + + public static MetaMachine getMachine(PosGuiData data) { + return MetaMachine.getMachine(data.getLevel(), data.getBlockPos()); + } + + @Override + @OnlyIn(Dist.CLIENT) + public ModularScreen createScreen(PosGuiData data, ModularPanel mainPanel) { + return new GTGuiScreen(MOD_ID, mainPanel, getThemeId(data)); + } + + public String getThemeId(PosGuiData data) { + return getMachine(data).getDefinition().getThemeId(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/mui/factory/ModularItemUIFactory.java b/src/main/java/com/gregtechceu/gtceu/api/mui/factory/ModularItemUIFactory.java new file mode 100644 index 00000000000..6813c365668 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/mui/factory/ModularItemUIFactory.java @@ -0,0 +1,33 @@ +package com.gregtechceu.gtceu.api.mui.factory; + +import com.gregtechceu.gtceu.GTCEu; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Player; + +import brachy.modularui.api.IUIHolder; +import brachy.modularui.factory.AbstractUIFactory; +import brachy.modularui.factory.GuiData; +import org.jetbrains.annotations.NotNull; + +public class ModularItemUIFactory extends AbstractUIFactory { + + public static final ModularItemUIFactory INSTANCE = new ModularItemUIFactory(); + + protected ModularItemUIFactory() { + super(GTCEu.id("modular_item")); + } + + @Override + public @NotNull IUIHolder getGuiHolder(GuiData data) { + return new ModularItemUIHolder(data.getPlayer()); + } + + @Override + public void writeGuiData(GuiData data, FriendlyByteBuf buf) {} + + @Override + public @NotNull GuiData readGuiData(Player player, FriendlyByteBuf buf) { + return new GuiData(player); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/mui/factory/ModularItemUIHolder.java b/src/main/java/com/gregtechceu/gtceu/api/mui/factory/ModularItemUIHolder.java new file mode 100644 index 00000000000..0312ff44c84 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/mui/factory/ModularItemUIHolder.java @@ -0,0 +1,266 @@ +package com.gregtechceu.gtceu.api.mui.factory; + +import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; +import com.gregtechceu.gtceu.api.item.module.AppliedItemModule; +import com.gregtechceu.gtceu.api.item.module.IModularItem; +import com.gregtechceu.gtceu.api.item.module.ItemModule; +import com.gregtechceu.gtceu.api.item.module.ItemModuleSlot; +import com.gregtechceu.gtceu.api.mui.GTGuiScreen; +import com.gregtechceu.gtceu.common.mui.GTGuiTextures; +import com.gregtechceu.gtceu.common.mui.GTMuiWidgets; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.wrapper.PlayerArmorInvWrapper; + +import brachy.modularui.api.IPanelHandler; +import brachy.modularui.api.IUIHolder; +import brachy.modularui.api.drawable.IDrawable; +import brachy.modularui.api.drawable.IKey; +import brachy.modularui.api.widget.IWidget; +import brachy.modularui.drawable.GuiDraw; +import brachy.modularui.factory.GuiData; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.ModularScreen; +import brachy.modularui.screen.UISettings; +import brachy.modularui.screen.viewport.ModularGuiContext; +import brachy.modularui.theme.WidgetThemeEntry; +import brachy.modularui.utils.Alignment; +import brachy.modularui.value.sync.*; +import brachy.modularui.widgets.*; +import brachy.modularui.widgets.layout.Flow; +import brachy.modularui.widgets.layout.Grid; +import brachy.modularui.widgets.slot.ItemSlot; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +@Setter(AccessLevel.PRIVATE) +@Getter(AccessLevel.PRIVATE) +public class ModularItemUIHolder implements IUIHolder { + + private final Player player; + private boolean inventoryUnlocked = false; + private IntSyncValue selectedSlotSyncValue = null; + private int selectedSlot = -1; + private int panelCount = 0; + private DynamicSyncHandler dynamicSyncHandler = null; + + public ModularItemUIHolder(Player player) { + this.player = player; + } + + private void registerSyncValues(PanelSyncManager syncManager) { + dynamicSyncHandler = new DynamicSyncHandler(); + dynamicSyncHandler.widgetProvider(this::getStackInfoWidget); + selectedSlotSyncValue = SyncHandlers.intNumber(this::getSelectedSlot, this::setSelectedSlot); + syncManager.syncValue("selectedSlot", selectedSlotSyncValue); + } + + @Override + public ModularPanel buildUI(GuiData data, PanelSyncManager syncManager, UISettings settings) { + registerSyncValues(syncManager); + return new ModularPanel<>("modularItem") + .leftRel(.2f) + .width(250) + .child(GTMuiWidgets.createTitleBar(IDrawable.EMPTY.asIcon().size(0), "Modules", 250, + GTGuiTextures.BACKGROUND)) + .child(playerInventory()) + .child(new ToggleButton() + .value(new BooleanSyncValue(this::isInventoryUnlocked, this::setInventoryUnlocked)) + .overlay(true, GTGuiTextures.BUTTON_LOCK) + .overlay(false, GTGuiTextures.BUTTON_LOCK) + .invertSelected(true) + .left(7).bottom(7)) + .child(new DynamicSyncedWidget<>() + .syncHandler(dynamicSyncHandler) + .initialChild(new TextWidget<>("Select an item") + .center()) + .widthRel(1) + .height(85) + .top(5)); + } + + private IWidget getStackInfoWidget(PanelSyncManager psm, FriendlyByteBuf buf) { + ItemStack stack = getSelectedItem(); + IModularItem modularItem = GTCapabilityHelper.getModularItem(stack); + List slots = modularItem == null ? List.of() : modularItem.getSlots(); + return Flow.col() + .horizontalCenter() + .widthRel(1) + .child(Flow.row() + .coverChildren() + .childPadding(5) + .child(new ItemDisplayWidget().item(stack)) + .child(new TextWidget<>(IKey.dynamic(stack::getHoverName)))) + .childIf(modularItem == null, + () -> new TextWidget<>(IKey.str("This item does not accept modules")).center()) + .childIf(modularItem != null, () -> new Grid() + .minColWidth(100) + .widthRel(1) + .minRowHeight(10) + .margin(5) + .mapTo(2, slots.size(), index -> { + assert modularItem != null; + AppliedItemModule appliedModule = modularItem.getModuleInSlot(index); + if (appliedModule == null) { + return new ButtonWidget<>() + .height(10) + .widthRel(0.5f) + .backgroundOverlay(slots.get(index).getSlotTexture()) + .overlay(IKey.lang("metaarmor.tooltip.modifier.empty").scale(0.5f)); + } else { + ItemModule module = appliedModule.getModule(); + IPanelHandler panelHandler = psm.syncedPanel("module" + index, false, + (psm1, handler) -> createPanelForModule(psm1, handler, index)); + return new ButtonWidget<>() + .onMousePressed((x, y, button) -> { + panelHandler.openPanel(); + return false; + }) + .height(10) + .widthRel(0.5f) + .overlay(IKey.dynamic(() -> module.getDisplayName(appliedModule)).scale(0.5f)) + .backgroundOverlay(slots.get(index).getSlotTexture()) + .addTooltipElement(IKey.dynamic(module::getInfo)); + } + })); + } + + private ModularPanel createPanelForModule(PanelSyncManager psm, IPanelHandler panelHandler, int index) { + ItemStack stack = getSelectedItem(); + IModularItem modularItem = GTCapabilityHelper.getModularItem(stack); + assert modularItem != null; + AppliedItemModule appliedModule = modularItem.getModuleInSlot(index); + assert appliedModule != null; + ItemModule module = appliedModule.getModule(); + ItemStack moduleItem = appliedModule.getModuleItem(); + return new ModularPanel<>("module" + index) + .leftRelOffset(0.2f, 250 + 2 - 154 * (panelCount / 3)) + .topRelOffset(0.5f, -83 + 80 * (panelCount++ % 3) + 2) + .width(154) + .height(80) + .child(Flow.col() + .crossAxisAlignment(Alignment.CrossAxis.START) + .left(5) + .childPadding(3) + .childIf(moduleItem == null || moduleItem.isEmpty(), + () -> new TextWidget<>(IKey.dynamic(() -> module.getDisplayName(appliedModule))) + .scale(0.75f) + .horizontalCenter()) + .childIf(moduleItem != null && !moduleItem.isEmpty(), () -> { + assert moduleItem != null; + return Flow.row() + .coverChildren() + .padding(4) + .paddingLeft(0) + .childPadding(4) + .child(new ItemDisplayWidget().item(moduleItem)) + .child(Flow.col() + .coverChildrenWidth() + .childPadding(2) + .heightRel(1) + .child(new TextWidget<>( + IKey.dynamic(() -> module.getDisplayName(appliedModule))) + .scale(0.75f) + .left(0)) + .child(new TextWidget<>(IKey.dynamic(moduleItem::getHoverName)) + .scale(0.6f) + .left(0))); + }) + .children(module.getSettings(appliedModule, psm, index))); + } + + private ItemStack getSelectedItem() { + return player.getInventory().getItem(selectedSlot); + } + + @Override + public ModularScreen createScreen(GuiData data, ModularPanel mainPanel) { + return new GTGuiScreen(mainPanel); + } + + private class InventorySlot extends ItemSlot { + + private Integer index = null; + + public InventorySlot index(int index) { + this.index = index; + return this; + } + + private int getIndex() { + return index == null ? getSlot().getSlotIndex() : index; + } + + @Override + public @NotNull Result onMousePressed(double mouseX, double mouseY, int button) { + if (inventoryUnlocked) + return super.onMousePressed(mouseX, mouseY, button); + selectedSlotSyncValue.setValue(getIndex()); + dynamicSyncHandler.notifyUpdate(buf -> {}); + return Result.SUCCESS; + } + + @Override + public boolean onMouseReleased(double mouseX, double mouseY, int button) { + if (inventoryUnlocked) + return super.onMouseReleased(mouseX, mouseY, button); + return false; + } + + @Override + protected void drawOverlay(ModularGuiContext context) { + if (inventoryUnlocked) + super.drawOverlay(context); + if (getIndex() == selectedSlot) { + GuiDraw.drawBorder(context.getGraphics(), 0, 0, 17, 17, 0xFFFFFF00, 1); + } + } + + @Override + public void draw(ModularGuiContext context, WidgetThemeEntry widgetTheme) { + if (!inventoryUnlocked && !isHovering() && getIndex() != selectedSlot) { + GuiDraw.drawRect(context.getGraphics(), 1, 1, 15, 15, 0x88444444); + } + super.draw(context, widgetTheme); + } + } + + private Flow playerInventory() { + SlotGroupWidget slotGroupWidget = new SlotGroupWidget(); + slotGroupWidget.coverChildren(); + slotGroupWidget.name("player_inventory"); + String key = "player"; + for (int i = 0; i < 9; i++) { + slotGroupWidget.child(new InventorySlot() + .syncHandler(key, i) + .pos(i * 18, 3 * 18 + 4) + .name("slot_" + i)); + } + for (int i = 0; i < 27; i++) { + slotGroupWidget.child(new InventorySlot() + .syncHandler(key, i + 9) + .pos(i % 9 * 18, i / 9 * 18) + .name("slot_" + (i + 9))); + } + SlotGroupWidget armorGroup = new SlotGroupWidget(); + armorGroup.coverChildren(); + armorGroup.name("player_armor"); + PlayerArmorInvWrapper inv = new PlayerArmorInvWrapper(player.getInventory()); + for (int i = 0; i < 4; i++) { + armorGroup.child(new InventorySlot() + .index(36 + i) + .slot(inv, i) + .pos(0, (3 - i) * 18) + .name("slot_" + (i + 36))); + } + return Flow.row() + .child(slotGroupWidget.bottom(7).leftRel(.5f)) + .child(armorGroup.bottom(7).leftRelOffset(.5f, 162 / 2 + 20)); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/mui/factory/PanelEditor.java b/src/main/java/com/gregtechceu/gtceu/api/mui/factory/PanelEditor.java new file mode 100644 index 00000000000..a44f1c260a4 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/mui/factory/PanelEditor.java @@ -0,0 +1,15 @@ +package com.gregtechceu.gtceu.api.mui.factory; + +import com.gregtechceu.gtceu.api.machine.MetaMachine; + +import brachy.modularui.factory.PosGuiData; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.sync.PanelSyncManager; + +@FunctionalInterface +public interface PanelEditor { + + void editUI(PosGuiData data, PanelSyncManager syncManager, UISettings settings, + MetaMachine machine, ModularPanel panel); +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/mui/factory/PanelFactory.java b/src/main/java/com/gregtechceu/gtceu/api/mui/factory/PanelFactory.java new file mode 100644 index 00000000000..0b166d5b795 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/mui/factory/PanelFactory.java @@ -0,0 +1,63 @@ +package com.gregtechceu.gtceu.api.mui.factory; + +import com.gregtechceu.gtceu.api.machine.MetaMachine; +import com.gregtechceu.gtceu.api.mui.GTGuiScreen; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import brachy.modularui.api.IUIHolder; +import brachy.modularui.factory.PosGuiData; +import brachy.modularui.screen.ModularPanel; +import brachy.modularui.screen.ModularScreen; +import brachy.modularui.screen.UISettings; +import brachy.modularui.value.sync.PanelSyncManager; + +@FunctionalInterface +public interface PanelFactory extends IUIHolder { + + @Override + default ModularPanel buildUI(PosGuiData data, PanelSyncManager syncManager, UISettings settings) { + var machine = MachineUIFactory.getMachine(data); + return buildUIFunction(data, syncManager, settings, machine); + } + + @Override + @OnlyIn(Dist.CLIENT) + default ModularScreen createScreen(PosGuiData data, ModularPanel mainPanel) { + return new GTGuiScreen(mainPanel); + } + + ModularPanel buildUIFunction(PosGuiData data, PanelSyncManager syncManager, UISettings settings, + MetaMachine machine); + + default boolean shouldOpenUI(Player player, InteractionHand hand, BlockHitResult hit) { + return true; + } + + default InteractionResult tryToOpenUI(Player player, InteractionHand hand, BlockHitResult hit) { + if (this.shouldOpenUI(player, hand, hit)) { + if (player instanceof ServerPlayer serverPlayer) { + MachineUIFactory.INSTANCE.open(serverPlayer, hit.getBlockPos()); + } + return InteractionResult.sidedSuccess(player.level().isClientSide); + } else { + return InteractionResult.PASS; + } + } + + default PanelFactory andThen(PanelEditor... edits) { + return (data, syncManager, settings, machine) -> { + var panel = this.buildUIFunction(data, syncManager, settings, machine); + for (PanelEditor edit : edits) { + edit.editUI(data, syncManager, settings, machine, panel); + } + return panel; + }; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/pattern/MultiblockShapeInfo.java b/src/main/java/com/gregtechceu/gtceu/api/pattern/MultiblockShapeInfo.java index cc1c36353af..95e52709df7 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/pattern/MultiblockShapeInfo.java +++ b/src/main/java/com/gregtechceu/gtceu/api/pattern/MultiblockShapeInfo.java @@ -4,31 +4,43 @@ import com.gregtechceu.gtceu.api.data.RotationState; import com.lowdragmc.lowdraglib.utils.BlockInfo; -import com.lowdragmc.lowdraglib.utils.Builder; import net.minecraft.core.Direction; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; +import lombok.Getter; + +import java.util.*; import java.util.function.Supplier; public class MultiblockShapeInfo { + @Getter private final BlockInfo[][][] blocks; // [z][y][x] public MultiblockShapeInfo(BlockInfo[][][] blocks) { this.blocks = blocks; } - public BlockInfo[][][] getBlocks() { - return blocks; - } - public static ShapeInfoBuilder builder() { return new ShapeInfoBuilder(); } - public static class ShapeInfoBuilder extends Builder { + public static class ShapeInfoBuilder { + + protected List shape = new ArrayList<>(); + protected Map symbolMap = new LinkedHashMap<>(); + + public ShapeInfoBuilder aisle(String... data) { + this.shape.add(data); + return this; + } + + public ShapeInfoBuilder where(char symbol, BlockInfo value) { + this.symbolMap.put(symbol, value); + return this; + } public ShapeInfoBuilder where(char symbol, BlockState blockState) { return where(symbol, BlockInfo.fromBlockState(blockState)); @@ -53,11 +65,29 @@ public ShapeInfoBuilder where(char symbol, MetaMachineBlock machine, Direction f } private BlockInfo[][][] bake() { - return this.bakeArray(BlockInfo.class, BlockInfo.EMPTY); + BlockInfo[][][] Ts = new BlockInfo[shape.get(0)[0].length()][shape.get(0).length][shape.size()]; + for (int z = 0; z < shape.size(); z++) { // z + String[] aisleEntry = shape.get(z); + for (int y = 0; y < shape.get(0).length; y++) { + String columnEntry = aisleEntry[y]; + for (int x = 0; x < columnEntry.length(); x++) { + BlockInfo info = symbolMap.getOrDefault(columnEntry.charAt(x), BlockInfo.EMPTY); + Ts[x][y][z] = info; + } + } + } + return Ts; } public MultiblockShapeInfo build() { return new MultiblockShapeInfo(bake()); } + + public ShapeInfoBuilder shallowCopy() { + ShapeInfoBuilder builder = new ShapeInfoBuilder(); + builder.shape = new ArrayList<>(this.shape); + builder.symbolMap = new HashMap<>(this.symbolMap); + return builder; + } } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/placeholder/MultiLineComponent.java b/src/main/java/com/gregtechceu/gtceu/api/placeholder/MultiLineComponent.java index ac19946fe1b..f25c0c484a6 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/placeholder/MultiLineComponent.java +++ b/src/main/java/com/gregtechceu/gtceu/api/placeholder/MultiLineComponent.java @@ -18,6 +18,7 @@ import java.util.Collection; import java.util.List; import java.util.Objects; +import java.util.function.UnaryOperator; @Accessors(chain = true) public class MultiLineComponent extends ArrayList { @@ -134,6 +135,16 @@ public MultiLineComponent withStyle(Style style) { return out; } + public MultiLineComponent withStyle(UnaryOperator