Added stack merging, RMB actions, Sticks and fixed an unholy bug
- Added Test:Stick - When left-clicking, stacks that can merge will - Added right-clicking behavior straight from Minecraft - hooooooly sh*t man StatefulObject.equals was totally broken omfg how tf i did notice :o
This commit is contained in:
parent
b3ac7b6afe
commit
040a4f7fd7
@ -235,7 +235,7 @@ public abstract class StatefulObject extends Namespaced implements Encodable {
|
|||||||
|
|
||||||
StatefulObject statefulObj = (StatefulObject) obj;
|
StatefulObject statefulObj = (StatefulObject) obj;
|
||||||
|
|
||||||
if (statefulObj.getId().equals(this.getId()))
|
if (!statefulObj.getId().equals(this.getId()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -94,6 +94,21 @@ public class ItemSlot implements Encodable {
|
|||||||
return amount == 0;
|
return amount == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized boolean canInsert(ItemData contents, int amount) {
|
||||||
|
|
||||||
|
// Ignore amount
|
||||||
|
|
||||||
|
if (this.contents == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.contents.equals(contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean canRemove(int amount) {
|
||||||
|
return this.amount >= amount;
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized void checkState() {
|
private synchronized void checkState() {
|
||||||
if ((contents == null) != (amount == 0)) {
|
if ((contents == null) != (amount == 0)) {
|
||||||
if (contents == null) {
|
if (contents == null) {
|
||||||
|
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package ru.windcorp.progressia.common.world.item;
|
||||||
|
|
||||||
|
public class Items {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to transfer as many items as possible, but no more than
|
||||||
|
* {@code max}, between two slots. The origin of the items is {@code from},
|
||||||
|
* the destination is {@code into}. This method does nothing if the items
|
||||||
|
* could not be removed from origin or could not be inserted into
|
||||||
|
* destination, such as when {@code into} contains different items.
|
||||||
|
*
|
||||||
|
* @param from the slot to transfer item from
|
||||||
|
* @param into the destination of the items
|
||||||
|
* @param max the maximum amount of items to transfer. Use
|
||||||
|
* {@code Integer.MAX_VALUE} to remove the limit
|
||||||
|
* @return the actual amount of items moved between slots
|
||||||
|
*/
|
||||||
|
public static int pour(ItemSlot from, ItemSlot into, int max) {
|
||||||
|
synchronized (from) {
|
||||||
|
synchronized (into) {
|
||||||
|
|
||||||
|
ItemData item = from.getContents();
|
||||||
|
|
||||||
|
int originalAmount = from.getAmount();
|
||||||
|
int transferAmount = Math.min(originalAmount, max);
|
||||||
|
|
||||||
|
while (transferAmount > 0 && !into.canInsert(item, transferAmount)) {
|
||||||
|
transferAmount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transferAmount == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!from.canRemove(transferAmount)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
into.setContents(item, into.getAmount() + transferAmount);
|
||||||
|
from.setAmount(originalAmount - transferAmount);
|
||||||
|
|
||||||
|
return transferAmount;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to transfer as many items as possible between two slots. The
|
||||||
|
* origin of the items is {@code from}, the destination is {@code into}.
|
||||||
|
* This method does nothing if the items could not be removed from origin or
|
||||||
|
* could not be inserted into destination, such as when {@code into}
|
||||||
|
* contains different items.
|
||||||
|
*
|
||||||
|
* @param from the slot to transfer item from
|
||||||
|
* @param into the destination of the items
|
||||||
|
* @return the actual amount of items moved between slots
|
||||||
|
*/
|
||||||
|
public static int pour(ItemSlot from, ItemSlot into) {
|
||||||
|
return pour(from, into, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to swap the contents of the two slots.
|
||||||
|
*
|
||||||
|
* @param a one of the slots
|
||||||
|
* @param b the other slot
|
||||||
|
*
|
||||||
|
* @return whether the swap succeeded
|
||||||
|
*/
|
||||||
|
public static boolean swap(ItemSlot a, ItemSlot b) {
|
||||||
|
synchronized (a) {
|
||||||
|
synchronized (b) {
|
||||||
|
|
||||||
|
ItemData aItem = a.getContents();
|
||||||
|
int aAmount = a.getAmount();
|
||||||
|
|
||||||
|
ItemData bItem = b.getContents();
|
||||||
|
int bAmount = b.getAmount();
|
||||||
|
|
||||||
|
a.clear();
|
||||||
|
b.clear();
|
||||||
|
|
||||||
|
if (a.canInsert(bItem, bAmount) && b.canInsert(aItem, aAmount)) {
|
||||||
|
a.setContents(bItem, bAmount);
|
||||||
|
b.setContents(aItem, aAmount);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
a.setContents(aItem, aAmount);
|
||||||
|
b.setContents(bItem, bAmount);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Items() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -65,7 +65,8 @@ public class PlayerManager {
|
|||||||
|
|
||||||
player.getInventory().addSlots(10);
|
player.getInventory().addSlots(10);
|
||||||
|
|
||||||
player.getInventory().getSlot(3).setContents(ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream"), 5);
|
player.getInventory().getSlot(3).setContents(ItemDataRegistry.getInstance().create("Test:Stick"), 5);
|
||||||
|
player.getInventory().getSlot(5).setContents(ItemDataRegistry.getInstance().create("Test:Stick"), 4);
|
||||||
player.getInventory().getSlot(6).setContents(ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream"), 1);
|
player.getInventory().getSlot(6).setContents(ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream"), 1);
|
||||||
|
|
||||||
player.setPosition(getServer().getWorld().getGenerator().suggestSpawnLocation());
|
player.setPosition(getServer().getWorld().getGenerator().suggestSpawnLocation());
|
||||||
|
@ -106,7 +106,7 @@ public class TestContent {
|
|||||||
register(new BlockRenderNone("Test:Air"));
|
register(new BlockRenderNone("Test:Air"));
|
||||||
register(new TestBlockLogicAir("Test:Air"));
|
register(new TestBlockLogicAir("Test:Air"));
|
||||||
placeableBlacklist.add("Test:Air");
|
placeableBlacklist.add("Test:Air");
|
||||||
|
|
||||||
registerSimplestBlock("Dirt");
|
registerSimplestBlock("Dirt");
|
||||||
registerSimplestBlock("Chernozem");
|
registerSimplestBlock("Chernozem");
|
||||||
registerSimplestBlock("Stone");
|
registerSimplestBlock("Stone");
|
||||||
@ -244,6 +244,7 @@ public class TestContent {
|
|||||||
|
|
||||||
private static void registerItems() {
|
private static void registerItems() {
|
||||||
registerSimplestItem("MoonTypeIceCream", Units.get("200 g"), Units.get("1 L"));
|
registerSimplestItem("MoonTypeIceCream", Units.get("200 g"), Units.get("1 L"));
|
||||||
|
registerSimplestItem("Stick", Units.get("260 g"), Units.get("0.5 L"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerSimplestBlock(String name) {
|
private static void registerSimplestBlock(String name) {
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
package ru.windcorp.progressia.test.inv;
|
package ru.windcorp.progressia.test.inv;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
@ -33,11 +34,13 @@ import ru.windcorp.progressia.client.graphics.gui.Layout;
|
|||||||
import ru.windcorp.progressia.client.graphics.gui.Panel;
|
import ru.windcorp.progressia.client.graphics.gui.Panel;
|
||||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign;
|
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign;
|
||||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill;
|
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill;
|
||||||
|
import ru.windcorp.progressia.client.graphics.input.KeyEvent;
|
||||||
|
import ru.windcorp.progressia.client.graphics.input.bus.InputListener;
|
||||||
import ru.windcorp.progressia.client.graphics.model.Renderable;
|
import ru.windcorp.progressia.client.graphics.model.Renderable;
|
||||||
import ru.windcorp.progressia.common.world.entity.EntityDataPlayer;
|
import ru.windcorp.progressia.common.world.entity.EntityDataPlayer;
|
||||||
import ru.windcorp.progressia.common.world.item.ItemContainer;
|
import ru.windcorp.progressia.common.world.item.ItemContainer;
|
||||||
import ru.windcorp.progressia.common.world.item.ItemData;
|
|
||||||
import ru.windcorp.progressia.common.world.item.ItemSlot;
|
import ru.windcorp.progressia.common.world.item.ItemSlot;
|
||||||
|
import ru.windcorp.progressia.common.world.item.Items;
|
||||||
|
|
||||||
public class InventoryScreen extends Component {
|
public class InventoryScreen extends Component {
|
||||||
|
|
||||||
@ -131,34 +134,72 @@ public class InventoryScreen extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addListeners(InventoryComponent mainInventory) {
|
private void addListeners(InventoryComponent mainInventory) {
|
||||||
Consumer<BasicButton> pickIntoLeft = createPickAction(leftHand.getSlot(0), rightHand.getSlot(0));
|
|
||||||
|
ItemSlot left = leftHand.getSlot(0);
|
||||||
for (DecoratedSlotComponent component : mainInventory.getSlots()) {
|
ItemSlot right = rightHand.getSlot(0);
|
||||||
component.addAction(pickIntoLeft);
|
|
||||||
}
|
Supplier<ItemSlot> handSlot = () -> {
|
||||||
}
|
|
||||||
|
|
||||||
private Consumer<BasicButton> createPickAction(ItemSlot toWithoutCtrl, ItemSlot toWithCtrl) {
|
|
||||||
return button -> {
|
|
||||||
|
|
||||||
boolean hasCtrl = InputTracker.isKeyPressed(GLFW.GLFW_KEY_LEFT_CONTROL)
|
boolean hasCtrl = InputTracker.isKeyPressed(GLFW.GLFW_KEY_LEFT_CONTROL)
|
||||||
|| InputTracker.isKeyPressed(GLFW.GLFW_KEY_RIGHT_CONTROL);
|
|| InputTracker.isKeyPressed(GLFW.GLFW_KEY_RIGHT_CONTROL);
|
||||||
|
|
||||||
ItemSlot to = hasCtrl ? toWithCtrl : toWithoutCtrl;
|
return hasCtrl ? left : right;
|
||||||
ItemSlot from = ((DecoratedSlotComponent) button).getSlot();
|
};
|
||||||
|
|
||||||
|
Consumer<BasicButton> pickAll = createPickAllAction(handSlot);
|
||||||
|
|
||||||
ItemData fromData = from.getContents();
|
for (DecoratedSlotComponent component : mainInventory.getSlots()) {
|
||||||
int fromAmount = from.getAmount();
|
component.addAction(pickAll);
|
||||||
|
component.addListener(KeyEvent.class, createRMBAction(component.getSlot(), handSlot));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Consumer<BasicButton> createPickAllAction(Supplier<ItemSlot> handSlotChooser) {
|
||||||
|
return button -> {
|
||||||
|
|
||||||
ItemData toData = to.getContents();
|
ItemSlot handSlot = handSlotChooser.get();
|
||||||
int toAmount = to.getAmount();
|
ItemSlot invSlot = ((DecoratedSlotComponent) button).getSlot();
|
||||||
|
|
||||||
from.setContents(toData, toAmount);
|
if (Items.pour(handSlot, invSlot) == 0) {
|
||||||
to.setContents(fromData, fromAmount);
|
if (!Items.swap(handSlot, invSlot)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
requestReassembly();
|
requestReassembly();
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private InputListener<KeyEvent> createRMBAction(ItemSlot invSlot, Supplier<ItemSlot> handSlotChooser) {
|
||||||
|
return input -> {
|
||||||
|
|
||||||
|
if (input.isPress() && input.isRightMouseButton()) {
|
||||||
|
ItemSlot handSlot = handSlotChooser.get();
|
||||||
|
|
||||||
|
boolean success = false;
|
||||||
|
|
||||||
|
if (handSlot.isEmpty()) {
|
||||||
|
success = Items.pour(invSlot, handSlot, invSlot.getAmount() / 2) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
success = Items.pour(handSlot, invSlot, 1) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
success = Items.swap(handSlot, invSlot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
requestReassembly();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
BIN
src/main/resources/assets/textures/items/Stick.png
Normal file
BIN
src/main/resources/assets/textures/items/Stick.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 775 B |
Reference in New Issue
Block a user