Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,11 @@ jobs:
name: unit-test-reports-${{ github.run_id }}-${{ github.run_attempt }}
path: target/surefire-reports/
if-no-files-found: error

- name: Upload coverage report
if: ${{ !cancelled() && hashFiles('target/site/jacoco/jacoco.xml') != '' }}
uses: actions/upload-artifact@v7
with:
name: coverage-report-${{ github.run_id }}-${{ github.run_attempt }}
path: target/site/jacoco/
if-no-files-found: error
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ mvn -B --no-transfer-progress clean verify
The JUnit 5 suite covers food parsing and items, crops, husbandry, nutrition,
fishing and configuration loading, using MockBukkit and Mockito where Bukkit or
plugin APIs are involved. The Build and release workflows run the same command,
and the Build workflow uploads the Surefire reports. No coverage gate is
enforced. The tests do not replace checking kitchens, crops and livestock on a
live Paper server with the pinned integrations.
and the Build workflow uploads the Surefire reports. JaCoCo requires 100% line
coverage across all production classes, with no coverage exclusions. HTML and XML
reports are written to `target/site/jacoco/` and uploaded by the Build workflow.
The tests do not replace checking kitchens, crops and livestock on a live Paper
server with the pinned integrations.

## License

Expand Down
38 changes: 38 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@
</dependencyManagement>

<dependencies>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockbukkit.mockbukkit</groupId>
<artifactId>mockbukkit-v1.21</artifactId>
Expand Down Expand Up @@ -185,6 +191,38 @@
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.15</version>
<executions>
<execution><goals><goal>prepare-agent</goal></goals></execution>
<execution>
<id>coverage-report</id>
<phase>verify</phase>
<goals><goal>report</goal></goals>
</execution>
<execution>
<id>coverage-check</id>
<phase>verify</phase>
<goals><goal>check</goal></goals>
<configuration>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>MISSEDCOUNT</value>
<maximum>0</maximum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
Expand Down
19 changes: 8 additions & 11 deletions src/main/java/net/tfminecraft/cooking/baking/BakingTrayAging.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ private void tick() {
.getPlacedFurniture();

for (Furniture furniture : placed.values()) {
if (BakingTrayRegistry.isTray(furniture) && !furniture.isAttached()) {
BakingTrayRecipe recipe = BakingTrayRegistry.getByFurniture(furniture);
if (recipe != null && !furniture.isAttached()) {
if (visited.add(furniture.getEntityId())) {
ageTray(furniture);
ageTray(furniture, recipe);
}
}

Expand All @@ -47,22 +48,18 @@ private void tick() {

for (PlacedFurnitureSlot slot : furniture.getActiveFurnitureSlots().values()) {
Furniture nested = slot.getNested();
if (nested == null || !BakingTrayRegistry.isTray(nested)) {
BakingTrayRecipe nestedRecipe = BakingTrayRegistry.getByFurniture(nested);
if (nestedRecipe == null) {
continue;
}
if (visited.add(nested.getEntityId())) {
ageTray(nested);
ageTray(nested, nestedRecipe);
}
}
}
}

private void ageTray(Furniture tray) {
BakingTrayRecipe recipe = BakingTrayRegistry.getByFurniture(tray);
if (recipe == null) {
return;
}

private void ageTray(Furniture tray, BakingTrayRecipe recipe) {
boolean changed = false;
for (String slotId : recipe.getAllSlotIds()) {
if (!tray.hasActiveSlot(slotId)) {
Expand Down Expand Up @@ -94,7 +91,7 @@ private boolean ageSlot(PlacedSlot slot, Furniture tray) {
}

ItemStack updated = ItemUpdater.updateItem(item, foodItem, tray.getId());
if (updated == null) {
if (updated == null || updated.getType().isAir()) {
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,16 @@ private static boolean applyToSlot(Furniture tray, String slotId, int fromValue,
return false;
}
cookedTrack = new TagTrack(baseTrack);
foodItem.addOrModifyTrack(cookedTrack);
}

if (cookedTrack.getValue() != fromValue) {
return false;
}

cookedTrack.setValue(toValue);
foodItem.addOrModifyTrack(cookedTrack);
ItemStack updated = ItemUpdater.applyItemUpdate(item, foodItem, tray.getId());
if (updated == null) {
if (updated == null || updated.getType().isAir()) {
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,8 @@ private boolean handleTake(Furniture furniture, BakingTrayRecipe recipe, Player
return false;
}

PlacedSlot slot = furniture.getActiveSlot(slotId).orElse(null);
if (slot == null) {
return false;
}

PlacedSlot slot = furniture.getActiveSlot(slotId).orElseThrow();
ItemStack item = slot.getCurrentItem();
if (item == null || item.getType().isAir()) {
return false;
}

FoodItem foodItem = FoodItem.fromItem(item);
if (foodItem == null) {
Expand All @@ -173,7 +166,7 @@ private boolean handleTake(Furniture furniture, BakingTrayRecipe recipe, Player
if (WarmthUtils.isHeated(foodItem, 1)) {
WarmthUtils.applyHot(foodItem);
toGive = ItemUpdater.applyItemUpdate(item, foodItem, furniture.getId());
if (toGive == null) {
if (toGive == null || toGive.getType().isAir()) {
return false;
}
} else {
Expand Down Expand Up @@ -201,9 +194,6 @@ private boolean handleTake(Furniture furniture, BakingTrayRecipe recipe, Player
}

private static boolean matchesFillInput(BakingTrayRecipe recipe, ItemStack hand) {
if (hand == null) {
return false;
}
BakingTrayFill fill = recipe.getFill();
if (fill.getInputFood() != null) {
FoodItem foodItem = FoodItem.fromItem(hand);
Expand All @@ -219,9 +209,6 @@ private static boolean matchesFillInput(BakingTrayRecipe recipe, ItemStack hand)
}

private static boolean matchesPlaceableLoaf(BakingTrayRecipe recipe, ItemStack hand) {
if (hand == null || hand.getType().isAir()) {
return false;
}
FoodItem foodItem = FoodItem.fromItem(hand);
if (foodItem == null) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,6 @@ private static void applyTagSpec(FoodItem item, String tagsSpec) {
}

String[] kv = part.split("\\.", 2);
if (kv.length != 2) {
continue;
}

TagTrack baseTrack = TrackLoader.getByString(kv[0]);
if (baseTrack == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package net.tfminecraft.cooking.cache;

import java.util.Locale;

import net.tfminecraft.cooking.enums.Method;
import net.tfminecraft.interactiblefurniture.furniture.Furniture;

Expand Down Expand Up @@ -94,6 +96,6 @@ public static boolean isMealHolder(Furniture f) {
// Other plugins' furniture (pedestals, displays) keeps its own slot display.
public static boolean isCookingFurniture(Furniture f) {
return f.getType() != null
&& f.getType().getItemPath().toLowerCase().startsWith("ia.tfmc_cooking:");
&& f.getType().getItemPath().toLowerCase(Locale.ROOT).startsWith("ia.tfmc_cooking:");
}
}
11 changes: 6 additions & 5 deletions src/main/java/net/tfminecraft/cooking/cache/NamingConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Locale;
import java.util.Set;

public final class NamingConfig {
Expand Down Expand Up @@ -65,7 +66,7 @@ public static boolean isCategory(String bucket, String category) {
if (category == null) {
return false;
}
return getCategories(bucket).contains(category.toLowerCase());
return getCategories(bucket).contains(category.toLowerCase(Locale.ROOT));
}

public static Set<String> allCategoryBuckets() {
Expand All @@ -76,21 +77,21 @@ public static String getTagLabelDefault(String category, String trackId, String
if (category == null || trackId == null || stepId == null) {
return null;
}
Map<String, Map<String, String>> byTrack = tagLabelDefaults.get(category.toLowerCase());
Map<String, Map<String, String>> byTrack = tagLabelDefaults.get(category.toLowerCase(Locale.ROOT));
if (byTrack == null) {
return null;
}
Map<String, String> byStep = byTrack.get(trackId.toLowerCase());
Map<String, String> byStep = byTrack.get(trackId.toLowerCase(Locale.ROOT));
if (byStep == null) {
return null;
}
return byStep.get(stepId.toLowerCase());
return byStep.get(stepId.toLowerCase(Locale.ROOT));
}

public static String getOriginAdjective(String origin) {
if (origin == null) {
return null;
}
return originAdjectives.get(origin.toLowerCase());
return originAdjectives.get(origin.toLowerCase(Locale.ROOT));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ public static void initCarveState(ItemStack stack, FoodItem item) {
}

public static boolean isCarvable(FoodItem item) {
return item != null && item.hasCarveState() && item.getCarveRemaining() > 0
&& item.getCarveNextIndex() < getSequence(item).getCuts().size();
if (item == null || !item.hasCarveState() || item.getCarveRemaining() <= 0
|| item.getCarveNextIndex() < 0) return false;
CarveSequence sequence = getSequence(item);
return sequence != null && item.getCarveNextIndex() < sequence.getCuts().size();
}

public static boolean isCarvable(ItemStack stack) {
Expand Down Expand Up @@ -162,16 +164,13 @@ public static int visualCarveStage(FoodItem item, CarveSequence seq) {
}

public static ModelData getStageModelData(FoodItem item) {
FoodModel model = item.getModel();
if (model == null || model.getStates().isEmpty()) return null;
if (!item.hasCarveState() || item.getCarveRemaining() <= 0) {
FoodModel model = item.getModel();
ModelData fallback = model != null ? model.getModel(item) : null;
return fallback != null ? fallback : item.getModel().getModel(item);
return model.getModel(item);
}
String cookTag = resolveCookTag(item);
ModelData staged = item.getModel().getModelByStageAndTag(getVisualCarveStage(item), cookTag);
if (staged != null) return staged;
FoodModel model = item.getModel();
return model != null ? model.getModel(item) : null;
return model.getModelByStageAndTag(getVisualCarveStage(item), cookTag);
}

public static String resolveCookTag(FoodItem item) {
Expand Down
53 changes: 17 additions & 36 deletions src/main/java/net/tfminecraft/cooking/carve/CarveHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import net.tfminecraft.cooking.utils.ItemUpdater;

import net.tfminecraft.interactiblefurniture.furniture.Furniture;
import net.tfminecraft.interactiblefurniture.InteractibleFurniture;

import net.tfminecraft.interactiblefurniture.furniture.PlacedSlot;

Expand Down Expand Up @@ -93,50 +94,31 @@ public static boolean tryCarve(Player player, Furniture furniture, PlacedSlot sl

ItemStack reward = buildReward(player, roast, stack, cut, sequence);

if (reward == null) return false;



Location dropLoc = furniture.getLoc();

giveReward(player, dropLoc, reward);



CarvableRoastUtils.advanceAfterCarve(roast);

dropLoc.getWorld().playSound(dropLoc, Sound.BLOCK_SWEET_BERRY_BUSH_PICK_BERRIES, 1f, 1f);



if (roast.getCarveRemaining() <= 0) {
if (reward == null || reward.getType().isAir()) return false;

FoodItem remaining = new FoodItem(roast);
CarvableRoastUtils.advanceAfterCarve(remaining);
if (remaining.getCarveRemaining() <= 0) {
slot.clearModel();

furniture.removeActiveSlot(slot.getId());

return true;

} else {
var model = CarvableRoastUtils.getStageModelData(remaining);
if (model == null) return false;
ItemStack updated = ItemUpdater.applyItemUpdate(stack.clone(), remaining, furniture.getId());
if (updated == null || updated.getType().isAir()) return false;
CarvableRoastUtils.writeCarveState(updated, remaining);
slot.setCurrentItem(updated);
slot.applyDisplayData(model.getDisplayData(furniture.getId()));
}



ItemStack updated = ItemUpdater.applyItemUpdate(stack, roast, furniture.getId());

if (updated == null) return true;

CarvableRoastUtils.writeCarveState(updated, roast);

slot.setCurrentItem(updated);

slot.applyDisplayData(CarvableRoastUtils.getStageModelData(roast).getDisplayData(furniture.getId()));

Location dropLoc = furniture.getLoc();
InteractibleFurniture.getInstance().getFurnitureManager().markDirty(furniture);
giveReward(player, dropLoc, reward);
dropLoc.getWorld().playSound(dropLoc, Sound.BLOCK_SWEET_BERRY_BUSH_PICK_BERRIES, 1f, 1f);
return true;

}



private static ItemStack buildReward(Player player, FoodItem roast, ItemStack stack, CarveCut cut, CarveSequence sequence) {

if (cut.isItemCut()) {
Expand Down Expand Up @@ -220,4 +202,3 @@ public static boolean tryCarveFirstCarvableSlot(Player player, Furniture furnitu

}


Loading