Jump to content

Corey

Members
  • Posts

    59
  • Joined

  • Last visited

Everything posted by Corey

  1. I'm interested, depending on the size of the codebase. Send me a PM when you have a chance.
  2. Looks like you have too many mods registering biomes (I believe 1.12 only supports up to 256)
  3. You can see a list of tasks you can run by running `gradlew tasks`. All you have to do to get started is run `gradlew genIntelliJ runs` and import it into IntelliJ. Eclipse is similar.
  4. Don't use variants. Register one block for each colour.
  5. Container.slotChangedCraftingGrid has been updated to use Forge's overloaded RecipeManager.getRecipe, which accepts a RecipeType, and it is restricted to VanillaRecipeTypes.CRAFTING. This seems to mean that the only way to craft non-vanilla shaped/shapeless recipes in the inventory crafting grid or the crafting table is to replace those containers with custom ones which override slotChangedCraftingGrid. Fortunately for me, I'm already wrapping that container for other reasons, but this definitely doesn't seem ideal... Edit: I've implemented it in the way I described above, and it works, but it's not a good solution.
  6. I'm using quite a few custom recipe types, and after updating from Forge 107 to 191, none of them seem to be working. The way I'm registering them hasn't changed. I took a quick look through the Forge commits since then (and follow Forge development pretty closely anyway) and I didn't see anything that seemed related. Has something changed? Note: I added logging, and the recipes get loaded and deserialized fine, but the matches method is never called when I try to craft things. IRecipe/Serializer: package lordmonoxide.gradient.recipes; import com.google.gson.JsonObject; import lordmonoxide.gradient.progress.Age; import lordmonoxide.gradient.utils.AgeUtils; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemTool; import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.IRecipeSerializer; import net.minecraft.item.crafting.Ingredient; import net.minecraft.item.crafting.RecipeSerializers; import net.minecraft.item.crafting.ShapelessRecipe; import net.minecraft.network.PacketBuffer; import net.minecraft.util.JsonUtils; import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.crafting.RecipeType; import net.minecraftforge.event.ForgeEventFactory; import java.util.Random; public class AgeGatedShapelessToolRecipe implements IRecipe { private static final Random rand = new Random(); private final ShapelessRecipe recipe; public final Age age; public AgeGatedShapelessToolRecipe(final ShapelessRecipe recipe, final Age age) { this.recipe = recipe; this.age = age; } @Override public boolean matches(final IInventory inv, final World world) { return AgeUtils.playerMeetsAgeRequirement((InventoryCrafting)inv, this.age) && this.recipe.matches(inv, world); } @Override public ItemStack getCraftingResult(final IInventory inv) { return this.recipe.getCraftingResult(inv); } @Override public boolean canFit(final int width, final int height) { return this.recipe.canFit(width, height); } @Override public ItemStack getRecipeOutput() { return this.recipe.getRecipeOutput(); } @Override public NonNullList<ItemStack> getRemainingItems(final IInventory inv) { final NonNullList<ItemStack> remaining = IRecipe.super.getRemainingItems(inv); for(int i = 0; i < remaining.size(); ++i) { final ItemStack stack = inv.getStackInSlot(i); if(stack.getItem() instanceof ItemTool) { stack.attemptDamageItem(1, rand, null); if(stack.isDamageable() && stack.getDamage() > stack.getMaxDamage()) { ForgeEventFactory.onPlayerDestroyItem(ForgeHooks.getCraftingPlayer(), stack, null); remaining.set(i, ItemStack.EMPTY); } else { remaining.set(i, stack.copy()); } } } return remaining; } @Override public NonNullList<Ingredient> getIngredients() { return this.recipe.getIngredients(); } @Override public boolean isDynamic() { return this.recipe.isDynamic(); } @Override public String getGroup() { return this.recipe.getGroup(); } @Override public ResourceLocation getId() { return this.recipe.getId(); } @Override public IRecipeSerializer<?> getSerializer() { return GradientRecipeSerializers.SHAPELESS; } @Override public RecipeType<? extends IRecipe> getType() { return GradientRecipeTypes.SHAPELESS; } public static final class Serializer implements IRecipeSerializer<AgeGatedShapelessToolRecipe> { @Override public AgeGatedShapelessToolRecipe read(final ResourceLocation recipeId, final JsonObject json) { final ShapelessRecipe recipe = RecipeSerializers.CRAFTING_SHAPELESS.read(recipeId, json); final Age age = Age.get(JsonUtils.getInt(json, "age", 1)); return new AgeGatedShapelessToolRecipe(recipe, age); } @Override public AgeGatedShapelessToolRecipe read(final ResourceLocation recipeId, final PacketBuffer buffer) { final ShapelessRecipe recipe = RecipeSerializers.CRAFTING_SHAPELESS.read(recipeId, buffer); final Age age = Age.get(buffer.readVarInt()); return new AgeGatedShapelessToolRecipe(recipe, age); } @Override public void write(final PacketBuffer buffer, final AgeGatedShapelessToolRecipe recipe) { RecipeSerializers.CRAFTING_SHAPELESS.write(buffer, recipe.recipe); buffer.writeVarInt(recipe.age.value()); } @Override public ResourceLocation getName() { return GradientRecipeTypes.SHAPELESS.getId(); } } } Type registration: package lordmonoxide.gradient.recipes; import lordmonoxide.gradient.GradientMod; import net.minecraftforge.common.crafting.RecipeType; public final class GradientRecipeTypes { private GradientRecipeTypes() { } public static final RecipeType<AgeGatedShapedToolRecipe> SHAPED = RecipeType.get(GradientMod.resource("shaped"), AgeGatedShapedToolRecipe.class); public static final RecipeType<AgeGatedShapelessToolRecipe> SHAPELESS = RecipeType.get(GradientMod.resource("shapeless"), AgeGatedShapelessToolRecipe.class); public static final RecipeType<DryingRecipe> DRYING = RecipeType.get(GradientMod.resource("drying"), DryingRecipe.class); public static final RecipeType<FirePitRecipe> FIREPIT = RecipeType.get(GradientMod.resource("firepit"), FirePitRecipe.class); public static final RecipeType<FuelRecipe> FUEL = RecipeType.get(GradientMod.resource("fuel"), FuelRecipe.class); public static final RecipeType<GrindingRecipe> GRINDING = RecipeType.get(GradientMod.resource("grinding"), GrindingRecipe.class); public static final RecipeType<HardeningRecipe> HARDENING = RecipeType.get(GradientMod.resource("hardening"), HardeningRecipe.class); public static final RecipeType<MixingRecipe> MIXING = RecipeType.get(GradientMod.resource("mixing"), MixingRecipe.class); } Serializer registration package lordmonoxide.gradient.recipes; import net.minecraft.item.crafting.IRecipeSerializer; import net.minecraft.item.crafting.RecipeSerializers; public final class GradientRecipeSerializers { private GradientRecipeSerializers() { } public static final IRecipeSerializer<AgeGatedShapedToolRecipe> SHAPED = RecipeSerializers.register(new AgeGatedShapedToolRecipe.Serializer()); public static final IRecipeSerializer<AgeGatedShapelessToolRecipe> SHAPELESS = RecipeSerializers.register(new AgeGatedShapelessToolRecipe.Serializer()); public static final IRecipeSerializer<DryingRecipe> DRYING = RecipeSerializers.register(new DryingRecipe.Serializer()); public static final IRecipeSerializer<FirePitRecipe> FIREPIT = RecipeSerializers.register(new FirePitRecipe.Serializer()); public static final IRecipeSerializer<FuelRecipe> FUEL = RecipeSerializers.register(new FuelRecipe.Serializer()); public static final IRecipeSerializer<GrindingRecipe> GRINDING = RecipeSerializers.register(new GrindingRecipe.Serializer()); public static final IRecipeSerializer<HardeningRecipe> HARDENING = RecipeSerializers.register(new HardeningRecipe.Serializer()); public static final IRecipeSerializer<MixingRecipe> MIXING = RecipeSerializers.register(new MixingRecipe.Serializer()); } Recipe example: { "type": "gradient:shapeless", "age": 1, "result": { "item": "gradient:twine" }, "ingredients": [{ "item": "gradient:fibre" }, { "item": "gradient:fibre" }, { "item": "gradient:fibre" }, { "item": "gradient:fibre" }] }
  7. I'm having trouble figuring out how to access data from datapacks. Reading this leads me to believe that IResourceManager.getAllResourceLocations handles all relevant datapack cascading, etc., but it only seems to be giving me the contents of my assets dir. Here's the code I was using to test it: private void setupClient(final FMLClientSetupEvent event) { this.registerResourceLoader((IReloadableResourceManager)event.getMinecraftSupplier().get().getResourceManager()); } private void setupServer(final FMLDedicatedServerSetupEvent event) { this.registerResourceLoader(event.getServerSupplier().get().getResourceManager()); } private void registerResourceLoader(final IReloadableResourceManager resourceManager) { resourceManager.addReloadListener(manager -> { LOGGER.info("METALS:"); manager.getAllResourceLocations("metals", s -> true).forEach(LOGGER::info); }); } It lists files in assets/gradient-core/metals, but doesn't list files in data/gradient-core/metals. Side question, is Minecraft.getResourceManager always an instance of IReloadableResourceManager?
  8. The textures just haven't been loaded. I don't know the exact procedure here, but you'd probably need to load them in during the TextureStitchEvent.
  9. I don't see where he said he's using hardcoded recipes? Check out the conditions section of the docs here: https://mcforge.readthedocs.io/en/latest/utilities/recipes/ You can use conditions to conditionally disable json recipes.
  10. Just tried that, but no dice. Also tried with pretty much every Java 8/9/10 version and bytecode version combination possible with identical results each time.
  11. Okay, here's what I ultimately tried: Delete entire gradle cache Freshly clone project Run ./gradlew genIntellijRuns Step 3 again as per https://gist.github.com/mcenderdragon/6c7af2daf6f72b0cadf0c63169a87583 (is that what you mean when you say "Import the project twice"?) Open the project in IntelliJ Add a breakpoint in my code on a call to code in vanilla/forge Run in debug mode, trigger breakpoint, press F7 to step into vanilla/forge code The same thing happens as in my screenshot above, with the source not matching the bytecode. The source jar is attached and I can browse through it normally, but it doesn't match in debug mode.
  12. I'm having this issue when debugging. It's happening the same in both of my environments, so I'm assuming it's actually a problem with the source jar. If I remove the source jar, IntelliJ will decompile the classes and debugging works fine, but obviously I lose documentation and coherent variable names, so that's not ideal. I haven't see any other mention of this, is it a known issue?
  13. Try using breakpoints to debug and step through the code in your IDE, to find out where it's failing.
  14. You haven't shown us any errors
  15. Loader.isModLoaded("modname");
  16. It's referencing client-only classes, but still loads and functions properly on the server. Shouldn't it throw a similar exception to my first post when it tries to load those classes?
  17. I figured that was probably the case, but I have another handler that does this... shouldn't it fail too, since it's accessing the client's world in the same way? public static class Handler implements IMessageHandler<PacketUpdateHeatNeighbours, IMessage> { @Override @Nullable public IMessage onMessage(final PacketUpdateHeatNeighbours packet, final MessageContext ctx) { Minecraft.getMinecraft().addScheduledTask(() -> { final TileEntity te = Minecraft.getMinecraft().world.getTileEntity(packet.entityPos); if(!(te instanceof HeatSinker)) { return; } ((HeatSinker)te).updateSink(packet.updatePos); }); return null; } }
  18. I'm having an issue where my (client-only) packet handler is failing on the server. I've narrowed it down to the world.isBlockLoaded if statement, but I can't figure out why this is an issue or what to do about it. CHANNEL.registerMessage(PacketSyncEnergyNetwork.Handler.class, PacketSyncEnergyNetwork.class, id++, Side.CLIENT); public static class Handler implements IMessageHandler<PacketSyncEnergyNetwork, IMessage> { @Nullable @Override public IMessage onMessage(final PacketSyncEnergyNetwork message, final MessageContext ctx) { Minecraft.getMinecraft().addScheduledTask(() -> { for(final Long2FloatMap.Entry entry : message.state.entries()) { final long serialized = entry.getLongKey(); final float energy = entry.getFloatValue(); final BlockPos pos = BlockPosUtils.getBlockPosFromSerialized(serialized); final World world = Minecraft.getMinecraft().world; if(world.isBlockLoaded(pos)) { // } } }); return null; } }
  19. It's fine for me, try doing a full refresh? ctrl+shift+R in Chrome
  20. I have unit tests written for my project that I typically run through my IDE (and assumed ran automatically in my CI environment since it runs gradlew check) but it turns out running check or test isn't actually running my tests. I have a pretty standard setup - tests are located in <project root>/src/test/java/<package>/... Here's my build.gradle: buildscript { repositories { jcenter() maven { url = "http://files.minecraftforge.net/maven" } } dependencies { classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT' } } apply plugin: 'net.minecraftforge.gradle.forge' //Only edit below this line, the above code adds and enables the nessasary things for Forge to be setup. ext.configFile = file "build.properties" configFile.withReader { def prop = new Properties() prop.load(it) project.ext.config = new ConfigSlurper().parse prop } version = config.version group= "lordmonoxide.gradient" // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = "gradient" sourceCompatibility = targetCompatibility = "1.8" // Need this here so eclipse task generates correctly. compileJava { sourceCompatibility = targetCompatibility = "1.8" } minecraft { version = config.mc_version + "-" + config.forge_version runDir = "run" mappings = config.mappings_version } repositories { maven { //IC2 name = "player-ic2" url = "http://maven.ic2.player.to/" } maven { name = "BuildCraft" url = "http://www.mod-buildcraft.com/maven" } maven { // JEI name = "Progwml6 maven" url = "http://dvs1.progwml6.com/files/maven" } } dependencies { // compile against the JEI API but do not include it at runtime deobfProvided 'mezz.jei:jei_1.12.2:4.13.1.220:api' // at runtime, use the full JEI jar runtime 'mezz.jei:jei_1.12.2:4.13.1.220' testCompile "org.junit.jupiter:junit-jupiter-api:5.3.2" } processResources { // this will ensure that this task is redone when the versions change. inputs.property "version", project.version inputs.property "mcversion", project.minecraft.version // replace stuff in mcmod.info, nothing else from(sourceSets.main.resources.srcDirs) { include 'mcmod.info' // replace version and mcversion expand 'version':project.version, 'mcversion':project.minecraft.version } // copy everything else, thats not the mcmod.info from(sourceSets.main.resources.srcDirs) { exclude 'mcmod.info' } } I'm pretty unfamiliar with gradle, am I missing anything? Edit: just realised there's a gradle subforum, not sure if this belongs here or there...
  21. I scan the recipe registry for matching recipes (drying around a firepit). It's not a huge deal since I only have to scan if I find a firepit around the block, I was mostly just curious. I need a player reference so I can check if the player has the ability to do it. I'm assuming PlaceEvent only fires when players place blocks, since getPlayer is nonnull, but I'm not concerned about automation in the early game anyway.
  22. Is there a method similar to Block#neighborChanged that has a reference to the player that placed the block? I could use BlockEvent.PlaceEvent, but I have to do a fair bit of work and don't want the code to have to run every time a block is placed if I can avoid it.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.