Jump to content
Search In
  • More options...
Find results that contain...
Find results in...


  • Posts

  • Joined

  • Last visited


  • Gender
  • Location
    Poland, Gdynia
  • Personal Text
    Bats are adorable

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

Zethariel's Achievements

Stone Miner

Stone Miner (3/8)



  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.
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.