-
Posts
73 -
Joined
-
Last visited
Posts posted by Tieso2001
-
-
Thank you for your help, now it works
-
1 hour ago, diesieben07 said:
You need to provide it with the SRG names.
Where can I find these names?
-
3 hours ago, diesieben07 said:
You can also use access transformers instead of reflection.
I didn't know that was a thing so thank you, that looks like it is exactly what I need. I tried to use it but I can't get it to work.
Here is my accesstransformer.cfg
# Makes the fields from the FoodStats class public public net.minecraft.util.FoodStats foodLevel public net.minecraft.util.FoodStats foodSaturationLevel public net.minecraft.util.FoodStats foodExhaustionLevel public net.minecraft.util.FoodStats foodTimer public net.minecraft.util.FoodStats prevFoodLevel
And here the line I put into my build.gradle (in the minecraft section, under the line with the mappings)
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
It says that then I should refresh and it should work, but I refreshed and the fields still don't show up. Do you know how I should fix this?
-
4 hours ago, diesieben07 said:
EntityJoinWorldEvent is exactly right. You have to set the object every time. It does not magically persist.
Thank you, I got it working that my custom FoodStats is set. I have one more problem:
I created a class named CustomFoodStats that extends FoodStats. When I try to override/copy the tick() method I get lots of errors because all the fields of FoodStats are not accessible. Should I also use reflection to get and set these fields or should I do something else (because that would require a lot of reflection every tick, which I believe is not something I should be doing)?
public class CustomFoodStats extends FoodStats { private boolean foodHealthRegen = true; public CustomFoodStats() { super(); } @Override public void tick(PlayerEntity player) { /* this part would be copied from the original FoodStats (don't know if I could post that here) */ boolean flag = player.world.getGameRules().getBoolean(GameRules.NATURAL_REGENERATION) && this.foodHealthRegen; /* this part would be copied from the original FoodStats (don't know if I could post that here) */ } }
Also I have an additional question. Because I want to override the tick() method but I only change boolean flag, would that not be allowed because in essence I would then almost be entirely copying a method from the minecraft code.
-
8 hours ago, diesieben07 said:
Set PlayerEntity#foodStats using reflection.
When do I set it? Is there a PlayerEntity/Entity creation event or something similar that I should use? I only found EntityJoinWorldEvent but then it would create a new FoodStats object everytime the entity joins. How can I check if the entity hasn't been created before? Or should I use something completely different?
-
3 hours ago, diesieben07 said:
To disable generation from food (not from peaceful difficulty) you'd have to replace the Player's FoodStats object with your own version that does special handling.
Okay, I know how to make my own custom FoodStats using capabilities, but how can I disable/replace the original then?
-
-
I'm wondering if it's possible to cancel the healing and NOT to check whether the player heals and then apply damage to them.
-
I want to disable healing (from food, not from potions). I know you can do this by disabling the gamerule "naturalRegeneration" but if I'm correct, this will disable the healing for all players. Is there a way to disable the natural healing per player?
-
Thanks, I got it working.
-
I have created a custom status bar that is located right above the food bar. The problem is that when you go underwater it overlaps with the oxygenbar. I know that I can move my status bar up when underwater but I want to move the oxygen so that it is located above my custom bar. Is this possible? And if so, how do I do this. I used the RenderGameOverlayEvent.Post event to render my custom bar.
-
I have created this and it seems to work how I want it to. I can't drag of shift click item into the output slot, hoppers only insert in the input slot and when a crafting operation is completed, the result gets inserted into the output slot. I have a question about this: If I have to guess the reason that this works is that hoppers can only insert from the top or sides, and not from the bottom. That would mean that a machine that can insert items from the bottom of my block will insert the items into the output slot. Am I right about this?
If that is indeed the case then I will try to do the two version method you described. If the only way you can insert items into the output slot is by some obscure way that can only be done intentionally, then I think it is fine how it is right now.
Anyway here is the code:
Spoilerpublic class CaskTileEntity extends TileEntity implements ITickableTileEntity, INamedContainerProvider { public ItemStackHandler inputSlot; public ItemStackHandler outputSlot; private final LazyOptional<IItemHandler> inputSlotHolder = LazyOptional.of(() -> inputSlot); private final LazyOptional<IItemHandler> outputSlotHolder = LazyOptional.of(() -> outputSlot); private final LazyOptional<IItemHandler> combinedHolder = LazyOptional.of(() -> new CombinedInvWrapper(inputSlot, outputSlot)); protected FluidTank inputTank; private final LazyOptional<IFluidHandler> inputFluidHolder = LazyOptional.of(() -> inputTank); private RecipeWrapper recipeWrapper; public CaskTileEntity() { super(ModTileEntityTypes.CASK); inputSlot = new ItemStackHandler(); outputSlot = new ItemStackHandler(); inputTank = new FluidTank(1000); recipeWrapper = new RecipeWrapper(inputSlot); } @Override public CompoundNBT write(CompoundNBT compound) { compound.put("inputSlot", inputSlot.serializeNBT()); compound.put("outputSlot", outputSlot.serializeNBT()); inputTank.writeToNBT(compound); return compound; } @Override public void read(CompoundNBT compound) { super.read(compound); inputSlot.deserializeNBT(compound.getCompound("inputSlot")); outputSlot.deserializeNBT(compound.getCompound("outputSlot")); inputTank.readFromNBT(compound); } @Nonnull @Override public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) { if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { if (side == Direction.DOWN) return outputSlotHolder.cast(); return inputSlotHolder.cast(); } if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) return inputFluidHolder.cast(); return super.getCapability(cap, side); } @Override public void tick() { CaskRecipe recipe = world.getRecipeManager().getRecipe(CaskRecipe.cask, recipeWrapper, world).orElse(null); if (recipe != null && canProcess(recipe)) { inputSlot.extractItem(0,1, false); ItemStack stack = new ItemStack(recipe.getRecipeOutput().getItem(), outputSlot.getStackInSlot(0).getCount() + recipe.getRecipeOutput().getCount()); outputSlot.setStackInSlot(0, stack); inputTank.drain(recipe.getIngredientFluid().getAmount(), IFluidHandler.FluidAction.EXECUTE); markDirty(); } } private boolean canProcess(CaskRecipe recipe) { boolean itemInput = !inputSlot.extractItem(0,1, true).isEmpty() || recipe.getIngredients().isEmpty(); boolean fluidInput = inputTank.getFluid().containsFluid(recipe.getIngredientFluid()); boolean outputItemType = outputSlot.getStackInSlot(0).isEmpty() || outputSlot.getStackInSlot(0).isItemEqual(recipe.getRecipeOutput()); boolean outputItemAmount = outputSlot.getStackInSlot(0).getCount() + recipe.getRecipeOutput().getCount() <= outputSlot.getSlotLimit(0); return itemInput && fluidInput && outputItemType && outputItemAmount; } @Override public ITextComponent getDisplayName() { return new StringTextComponent(getType().getRegistryName().getPath()); } @Nullable @Override public Container createMenu(int i, PlayerInventory playerInventory, PlayerEntity playerEntity) { return new CaskContainer(i, world, pos, playerInventory, playerEntity); } }
-
1 hour ago, Draco18s said:
Have two "versions" of your handler
Why do I need two versions? Can't I just create an outputslot as an IItemHandler, cast it as an IItemHandlerModifiable when I have to insert a stack internally, and then expose the non-casted version?
-
1 hour ago, Draco18s said:
One is just a regular ItemStackHandler, which is used internally by your machine, and a non-modifiable version that you expose via getCapability.
If I understand correctly, in your case the non-modifiable version is the outputSlotWrapper, right?
-
Thanks for the information. I was hoping that it would be easier than that. Hope forge will add an easy way to do this because adding seeds to grass in 1.12.2 was really easy, using just one line of code.
-
I'm making a machine which has a result slot (same idea as the output slot of the furnace). You only take items out of the slot and not put them in. The problem is that in 1.12.2 you could use setStackInSlot on the ItemHandler to put the resulting item of a recipe into the slot (like when an item in a furnace smelts and the result appears in the output slot). In 1.14.4 I can't use setStackInSlot anymore (it won't let me), so how do I do this in 1.14.4?
I'm using isItemValid so that you can't put any items in, which is also what I used in 1.12.2 (and what the furnace uses)
Spoilerprivate IItemHandler outputInventory = new ItemStackHandler(1) { @Override protected void onContentsChanged(int slot) { markDirty(); } @Override public boolean isItemValid(int slot, @Nonnull ItemStack stack) { return false; } };
-
So I tried to make it so that my newly added seeds drop when breaking grass, just like wheat seeds. I couldn't get it working so I tried to do what @Draco18s mentioned in an earlier thread.
Here's what I did
Spoiler@Mod.EventBusSubscriber(modid = BoneAppleTea.MOD_ID) public class EventHandlers { @SubscribeEvent public static void onLootLoad(LootTableLoadEvent event) { if (event.getName().equals(new ResourceLocation("minecraft", "blocks/grass"))) { event.getTable().addPool(LootPool.builder().addEntry(TableLootEntry.builder(new ResourceLocation(BoneAppleTea.MOD_ID, "blocks/grass"))).build()); } } }
And here's the json file I created:
Spoiler{ "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:alternatives", "children": [ { "type": "minecraft:item", "conditions": [ { "condition": "minecraft:random_chance", "chance": 0.125 } ], "functions": [ { "function": "minecraft:apply_bonus", "enchantment": "minecraft:fortune", "formula": "minecraft:uniform_bonus_count", "parameters": { "bonusMultiplier": 2 } }, { "function": "minecraft:explosion_decay" } ], "name": "boneappletea:barley_seeds" } ] } ] } ] }
This is all similar to what Draco18s did in his mod:
The problem is that this adds a new pool to the already existing loot table for minecraft:grass. This makes it so that when you shear grass, the seeds from my mod can still drop. To fix this I don't want to add a new pool to the table, but modify the already existing table (the one which tells it to drop grass when using shears, and when not using shears have a chance to drop wheat seeds). If I can add an entry to this table then grass will: A: drop itself when using shears, B: sometimes drop wheat seeds, or C : sometimes drop my seeds.
I tried to add an entry to the pool but because addEntry can not be directly used (it is commented out in LootPool.class, I have no idea why) I did the following:
Spoiler@Mod.EventBusSubscriber(modid = BoneAppleTea.MOD_ID) public class EventHandlers { @SubscribeEvent public static void onLootLoad(LootTableLoadEvent event) { if (event.getName().equals(new ResourceLocation("minecraft", "blocks/grass"))) { LootPool pool = event.getTable().getPool("main"); LootPool newPool = pool.builder().addEntry(TableLootEntry.builder(new ResourceLocation(BoneAppleTea.MOD_ID, "blocks/grass"))).build(); event.getTable().addPool(newPool); event.getTable().removePool("main"); } } }
This also didn't work because now the original LootPool is not working and only the entry that I added. Grass can now only drop my seeds, even when using shears. Wheat seeds or grass itself don't drop anymore. I also tried this:
Spoiler@Mod.EventBusSubscriber(modid = BoneAppleTea.MOD_ID) public class EventHandlers { @SubscribeEvent public static void onLootLoad(LootTableLoadEvent event) { if (event.getName().equals(new ResourceLocation("minecraft", "blocks/grass"))) { LootPool pool = event.getTable().getPool("main"); event.setTable(LootTable.builder().addLootPool(pool.builder().addEntry(TableLootEntry.builder(new ResourceLocation(BoneAppleTea.MOD_ID, "blocks/grass")))).build()); } } }
The result of this was the same as the thing I tried earlier: only my seeds drop. Wheat seeds and grass itself don't drop anymore.
If someone could help me with this that would be greatly appreciated.
-
On 10/1/2019 at 8:17 PM, Animefan8888 said:
The IRecipeType is only used in code. The type in the Json refers to the registry name of the IRecipeSerializer.
As an extension. This will result in the IRecipeType being registered under minecraft:steeping which you don't want. Pass modid:steeping instead.
Finally got it working. Thank you for the help.
-
7 minutes ago, Animefan8888 said:
is not the same as
Changed it in the json to ingredient.
Also I have a question:
public static final IRecipeType<SteepingRecipe> steeping = IRecipeType.register("steeping");
If I register the type like this, what does the type in the json have to be.
"minecraft:steeping",
"boneappletea:steeping",
or just "steeping"?
-
Got everything working except for the following:
I created a recipe json named "test_steeping.json".
I put the recipe json in "resources.data.boneappletea.recipes".
In the TileEntity: RecipeManager#getRecipe only gives null and the recipe I created.
I pushed everything to github again so you can take a look again: https://github.com/Tieso2001/BoneAppleTea/tree/1.14.4-dev
Any idea what is wrong?
-
Just now, Animefan8888 said:
I'm gonna need to see the line of code and the exact error. Unless this is you saying that you've solved it.
Yes I meant that I solved it.
-
3 minutes ago, Animefan8888 said:
The second argument should be the RecipeWrapper field, and the first one should be your RecipeType.
That doesn't work because recipeWrapper gives an error saying that it is the wrong type.
Edit: Apparantly there was something wrong with the recipeType which gave an error for both arguments
-
4 minutes ago, Animefan8888 said:
You use ItemStackHandler to initialize it though. And ItemStackHandler is dun dun dun a IItemHandlerModifiable instance. Therefore cast it.
Okay, did that, that worked.
I can acces RecipeWrapper from my TileEntity, but what should I use as the second argument of RecipeManager#getRecipe.
-
6 minutes ago, Animefan8888 said:
Then use its constructor to initialize it.
But how do pass the inventory to it
recipeWrapper = new RecipeWrapper();
It needs IItemHandlerModifiable but inventory from my TileEntity is IItemHandler
[1.15.2] Setting setSprinting to false still allows sprint jumping
in Modder Support
Posted
I set use LivingEntity#setSprinting in PlayerTickEvent to false to disable sprinting for players. This works in that sprinting is not possible anymore, but there is one problem. If I hold ctrl+space+w to jump sprint forward, it is way faster than holding space+w without ctrl. The sprinting is only disabled for walking. I want to fix this because when the player has a foodLevel of less than 6, the sprinting is also disabled but here holding ctrl+space+w is much slower than when I manually disable it. Any idea how to fix this?