inventory #14

Merged
erns6604 merged 11 commits from inventory into main 2025-10-29 14:21:29 +01:00
13 changed files with 185 additions and 36 deletions

View File

@ -1,27 +1,74 @@
package Inventory;
import Item.Item;
import Item.ItemStack;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Inventory {
List<Item> items;
private final List<ItemStack> items;
private final int maxWeight;
public Inventory() {
items = new ArrayList<>();
maxWeight = 100;
}
public List<Item> getItems() {
public Inventory(int weightLimit) {
items = new ArrayList<>();
this.maxWeight = weightLimit;
}
public List<ItemStack> getItems() {
return Collections.unmodifiableList(items);
}
public void addItem(Item item) {
items.add(item);
public void addItem(ItemStack stack) {
if (stack.getWeight() + getCurrentWeight() > maxWeight) {
if(stack.isSingleItem()) return;
trySubstack(stack);
return;
}
items.add(stack);
}
public boolean containsItem(String item) {
return items.contains(item);
private void trySubstack(ItemStack stack) {
int stackSize = getMaxStackSize(stack);
if (stackSize == 0) return;
items.add(new ItemStack(stack.getItem(), stackSize));
}
private int getMaxStackSize(ItemStack stack) {
int weight = stack.getItem().getWeight();
int maxSize = (maxWeight - getCurrentWeight()) / weight;
return Math.min(maxSize, stack.getQuantity());
}
public int getCurrentWeight() {
int currentWeight = 0;
for (ItemStack item : items) {
currentWeight += item.getItem().getWeight();
}
return currentWeight;
}
private int calculateStackWeight(ItemStack stack) {
return stack.getItem().getWeight() * stack.getQuantity();
}
public boolean containsItem(Item item) {
for (ItemStack stack : items) {
if (stack.item().equals(item)) {
return true;
}
}
return false;
}
public int getMaxWeight() {
return maxWeight;
}
}

View File

@ -1,6 +1,6 @@
package Item;
public record BasicItem(String id, String name) implements Item {
public record BasicItem(String id, String name, int weight) implements Item {
@Override
public String getId() {
return id;
@ -10,4 +10,8 @@ public record BasicItem(String id, String name) implements Item {
public String getName() {
return name;
}
@Override
public int getWeight() {
return weight;
}
}

View File

@ -24,6 +24,11 @@ public class Equipment implements Item {
return name;
}
@Override
public int getWeight() {
return 0;
}
public EquipmentType getEquipmentType() {
return equipmentType;
}

View File

@ -3,4 +3,5 @@ package Item;
public interface Item {
String getId();
String getName();
int getWeight();
}

View File

@ -0,0 +1,26 @@
package Item;
import Inventory.Inventory;
public record ItemStack(Item item, int quantity) {
public ItemStack {
if (quantity <= 0) {
throw new IllegalArgumentException("Quantity must be greater than zero.");
}
}
public Item getItem() {
return item;
}
public int getQuantity() {
return quantity;
}
public boolean isSingleItem() {
return quantity == 1;
}
public int getWeight() {
return item.getWeight() * quantity;
}
}

View File

@ -1,6 +1,7 @@
package Job;
import Inventory.HasInventory;
import Item.ItemStack;
import Terrain.Biome;
@ -18,6 +19,6 @@ public class Miner extends Job {
public void dig(Biome biome) {
var item = biome.getLootTable().roll();
actor.getInventory().addItem(item);
actor.getInventory().addItem(new ItemStack(item, 1));
}
}

View File

@ -2,7 +2,6 @@ package Shared;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class LootTable<T> {
private RandomProvider random;
@ -18,6 +17,8 @@ public class LootTable<T> {
this.entries.addAll(entries);
}
public void setRandomProvider(RandomProvider random) {
this.random = random;
}
@ -43,4 +44,7 @@ public class LootTable<T> {
return null;
}
public List<LootEntry<T>> getEntries() {
return entries;
}
}

View File

@ -10,27 +10,27 @@ import java.util.List;
public enum Biome {
GRASSLAND("Grassland", new LootTable<>(new ArrayList<>(List.of(
new LootEntry<>(new BasicItem("mud", "Mud"), 10),
new LootEntry<>(new BasicItem("earth_root", "Earth Root"), 50),
new LootEntry<>(new BasicItem("crystal_core", "Crystal core"), 180)
new LootEntry<>(new BasicItem("mud", "Mud", 10), 10),
new LootEntry<>(new BasicItem("earth_root", "Earth Root", 5), 50),
new LootEntry<>(new BasicItem("crystal_core", "Crystal core", 20), 180)
)) {
})),
MOUNTAIN("Mountain", new LootTable<>(new ArrayList<>(List.of(
new LootEntry<>(new BasicItem("rock", "Rock"), 10),
new LootEntry<>(new BasicItem("iron", "Iron"), 50),
new LootEntry<>(new BasicItem("diamond", "Diamond"), 180)
new LootEntry<>(new BasicItem("rock", "Rock", 50), 10),
new LootEntry<>(new BasicItem("iron", "Iron", 80), 50),
new LootEntry<>(new BasicItem("diamond", "Diamond", 8), 180)
)) {
})),
COAST("Coast", new LootTable<>(new ArrayList<>(List.of(
new LootEntry<>(new BasicItem("sand", "Sand"), 10),
new LootEntry<>(new BasicItem("shell", "Shell"), 50),
new LootEntry<>(new BasicItem("sandfish", "Sandfish"), 180)
new LootEntry<>(new BasicItem("sand", "Sand", 1), 10),
new LootEntry<>(new BasicItem("shell", "Shell", 4), 50),
new LootEntry<>(new BasicItem("sandfish", "Sandfish", 11), 180)
)) {
})),
FOREST("Forest", new LootTable<>(new ArrayList<>(List.of(
new LootEntry<>(new BasicItem("moss", "Moss"), 10),
new LootEntry<>(new BasicItem("fairy_rock", "Fairy rock"), 50),
new LootEntry<>(new BasicItem("unicorn_horn", "Unicorn horn"), 230)
new LootEntry<>(new BasicItem("moss", "Moss", 7 ), 10),
new LootEntry<>(new BasicItem("fairy_rock", "Fairy rock", 89), 50),
new LootEntry<>(new BasicItem("unicorn_horn", "Unicorn horn", 18), 230)
)) {
}));

View File

@ -29,7 +29,7 @@ public class EquipmentTest {
@Test
void setTypeOnCreation() {
var e = defaultBodyArmour();
assertEquals("helmet", e.getEquipmentType().getName(), "Equipment type should have been set");
assertEquals("Body Armour", e.getEquipmentType().getName(), "Equipment type should have been set");
}
@Test
@ -41,19 +41,19 @@ public class EquipmentTest {
@Test
void setMaxHpModOnCreation() {
var e = defaultBodyArmour();
assertEquals(1, e.getEquipmentType().getModifiers().getMaxHpMod(), "Equipment max hp modifier should have been set");
assertEquals(4, e.getEquipmentType().getModifiers().getMaxHpMod(), "Equipment max hp modifier should have been set");
}
@Test
void setMaxMpModOnCreation() {
var e = defaultBodyArmour();
assertEquals(1, e.getEquipmentType().getModifiers().getMaxMpMod(), "Equipment max mp modifier should have been set");
assertEquals(8, e.getEquipmentType().getModifiers().getMaxMpMod(), "Equipment max mp modifier should have been set");
}
@Test
void setStrModOnCreation() {
var e = defaultBodyArmour();
assertEquals(1, e.getEquipmentType().getModifiers().getStrMod(), "Equipment strength modifier should have been set");
assertEquals(7, e.getEquipmentType().getModifiers().getStrMod(), "Equipment strength modifier should have been set");
}
@Test
@ -65,12 +65,12 @@ public class EquipmentTest {
@Test
void setDefModOnCreation() {
var e = defaultBodyArmour();
assertEquals(1, e.getEquipmentType().getModifiers().getDefMod(), "Equipment defence modifier should have been set");
assertEquals(4, e.getEquipmentType().getModifiers().getDefMod(), "Equipment defence modifier should have been set");
}
@Test
void setMagicDefModOnCreation() {
var e = defaultBodyArmour();
assertEquals(1, e.getEquipmentType().getModifiers().getMagicDefMod(), "Equipment magic defence modifier should have been set");
assertEquals(16, e.getEquipmentType().getModifiers().getMagicDefMod(), "Equipment magic defence modifier should have been set");
}
}

View File

@ -1,5 +1,6 @@
import Inventory.Inventory;
import Item.BasicItem;
import Item.ItemStack;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@ -9,9 +10,54 @@ public class InventoryTest {
@Test
void can_add_item_to_inventory() {
var inventory = new Inventory();
inventory.addItem(new BasicItem("iron_sword", "Iron Sword"));
var item = new BasicItem("iron_sword", "Iron Sword", 5);
inventory.addItem(new ItemStack(item, 1));
assertThat(inventory.getItems(), hasItem(
hasProperty("item",
hasProperty("id", equalTo("iron_sword"))
)
));
}
@Test
void can_add_quantity_to_inventory() {
var inventory = new Inventory();
var item = new BasicItem("iron_sword", "Iron Sword", 5);
var stack = new ItemStack(item, 5);
inventory.addItem(stack);
assertThat(inventory.getItems(), hasItem(
allOf(
hasProperty("item",
hasProperty("id", equalTo("iron_sword"))),
hasProperty("quantity", equalTo(5))
)
));
}
@Test
void item_can_not_be_added_if_above_weight_limit() {
var inventory = new Inventory(5);
var item = new BasicItem("iron_sword", "Iron Sword", 10);
var stack = new ItemStack(item, 1);
inventory.addItem(stack);
assertThat(inventory.getItems().size(), is(0));
}
@Test
void stack_can_be_added_up_to_capacity() {
var inventory = new Inventory(5);
var item = new BasicItem("sand_grain", "Sand Grain", 1);
var stack = new ItemStack(item, 8);
inventory.addItem(stack);
assertThat(inventory.getItems(), hasItem(allOf(
hasProperty("item", (
hasProperty("id", equalTo("sand_grain"))
)),
hasProperty("quantity", equalTo(5)))
));
}
}

View File

@ -2,10 +2,8 @@ import Shared.LootTable;
import Shared.RandomProvider;
import org.junit.jupiter.api.Test;
import java.util.Random;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
@ -19,6 +17,12 @@ public class LootTableTest {
return lootTable;
}
@Test
void instantiates_as_empty() {
LootTable<String> lootTable = new LootTable<>();
assertThat(lootTable.getEntries().size(), is(0));
}
@Test
void returns_an_item_was_added() {
LootTable<String> loot = defaultLootTable();
@ -33,7 +37,10 @@ public class LootTableTest {
LootTable<String> loot = new LootTable<>(mockRandomProvider);
loot.addEntry("Stone", 90);
loot.addEntry("Iron", 10);
String result = loot.roll();
assertThat(result, equalTo("Iron"));
}
}

View File

@ -7,7 +7,9 @@ import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class MinerTest {
private Player defaultPlayer() {return new Player("John"); }
@ -41,21 +43,27 @@ public class MinerTest {
}
@Test
void dig_in_coast_use_coast_loot() {
RandomProvider random = bound -> 9;
RandomProvider random = mock(RandomProvider.class);
when(random.nextInt(anyInt())).thenReturn(9);
var job = new Miner(defaultPlayer());
Biome.COAST.getLootTable().setRandomProvider(random);
job.dig(Biome.COAST);
assertThat(job.getActor().getInventory().getItems(), hasItem(
hasProperty("id", equalTo("sand"))));
hasProperty("item", hasProperty("id", equalTo("sand")))));
}
@Test
void dig_in_mountain_use_mountain_loot() {
RandomProvider random = bound -> 15;
RandomProvider random = mock(RandomProvider.class);
when(random.nextInt(anyInt())).thenReturn(15);
var job = new Miner(defaultPlayer());
Biome.MOUNTAIN.getLootTable().setRandomProvider(random);
job.dig(Biome.MOUNTAIN);
assertThat(job.getActor().getInventory().getItems(), hasItem( hasProperty("id", equalTo("iron"))));
assertThat(job.getActor().getInventory().getItems(), hasItem(
hasProperty("item",
hasProperty("id", equalTo("iron")))
)
);
}
}

View File

@ -78,7 +78,7 @@ class PlayerTest {
p.learnJob(new Miner(p));
var mockAction = mock(DigAction.class);
p.performAction(mockAction);
verify(mockAction, times(1)).execute(any());
verify(mockAction, times(1)).execute(p);
}
@Test