Jump to content

Zethariel

Members
  • Posts

    74
  • Joined

  • Last visited

Everything posted by Zethariel

  1. Hello, I am taking my first steps with 1.14 modding, and have encountered a most curious error. I want to make my own crafting table, so as a start I copied CraftingTableBlock and registered it. The item show up properly, can be retrieved from creative intentory and placed. But upon right clicking, the GUI opens up and then immediatelly closes. This does not happen for the standard workbench. I've tried making sense of what could be the reason, but turned up empty after some time. Can someone guide me on which part could be wrong? CraftingTableBlock.java package com.gmail.zethariel.FoxTech.block; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.container.INamedContainerProvider; import net.minecraft.inventory.container.SimpleNamedContainerProvider; import net.minecraft.inventory.container.WorkbenchContainer; import net.minecraft.stats.Stats; import net.minecraft.util.Hand; import net.minecraft.util.IWorldPosCallable; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.world.World; public class CraftingTableBlock extends Block { private static final ITextComponent field_220271_a = new TranslationTextComponent("container.crafting"); public CraftingTableBlock(Block.Properties properties) { super(properties); } @Override public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { player.openContainer(state.getContainer(worldIn, pos)); player.addStat(Stats.INTERACT_WITH_CRAFTING_TABLE); return true; } public INamedContainerProvider getContainer(BlockState state, World worldIn, BlockPos pos) { return new SimpleNamedContainerProvider((p_220270_2_, p_220270_3_, p_220270_4_) -> { return new WorkbenchContainer(p_220270_2_, p_220270_3_, IWorldPosCallable.of(worldIn, pos)); }, field_220271_a); } } ItemAndBlockRegister.java package com.gmail.zethariel.FoxTech; import com.gmail.zethariel.FoxTech.block.CraftingTableBlock; import com.gmail.zethariel.FoxTech.item.FoxTechItemGroup; import net.minecraft.block.Block; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.registries.ObjectHolder; @Mod.EventBusSubscriber(modid = FoxTechMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) @ObjectHolder(FoxTechMod.MOD_ID) public class ItemAndBlockRegister { public static final Item flour = null; public static final Block mixing_bowl = null; /** * The actual event handler that registers the custom items. * * @param event The event this event handler handles */ @SubscribeEvent public static void registerItems(RegistryEvent.Register<Item> event) { //create group //In here you pass in all item instances you want to register. //Make sure you always set the registry name. event.getRegistry().registerAll( new Item(new Item.Properties().group(FoxTechItemGroup.foxTechItemGroup)).setRegistryName(FoxTechMod.MOD_ID, "flour"), new BlockItem(mixing_bowl, new Item.Properties().group(FoxTechItemGroup.foxTechItemGroup)).setRegistryName(mixing_bowl.getRegistryName()) ); } /** * The actual event handler that registers the custom blocks. * * @param event The event this event handler handles */ @SubscribeEvent public static void registerBlocks(RegistryEvent.Register<Block> event) { //In here you pass in all block instances you want to register. //Make sure you always set the registry name. event.getRegistry().registerAll( new CraftingTableBlock(Block.Properties.create(Material.GLASS).hardnessAndResistance(0.3F).sound(SoundType.GLASS)).setRegistryName(FoxTechMod.MOD_ID, "mixing_bowl") ); } } Thanks in advance!
  2. Okay, thanks. Seems there is no way around it - shame, since it means more classes to maintain. Thanks for the answers guys!
  3. I just see it as the most optimal way out, without re-creating already implemented frameworks. Is there a more common way to do it correctly? Also, for Reflection to work, I'd need the obfuscated names of the fields. Any idea how to get them?
  4. The point is missed again. What if some other mod registers a particle in the ParticleManager that is not part of the Enum? How will I reliably know it has been registered and what ID it has? This is my problem. Unless I can solve it, I'll have to copy-paste the relevant parts of RenderGlobal into a separate class, which isn't ideal...
  5. Actually, you can register them and pass the ID of the registered particle. Also using addEffect is bad practice, as it bypasses the RenderGlobal spawnParticle method (which is what I'll be using) that checks the user's particle settings. The only problem I'm seeing is that there are no checks made if the ID I'm registering is already taken or not. The GlobalRender has a spawnParticle method that takes in an ID, calls that ID's factory if it is allowed to spawn (according to player particle settings) and renders it. I want to use that framework instead of re-inventing the wheel.
  6. Hello, Quick question - is there a good way to register a particle to use the vanilla ParticleManager system? What I mean is, is there a way to safely determine an ID that is "free" (not taken by vanilla particle and not taken by any other custom mod particle) ? The Map with the particles is private and there is no way to access it...
  7. I don't think we understood each other. It's one float per packet, and there can be many per second, hence my estimate of 5 per player (5 active toggle effects). This is a dedicated packet that does what you say - only sends the value when it changes. The partialticks render won't do anything against latency in packet arrival - when the client thinks it has 90 mana, the server might in fact have 89, and there will be a flicker back to the original value. That is what I meant - discrepancy between client and server values due to latency
  8. Hello, This is not strictly a technical question, so I hope it's okay. Currently I have a magic system that supports toggled spells, eg. ones that periodically substract mana. The way it works now is that each second I send out a packet to every player with their current mana value (authoritative server). This means that if someone activates a spell right before this mana synch happens, they'll be taxed for it, which should occur only after a second of the spell being active. Ideally, I'd like to have each spell have it's own recurring task (the system for that is already implemented in my solution), so that the player's mana is being changed at the correct times - that would mean sending potentially a lot of packets with many spells activated at different times. It may be just in my head, but it doesn't seem to scale well. Sending ~5 floats per second per player just looks like traffic waste. One idea I had was to simulate the mana drain on the client and only send synchronization packets on spell cast or every second or so. I'm not hot on it because the clash of synch vs local player values would make the mana bar flicker a lot between values, depending on latency. Has anyone done something similar in the past and could spare some advice? Thanks!
  9. Hi, I'm trying to obtain the cyan color on the string "Cost". No matter how I try, it gets nowhere near cyan. Something I'm doing wrong? Image attached According to gimp color samping, the HTML value is correct at (153, 235, 255) while the minecraft one is a lot darker (61, 94, 102), which is nowhere near the values I used... Is this a minecraft OpenGL thing, or am I messing up the formatting something fierce? Thanks, Wing
  10. Can the predicate/overrides be texture exclusive, or must they be done only via models, like the compass is? I was thinking along the lines of: { "forge_marker": 1, "defaults": { "model": "ponypowers:item/generated" }, "variants": { "spell_type": { "0": { "textures": {"layer0": "ponypowers:items/itemspell0"}, "overrides": [ {"predicate": {"state": 0}, "texture": "ponypowers:items/itemspell00"}, {"predicate": {"state": 1}, "texture": "ponypowers:items/itemspell00"} ] }, "1": { "textures": {"layer0": "ponypowers:items/itemspell1"}, "overrides": [ {"predicate": {"state": 0}, "texture": "ponypowers:items/itemspell10"}, {"predicate": {"state": 1, "texture": "ponypowers:items/itemspell11} ] }, } } }
  11. I attempted doing what you suggested, but failed. Maybe I'm missing something... registerItems() is called in pre-init, while registerItemModels() in init of the client public final class PonyPowersItemManager { public static Item itemSpell; public static void registerItems(){ itemSpell = new ItemSpell().setRegistryName(PonyPowers.MODID, "itemspell"); registerItem(itemSpell); } public static void registerItemModels(){ //Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(itemSpell,0,new ModelResourceLocation(itemSpell.getRegistryName().toString(), "inventory")); registerItemModel(itemSpell, 0); registerItemModel(itemSpell, 1); } private static void registerItemModel(Item item, int variantID) { ModelLoader.setCustomModelResourceLocation(item, variantID, new ModelResourceLocation(item.getRegistryName().toString(), "spell_type="+variantID)); } private static void registerItem(Item i){ GameRegistry.register(i.setUnlocalizedName(i.getRegistryName().toString())); } } in assets/ponypowers/models/block/item/generated.json { "__comment": "Allows blockstates files to use basic item models", "parent": "minecraft:item/generated" } in assets/ponypowers/blockstates/itemspell.json { "forge_marker": 1, "defaults": { "model": "ponypowers:item/generated" }, "variants": { "spell_type": { "0": {"textures": {"layer0": "ponypowers:items/itemspell0"} }, "1": {"textures": {"layer0": "ponypowers:items/itemspell1"} } } } } And the textures are there
  12. Just for the record, I solved my problem, but it's not something I'm that much proud of. I did this clientside-only, taking into consideration that the server has no clue what's happening on the hotbar and is only fed raw information about the currently held item. What I did was capture the hotbar press, check the item in the slot, if it's my special item, UNPRESS the hotbar key (via isPressed, which god knows why is the only function that actually is capable of doing so) and do whatever the item is supposed to. This prevents the flickering I had, the items don't swap out and it's perfect. The downside, as Draco18s mentioned, is that tampering with the code will break this specific functionality... Which is the user's problem, since the item doesn't do anything much. Code for interested people: public class ClientEvents { int lastItemSlot = -1; boolean[] lastHotbarKeyState; private void handlePlayerSwitchingItems(EntityPlayerSP player, int destinationSlot, boolean castSpell, KeyBinding hotbar){ ItemStack stack = player.inventory.getStackInSlot(destinationSlot); Item item = stack.getItem(); //if this is a magic spell, we will need to activate the spell and put the player back in the slot he was if (item == PonyPowersItemManager.itemTestSpell){ if (castSpell) ((ItemTestSpell)item).onSelectedFromHotbar(stack); player.inventory.currentItem = lastItemSlot; PonyLogger.info("forcing change to "+lastItemSlot); //have to use this f**** function to actually unpress something... hotbar.isPressed(); } else //if this wasn't the spell, allow for the change; lastItemSlot = destinationSlot; } @SideOnly(Side.CLIENT) @SubscribeEvent public void onTestKeyPress(KeyInputEvent event){ EntityPlayerSP player = (EntityPlayerSP) Minecraft.getMinecraft().player; if (player != null){ KeyBinding[] hotbar = Minecraft.getMinecraft().gameSettings.keyBindsHotbar; //lazy creation if (lastHotbarKeyState == null){ lastHotbarKeyState = new boolean[hotbar.length]; } if (lastItemSlot == -1){ lastItemSlot = player.inventory.currentItem; } for (int i = 0; i < 9; ++i) { //if this button is pressed... if (hotbar[i].isKeyDown()) { //...check if it is the first press or is this a continuous press... //...if first press, cast spell and go back to last item.... if (!lastHotbarKeyState[i]) handlePlayerSwitchingItems(player, i, true, hotbar[i]); else{ //...if not first press, don't cast spell and go to last item... handlePlayerSwitchingItems(player, i, false, hotbar[i]); } lastHotbarKeyState[i] = true; } else{ //...if it is not pressed, reset it's state lastHotbarKeyState[i] = false; } } } } }
  13. Yes, I'll agree with both things, and I'm trying to have that in mind - with my current conundrum, I just don't see it feasible to be able to control it server-side, save for sending packets with button clicks to the server, which would probably clog it if someone was stupid enough to faceroll the keyboard.
  14. The server takes the client's position at face value - that's why we have a lot of fly cheat mods. And I think the same happens, to my great dismay, with hotbars - the server only receives which item slot if selected instead of the keyboard input and act according to that. Or am I wrong? It SHOULD work so that I could check server-side what buttons were pressed so that I can work with them server-side. Scenario I'm getting at: Player has currently my special item selected as the one he is wielding in main hand. He presses the hotbar key for the special item. What I want to happen is for the press to register and do something - in this case, I can't rely on checking the itemslot, only raw information about the button press can help me. This is even more relevant if some of the actions in my mod swap around the player's currently equipped item - I need to distinguish my mod changing the slot from a player's input. Is what I'm trying even feasible, or should I look into a different method?
  15. Isn't that the point of modding though, with how the events are exposed? By my version of events, I meant the changed state of the hotbar - the client knows best what it wanted to click, and I wanted to influence that before it got sent to the server.
  16. I was attempting to persuade the client to send to the server my version of events, but I guess that failed.
  17. Okay, so it's deffinetly the issue with the server getting the information then? If so, you're right, I'll change to the update in the item...
  18. Fair point. But does the place at which I set my rules to changing the hotbar behaviour make a difference? Plus, the client ticket has the potential to trigger the revert of hotbar selection before the item update, yes?
  19. Hello, I've been trying to make an item that, when equipped, runs a function and goes back to the last equipped item. To do that, I check for the hotbar hotkeys being pressed and act accordingly. The problem begins when the hotbar key is pressed down. After a flicker or two the item that wasn't supposed to be equipped in the main hand is, despite the local EntityPlayerSP telling me that the currently equipped slot is different from the displayed one. After that even, single presses have a 50% chance of fixing the issue. Is this because the item gets set server side and feeds the player what he should have, or is there a race condition I'm not seeing somewhere? int lastItemSlot = -1; boolean[] lastHotbarKeyState; @SideOnly(Side.CLIENT) @SubscribeEvent public void handlePlayerSwitchingItemsToMagic(ClientTickEvent event){ //only do this at the end of tick to set the proper item we are selecting EntityPlayerSP player = (EntityPlayerSP) Minecraft.getMinecraft().player; if ((event.side == Side.CLIENT) && (event.phase == Phase.START) && (player != null)){ KeyBinding[] hotbar = Minecraft.getMinecraft().gameSettings.keyBindsHotbar; PonyLogger.info(player.inventory.currentItem+""); //lazy creation if (lastHotbarKeyState == null){ lastHotbarKeyState = new boolean[hotbar.length]; } if (lastItemSlot == -1){ lastItemSlot = player.inventory.currentItem; } for (int i = 0; i < 9; ++i) { //if this button is pressed... if (hotbar[i].isKeyDown()) { //...check if it is the first press or is this a continuous press... //...if first press, cast spell and go back to last item.... if (!lastHotbarKeyState[i]) handlePlayerSwitchingItems(player, i, true); else{ //...if not first press, don't cast spell and go to last item... handlePlayerSwitchingItems(player, i, false); } lastHotbarKeyState[i] = true; } else{ //...if it is not pressed, reset it's state lastHotbarKeyState[i] = false; } } } } private void handlePlayerSwitchingItems(EntityPlayerSP player, int destinationSlot, boolean castSpell){ ItemStack stack = player.inventory.getStackInSlot(destinationSlot); Item item = stack.getItem(); //if this is a magic spell, we will need to activate the spell and put the player back in the slot he was if (item == PonyPowersItemManager.itemTestSpell){ if (castSpell) ((ItemTestSpell)item).onSelectedFromHotbar(stack); player.inventory.currentItem = lastItemSlot; PonyLogger.info("forcing change to "+lastItemSlot); } else //if this wasn't the spell, allow for the change; lastItemSlot = destinationSlot; } The reason for the event being the ClientTickEvent instead of the PlayerTick variant is that I was experimenting with this to see where the issue could be. If something is unclear, please let me know, and thanks for your time.
  20. Just one fast follow up question If I did it like this, would it be extendable by other mods? As in, could I easily add more subitems with a separate json file that uses the mod I'm making now as an API/library?
  21. Okay, thanks for your time and the example!
  22. So there is no way to purely by code register multiple textures for a single item with metadata-dependent variations? Still need the json file one way or another, and maintain the register + .png + blockstate.json update?
  23. Hello, Simple question, is there any way to simplify the loading of textures to items with variants? I have one item that has dozens of variants, and all I really need is for each variant to have a separate texture - I don't want to have to create a json file for each of them, as it would virtually be just a copy paste of the same, save for changing the ending of the texture name to a different number. There is no model to speak of, just textures that need to be displayed in the inventory screen. Any guidance would be appreciated.
×
×
  • Create New...

Important Information

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