diff --git a/src/main/java/dev/latvian/mods/kubejs/DevProperties.java b/src/main/java/dev/latvian/mods/kubejs/DevProperties.java index ab71a99bf..5e5894da2 100644 --- a/src/main/java/dev/latvian/mods/kubejs/DevProperties.java +++ b/src/main/java/dev/latvian/mods/kubejs/DevProperties.java @@ -48,7 +48,7 @@ protected void load() { logAddedRecipes = get("log_added_recipes", false); logRemovedRecipes = get("log_removed_recipes", false); logModifiedRecipes = get("log_modified_recipes", false); - logSkippedRecipes = get("log_skipped_recipes", false); + logSkippedRecipes = get("log_skipped_recipes", true); logRecipeDebug = get("log_recipe_debug", false); logSkippedTags = get("log_skipped_tags", false); logErroringRecipes = get("log_erroring_recipes", true); diff --git a/src/main/java/dev/latvian/mods/kubejs/bindings/DirectionWrapper.java b/src/main/java/dev/latvian/mods/kubejs/bindings/DirectionWrapper.java index c662bec22..709a31cd8 100644 --- a/src/main/java/dev/latvian/mods/kubejs/bindings/DirectionWrapper.java +++ b/src/main/java/dev/latvian/mods/kubejs/bindings/DirectionWrapper.java @@ -22,6 +22,8 @@ public interface DirectionWrapper { Direction WEST = Direction.WEST; Direction EAST = Direction.EAST; Direction[] VALUES = Direction.values(); + Direction[] NONE = new Direction[0]; Map ALL = Map.copyOf(Arrays.stream(VALUES).collect(Collectors.toMap(Direction::getSerializedName, Function.identity()))); + EnumSet ALL_SET = EnumSet.allOf(Direction.class); EnumSet EMPTY_SET = EnumSet.noneOf(Direction.class); } \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/block/entity/EnergyStorageAttachment.java b/src/main/java/dev/latvian/mods/kubejs/block/entity/EnergyStorageAttachment.java index eaadd5858..cc37b273b 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/entity/EnergyStorageAttachment.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/entity/EnergyStorageAttachment.java @@ -22,7 +22,7 @@ public BlockEntityAttachment create(BlockEntityAttachmentInfo info, KubeBlockEnt int rx = Math.max(0, maxReceive.orElse(0)); int tx = Math.max(0, maxExtract.orElse(0)); int auto = Math.max(0, autoOutput.orElse(0)); - return new EnergyStorageAttachment(entity, capacity, rx, tx, auto, (auto > 0 ? info.directions() : DirectionWrapper.EMPTY_SET).toArray(new Direction[0])); + return new EnergyStorageAttachment(entity, capacity, rx, tx, auto, auto > 0 ? info.directions().isEmpty() ? DirectionWrapper.VALUES : info.directions().toArray(new Direction[0]) : DirectionWrapper.NONE); } @Override @@ -49,14 +49,38 @@ public void setEnergyStored(int energy) { } public int addEnergy(int add, boolean simulate) { - int energyReceived = Mth.clamp(this.capacity - this.energy, 0, add); + int i = Mth.clamp(this.capacity - this.energy, 0, add); - if (!simulate && energyReceived > 0) { - energy += energyReceived; + if (!simulate && i > 0) { + energy += i; attachment.entity.save(); } - return energyReceived; + return i; + } + + public int removeEnergy(int remove, boolean simulate) { + int i = Math.max(energy, remove); + + if (!simulate && i > 0) { + energy -= i; + attachment.entity.save(); + } + + return i; + } + + public boolean useEnergy(int use, boolean simulate) { + if (energy >= use) { + if (!simulate) { + energy -= use; + attachment.entity.save(); + } + + return true; + } + + return false; } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/client/KubeJSErrorScreen.java b/src/main/java/dev/latvian/mods/kubejs/client/KubeJSErrorScreen.java index fd35edaf9..bfd61ff44 100644 --- a/src/main/java/dev/latvian/mods/kubejs/client/KubeJSErrorScreen.java +++ b/src/main/java/dev/latvian/mods/kubejs/client/KubeJSErrorScreen.java @@ -266,8 +266,20 @@ public boolean mouseClicked(double d, double e, int i) { } } + private String fixSource(@Nullable String source) { + if (source != null && !source.isEmpty()) { + int c = source.indexOf(':'); + + if (c >= 0) { + return source.substring(c + 1); + } + } + + return source; + } + public void open() { - var path = line.externalFile == null ? (line.sourceLines.isEmpty() || line.sourceLines.iterator().next().source().isEmpty() ? null : line.console.scriptType.path.resolve(line.sourceLines.iterator().next().source())) : line.externalFile; + var path = line.externalFile == null ? (line.sourceLines.isEmpty() || line.sourceLines.iterator().next().source().isEmpty() ? null : line.console.scriptType.path.resolve(fixSource(line.sourceLines.iterator().next().source()))) : line.externalFile; if (path != null && Files.exists(path)) { try { diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/RecipeHelper.java b/src/main/java/dev/latvian/mods/kubejs/recipe/RecipeHelper.java index 535ebf9d3..6a56ac9ed 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/RecipeHelper.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/RecipeHelper.java @@ -2,15 +2,12 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; import com.mojang.serialization.DynamicOps; import dev.latvian.mods.kubejs.script.ConsoleJS; import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.GsonHelper; import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.item.crafting.RecipeSerializer; -import net.neoforged.neoforge.common.conditions.ConditionalOps; import org.jetbrains.annotations.Nullable; public interface RecipeHelper { @@ -21,6 +18,8 @@ static RecipeHolder fromJson(DynamicOps ops, RecipeSerializer if (codec == null) { if (errors) { ConsoleJS.SERVER.error("Error parsing recipe " + id + ": Codec not found in " + serializer.getClass().getName()); + } else { + RecipeManager.LOGGER.error("Error parsing recipe " + id + ": Codec not found in " + serializer.getClass().getName()); } return null; @@ -31,6 +30,8 @@ static RecipeHolder fromJson(DynamicOps ops, RecipeSerializer if (map.isEmpty()) { if (errors) { ConsoleJS.SERVER.error("Error parsing recipe " + id + ": Couldn't convert " + json + " to a map"); + } else { + RecipeManager.LOGGER.error("Error parsing recipe " + id + ": Couldn't convert " + json + " to a map"); } return null; @@ -45,38 +46,24 @@ static RecipeHolder fromJson(DynamicOps ops, RecipeSerializer } else if (recipe.error().isPresent()) { if (errors) { ConsoleJS.SERVER.error("Error parsing recipe " + id + ": " + recipe.error().get().message()); + } else { + RecipeManager.LOGGER.error("Error parsing recipe " + id + ": " + recipe.error().get().message()); } } else { if (errors) { ConsoleJS.SERVER.error("Error parsing recipe " + id + ": Unknown"); + } else { + RecipeManager.LOGGER.error("Error parsing recipe " + id + ": Unknown"); } } } catch (Exception e) { if (errors) { ConsoleJS.SERVER.error("Error parsing recipe " + id + " from " + map.get(), e, RecipesKubeEvent.CREATE_RECIPE_SKIP_ERROR); + } else { + RecipeManager.LOGGER.error("Error parsing recipe " + id + " from " + map.get(), e); } } return null; } - - static DataResult validate(DynamicOps ops, JsonElement jsonElement) { - if (!jsonElement.isJsonObject()) { - return DataResult.error(() -> "not a json object: " + jsonElement); - } - - var json = GsonHelper.convertToJsonObject(jsonElement, "top element"); - - if (!json.has("type")) { - return DataResult.error(() -> "missing type"); - } - - var codec = ConditionalOps.createConditionalCodec(Codec.unit(json)); - - return codec.parse(ops, json) - .mapError(str -> "error while parsing conditions: " + str) - .flatMap(optional -> optional - .map(DataResult::success) - .orElseGet(() -> DataResult.error(() -> "conditions not met"))); - } } diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/RecipesKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/RecipesKubeEvent.java index 9f713993c..ee617e57a 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/RecipesKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/RecipesKubeEvent.java @@ -4,6 +4,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; +import com.mojang.serialization.Codec; import dev.latvian.mods.kubejs.CommonProperties; import dev.latvian.mods.kubejs.DevProperties; import dev.latvian.mods.kubejs.bindings.event.ServerEvents; @@ -47,6 +48,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.item.crafting.RecipeSerializer; import net.neoforged.neoforge.common.conditions.ConditionalOps; import org.jetbrains.annotations.Nullable; @@ -240,30 +242,75 @@ public void post(RecipeManagerKJS recipeManager, Map { try { Files.write(logFile, List.of()); @@ -246,10 +247,7 @@ private ConsoleLine log(LogType type, SourceLine sourceLine, @Nullable Throwable if (writeToFile) { writeToFile(type, line.timestamp, line.getText()); - - if (wsBroadcaster != null) { - KubeJSWeb.broadcastEvent(wsBroadcaster, type.id, "", line); - } + KubeJSWeb.broadcastEvent(wsBroadcaster, type.id, "", line); } return line; diff --git a/src/main/java/dev/latvian/mods/kubejs/script/ConsoleLine.java b/src/main/java/dev/latvian/mods/kubejs/script/ConsoleLine.java index fc75249fb..325c400e8 100644 --- a/src/main/java/dev/latvian/mods/kubejs/script/ConsoleLine.java +++ b/src/main/java/dev/latvian/mods/kubejs/script/ConsoleLine.java @@ -96,7 +96,7 @@ public ConsoleLine withSourceLine(String source, int line) { line = 0; } - return source.isEmpty() && line == 0 ? this : withSourceLine(new SourceLine(source, line)); + return source.isEmpty() && line == 0 ? this : withSourceLine(SourceLine.of(source, line)); } public ConsoleLine withSourceLine(SourceLine sourceLine) { @@ -119,7 +119,7 @@ public ConsoleLine withSourceLine(SourceLine sourceLine) { public ConsoleLine withExternalFile(Path path) { externalFile = path; - sourceLines = Set.of(new SourceLine(path.getFileName().toString(), 0)); + sourceLines = Set.of(SourceLine.of(path.getFileName().toString(), 0)); return this; } diff --git a/src/main/java/dev/latvian/mods/kubejs/script/KubeJSContext.java b/src/main/java/dev/latvian/mods/kubejs/script/KubeJSContext.java index 82ad51a0a..cbfe52261 100644 --- a/src/main/java/dev/latvian/mods/kubejs/script/KubeJSContext.java +++ b/src/main/java/dev/latvian/mods/kubejs/script/KubeJSContext.java @@ -20,6 +20,7 @@ import net.minecraft.tags.TagKey; import java.lang.reflect.AccessibleObject; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -230,4 +231,8 @@ public Object classOf(Object from) { return loadJavaClass(String.valueOf(from), true).getClassObject(); } } + + public Map> getJavaClassCache() { + return javaClassCache == null ? Map.of() : Collections.unmodifiableMap(javaClassCache); + } } diff --git a/src/main/java/dev/latvian/mods/kubejs/script/SourceLine.java b/src/main/java/dev/latvian/mods/kubejs/script/SourceLine.java index 4feac4698..75de33010 100644 --- a/src/main/java/dev/latvian/mods/kubejs/script/SourceLine.java +++ b/src/main/java/dev/latvian/mods/kubejs/script/SourceLine.java @@ -11,7 +11,7 @@ public static SourceLine of(@Nullable String source, int line) { if ((source == null || source.isEmpty()) && line <= 0) { return UNKNOWN; } else { - return new SourceLine(source == null ? "" : source, Math.max(line, 0)); + return new SourceLine(source == null || source.isEmpty() ? "" : source, Math.max(line, 0)); } } @@ -26,7 +26,7 @@ public static SourceLine of(@Nullable Context cx) { int[] lineP = {0}; var source = Context.getSourcePositionFromStack(cx, lineP); - return new SourceLine(source == null ? "" : source, lineP[0]); + return SourceLine.of(source, lineP[0]); } public boolean isUnknown() { diff --git a/src/main/java/dev/latvian/mods/kubejs/web/local/KubeJSWeb.java b/src/main/java/dev/latvian/mods/kubejs/web/local/KubeJSWeb.java index 0ab1d1b0a..5015023ce 100644 --- a/src/main/java/dev/latvian/mods/kubejs/web/local/KubeJSWeb.java +++ b/src/main/java/dev/latvian/mods/kubejs/web/local/KubeJSWeb.java @@ -23,6 +23,7 @@ import net.neoforged.fml.ModList; import net.neoforged.fml.loading.FMLPaths; import net.neoforged.neoforge.server.ServerLifecycleHooks; +import org.jetbrains.annotations.Nullable; import java.nio.file.Files; import java.nio.file.Path; @@ -43,8 +44,8 @@ public class KubeJSWeb { "logs", FMLPaths.GAMEDIR.get().resolve("logs") ); - public static int broadcastEvent(WSHandler handler, String event, String requiredTag, Supplier payload) { - if (handler.sessions().isEmpty()) { + public static int broadcastEvent(@Nullable WSHandler handler, String event, String requiredTag, @Nullable Supplier payload) { + if (handler == null || handler.sessions().isEmpty()) { return 0; } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 1a2b017c7..8e8db1bcd 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -14,6 +14,7 @@ public net.minecraft.tags.TagEntry id # Lnet.minecraft.resources.ResourceLocatio public net.minecraft.tags.TagEntry required # Z public net.minecraft.tags.TagEntry tag # Z +public net.minecraft.world.item.crafting.RecipeManager LOGGER # Lorg.slf4j.Logger; public net.minecraft.world.item.crafting.ShapelessRecipe$Serializer CODEC # Lcom.mojang.serialization.MapCodec; # public net.minecraft.world.item.crafting.ShapedRecipe$Serializer CODEC Lcom.mojang.serialization.MapCodec; # public net.minecraft.world.item.crafting.ShapedRecipePattern symmetrical # Z