Jump to content

Icedice9

Members
  • Posts

    14
  • Joined

  • Last visited

Posts posted by Icedice9

  1. Let me give a few more details to make what I am doing more clear. I have another custom config text file that is read in per world, but that file can have 0 or more of the config entries. If my custom file doesn't have a config entry, the global config entry is used and changing the global value in the GUI does nothing. What I want to do is make it so changing it in the global GUI doesn't give the player a false sense that they are changing something when it doesn't make a difference.

    The point of having a world config and a global one is so regular players can set their global settings, but map makers can set specific values per world that come with the world when it is downloaded.

    2 hours ago, DavidM said:

    Can't the player just change the .cfg file anyway?

    DavidM- yes they can, but again, it doesn't change anything in game if my custom config file is filled in the world.

    1 hour ago, Cadiboo said:

    You could use your own GUI that doesn’t allow them to change it under certain conditions

    That would be neat! Do you have any tutorial suggestions? It sounds pretty complicated and I want to stick with the forge-made one if at all possible.

  2. Under certain conditions, I would like to be able to prevent players from changing the config through forge's config GUI interface. Is it possible to grey out values so that the player does not have access to them?

    Here is my mod config class:

    package oresheepmod.command;
    
    import net.minecraftforge.common.config.Config;
    import net.minecraftforge.common.config.ConfigManager;
    import net.minecraftforge.fml.client.event.ConfigChangedEvent;
    import net.minecraftforge.fml.common.Mod;
    import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
    import oresheepmod.ModOreSheep;
    
    @Config(modid = ModOreSheep.modid)
    @Config.LangKey("oresheepmod.config.title")
    public class ModConfig 
    {
    
    	@Config.Comment("Ignores the mobGriefing game rule.")
    	public static boolean IgnoreGameRuleMobGriefing = true;
    	
    	@Config.Comment("Determines if sheep can go into love mode.")
    	public static boolean CanBreed = true;
    	
    	@Config.Comment("If false, offspring are not ore sheep, but regular sheep.")
    	public static boolean OffspringAreOreSheep = true;
    	
    	@Config.Comment("If false, ore sheep can't be created with a weakness potion and diamond, but must be spawned with a spawn egg.")
    	public static boolean CanBrainwash = true;
    	
    	@Config.Comment("If false, ore sheep can't eat a different block to change their ore. They can only be changed through creative mode feeding.")
    	public static boolean CanChangeOre = true;
    	
    	@Config.Comment("If false, ore sheep eat in front of themselves before they eat down, otherwise they eat directly down.")
    	public static boolean DigStraightDown = false;
    	
    	@Config.Comment("If false, ore sheep can't eat bedrock.")
    	public static boolean Bedrock = false;
    
    	@Mod.EventBusSubscriber(modid = ModOreSheep.modid)
    	private static class EventHandler 
    	{
    		/**
    		 * Inject the new values and save to the config file when the config has been changed from the GUI.
    		 *
    		 * @param event The event
    		 */
    		@SubscribeEvent
    		public static void onConfigChanged(ConfigChangedEvent.OnConfigChangedEvent event)
    		{
    			if (event.getModID().equals(ModOreSheep.modid))
    			{
    				ConfigManager.sync(ModOreSheep.modid, Config.Type.INSTANCE);
    			}
    		}
    	}
    }

    The event handler class's onConfigChanged method looks like a good place to start, but I wanted to know first if there is any built-in/already-made solution.

    Thanks for any and all help!

  3. Here is some example code that checks if the player is holding a carrot-on-a-stick (found in the EntityPig class).

    [Mojang Code Removed]

    Notice that this code checks first if the entity is a player and then checks both main hand and off hand. 

     

    Edit: Oops, didn't realize I shouldn't be pasting Mojang code here. Totally makes sense though. For anyone seeing this later, just check the EntityPig method "canBeSteered"

  4. Turns out I do need to send a packet. I've sent packets before, but they were always server to client and involved setting static world values. Using the code I have below, how can I pass the value the client gives to the server side mob entity? Thanks so much again for the help!

     

    Updated event handler code testing for player inputs (spacebar):

    @SubscribeEvent (priority = EventPriority.LOWEST)
        @SideOnly(Side.CLIENT)
    	public void onClientTick(TickEvent.PlayerTickEvent event) throws Exception//.ClientTickEvent event) throws Exception 
    	{
    		if(KEYBIND_ARRAY == null)
    		{
    			KEYBIND_ARRAY = KeyBinding.class.getDeclaredField("KEYBIND_ARRAY");
    			KEYBIND_ARRAY.setAccessible(true);
    		}
    		
    		EntityPlayer player = event.player;
    		
    		if (player.isRiding() && player.getRidingEntity() instanceof EntityElytraPig)
    		{
    			EntityElytraPig elytraPig = (EntityElytraPig) player.getRidingEntity();
    			
    			if(elytraPig.isDragon() && elytraPig.isElytraFlying() && elytraPig.canPassengerSteer() && event.phase.equals(Phase.END))
    			{
    				Map<String, KeyBinding> binds = (Map<String, KeyBinding>) KEYBIND_ARRAY.get(null);
    		    	for (String bind : binds.keySet())
    		    	{
    					if(binds.get(bind).isKeyDown())
    					{
    						if (bind.equals("key.jump"))
    						{
    							//TODO How do I get the packet to connect to the player correctly?
    							WhenPigsFly.INSTANCE.sendTo(new ClientKeyboardPacket(90), (EntityPlayerMP) event.player);
    							elytraPig.setJumpPower(90);
    						}
    						break;
    					}
    				}
    			}
    		}
    	}

     

    Custom Client to Server Packet Code:

    package whenpigsfly.util;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    
    import io.netty.buffer.ByteBuf;
    import net.minecraft.block.Block;
    import net.minecraft.block.state.IBlockState;
    import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
    import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
    import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
    
    /**
     * Sends pig jump power to server.
     */
    public class ClientKeyboardPacket implements IMessage 
    {
    	public ClientKeyboardPacket(){}
    	
    	int jumpPower;
    	
    	public ClientKeyboardPacket(int jumpPower) 
    	{
    		this.jumpPower = jumpPower;
    	}
    
    	@Override 
    	public void toBytes(ByteBuf buf) 
    	{
    		buf.writeInt(jumpPower);
    	}
    
    	@Override 
    	public void fromBytes(ByteBuf buf)
    	{
    		this.jumpPower = buf.readInt();
    	}
    	
    	public int getJumpPower()
    	{
    		return jumpPower;
    	}
    	
    	//this is what ClientKeyboardPacket does to the server (output comes from server)
    	//The params of the IMessageHandler are <REQ, REPLY>, meaning that the first is the packet you are receiving, and the second is the packet you are returning. The returned packet can be used as a "response" from a sent packet.
    	public static class JumpPowerHandler implements IMessageHandler<ClientKeyboardPacket, IMessage> 
    	{
    		@Override
    		public IMessage onMessage(ClientKeyboardPacket message, MessageContext ctx)
    		{
    			//TODO this currently does nothing because I don't have an entity to give it to
    			int jumpPower = message.getJumpPower();
    			//response packet
    			return null;
    		}
    	}
    }

     

    As you can see with my "TODO" lines in both files, the "jumpPower" value passed to the server has nowhere to go because I don't know how to get it to the right player/mob.

  5. Yes! It's working! Thank you for your help! One last thing. Is a packet necessary, or is the following code fine? It seems to be working, but is their a cleaner way to do it?

    //detects when the player presses the spacebar
    	private static Field KEYBIND_ARRAY = null;
    
    	@SubscribeEvent (priority = EventPriority.LOWEST)
    	public void onClientTick(TickEvent.PlayerTickEvent event) throws Exception//.ClientTickEvent event) throws Exception 
    	{
    		if(KEYBIND_ARRAY == null)
    		{
    			KEYBIND_ARRAY = KeyBinding.class.getDeclaredField("KEYBIND_ARRAY");
    			KEYBIND_ARRAY.setAccessible(true);
    		}
    		if(event.phase.equals(Phase.END))
    		{
    			Map<String, KeyBinding> binds = (Map<String, KeyBinding>) KEYBIND_ARRAY.get(null);
    	    	for (String bind : binds.keySet())
    	    	{
    				if(binds.get(bind).isKeyDown())
    				{
    					EntityPlayer player = event.player;
    					if (bind.equals("key.jump") && player.isRiding() && player.getRidingEntity() instanceof EntityElytraPig)
    					{
    						EntityElytraPig elytraPig = (EntityElytraPig) player.getRidingEntity();
    						elytraPig.setJumpPower(90); //this is max horse jump power
    					}
    					break;
    				}
    			}
    		}
    	}

     

    I used the code I found here.

  6. Sweet! It's almost working! Now it jumps, but only once when "!this.onGround." How can I make it only jump when the player hits the spacebar? The player needs to set the jump power to 1.0F when they jump.

    Here is my code in the travel method of my entity class:

    public void travel(float p_191986_1_, float p_191986_2_, float p_191986_3_)
        {
            Entity entity = this.getPassengers().isEmpty() ? null : (Entity)this.getPassengers().get(0);
    
            if (this.isBeingRidden() && this.canBeSteered())
            {
                //...more code here...
    
                if (this.jumpPower > 0.0F && !this.isElytraPigJumping() && !this.onGround)
                {
                	//TODO set to make stronger/less strong
                    this.motionY = 1.0F * (double)this.jumpPower;
    
                    if (this.isPotionActive(MobEffects.JUMP_BOOST))
                    {
                        this.motionY += (double)((float)(this.getActivePotionEffect(MobEffects.JUMP_BOOST).getAmplifier() + 1) * 0.1F);
                    }
    
                    this.setElytraPigJumping(true);
    
                    if (p_191986_3_ > 0.0F)
                    {
                        float f = MathHelper.sin(this.rotationYaw * 0.017453292F);
                        float f1 = MathHelper.cos(this.rotationYaw * 0.017453292F);
                        this.motionX += (double)(-0.4F * f * this.jumpPower);
                        this.motionZ += (double)(0.4F * f1 * this.jumpPower);
                        this.playSound(SoundEvents.ENTITY_HORSE_JUMP, 0.4F, 1.0F);
                    }
                    
    		//jumpPower set to 0.0 to avoid constant jumping
                    this.jumpPower = 0.0F;
                }
    
                //...more code here..
                
                if (this.onGround)
                {
                    this.jumpPower = 0.0F;
                    this.setJumping(false);
                }
    
                //...more code here...
            }
            else
            {
                this.stepHeight = 0.5F;
                this.jumpMovementFactor = 0.02F;
                super.travel(p_191986_1_, p_191986_2_, p_191986_3_);
            }
        }

     

    Edit: The horse’s setJump code is called inside the player entity, so I don’t think I can override/call that.

  7. Hello all!

     

    I am trying to make a custom rideable mob similar to the pig called the Elytra Pig. When the player presses the space bar, I want this custom mob to jump. I've looked at the horse code for how they jump, but horses require "jump power," represented by the jump bar. I have also explored using the forge "LivingJumpEvent" which successfully detects when the player has jumped. However, when the player is riding an entity, the LivingJumpEvent does not fire. Here is my code for the event for reference:

    //called when an entity jumps
    @SubscribeEvent
    public void livingJumpEvent(LivingJumpEvent event)
    {
    	EntityLivingBase jumpingEntity = event.getEntityLiving();
      	
    	if (jumpingEntity instanceof EntityPlayer && jumpingEntity.world.isRemote)
    	{
    		//TODO
    		System.out.println("Player Jumped!"); //this correctly outputs, but only when the player is not riding my mob
    		EntityPlayer player = (EntityPlayer) jumpingEntity;
    		if (player.isRiding() && player.getRidingEntity() instanceof EntityElytraPig)
    		{
    			//TODO
    			System.out.println("Player is riding ElytraPig!");
    			EntityElytraPig elytraPig = (EntityElytraPig) player.getRidingEntity();
              
            	if (!elytraPig.isElytraPigJumping() && !elytraPig.onGround)
    			{
    				//TODO
    	    		System.out.println("Elytra pig is flying!");
    	            //change to make go higher
    	            elytraPig.motionY = 0.7F * 1.0F;
    
    				if (elytraPig.isPotionActive(MobEffects.JUMP_BOOST))
    				{
    					elytraPig.motionY += (double)((float)(elytraPig.getActivePotionEffect(MobEffects.JUMP_BOOST).getAmplifier() + 1) * 0.1F);
                    }
    
    				elytraPig.setElytraPigJumping(true);
    				elytraPig.isAirBorne = true;
    
    				if (elytraPig.moveForward > 0.0F)
                    {
    					float f = MathHelper.sin(elytraPig.rotationYaw * 0.017453292F);
    					float f1 = MathHelper.cos(elytraPig.rotationYaw * 0.017453292F);
    					elytraPig.motionX += (double)(-0.4F * f);
    					elytraPig.motionZ += (double)(0.4F * f1);
    					elytraPig.playSound(SoundEvents.ENTITY_HORSE_JUMP, 0.4F, 1.0F);
    				}
    			}
    			 
    	        elytraPig.jumpMovementFactor = elytraPig.getAIMoveSpeed() * 0.1F;
            }
        }
    }

     

    Anyone have any other ideas I can try? Mostly, I need an event that can test if the player hits the spacebar while riding my custom entity.

    Thanks for any and all help!

  8. Hello!

     

    I am working on an item, the pickle potion, that you eat to get a potion effect. A pickle potion exists for every PotionType in the game and can have multiple effects, just like regular potions. The potion data is stored and read from nbt, also just like potions, meaning that multiple effects are possible. The problem I now have is with the crafting recipes. I want to be able to combine a cucumber with any vanilla or modded potion in a crafting table and have the potion nbt data transfer to the pickles outputted, similar to how enchantments are combined in an anvil. I have created a new recipe class that extends ShapedOreRecipe and registered an instance of my recipe class using "RegistryEvent.Register<IRecipe>."

     

    My problem now is that the recipe class that I have now does not see the nbt data of ItemStacks in the crafting table. Here is some code for visualization:

     

    Custom Recipes Class:

    public class PickleShapedRecipes extends ShapedOreRecipe implements IShapedRecipe
    {
        @Deprecated
        public static final int MAX_CRAFT_GRID_WIDTH = 3;
        @Deprecated
        public static final int MAX_CRAFT_GRID_HEIGHT = 3;
    
        @Nonnull
        protected ItemStack output = ItemStack.EMPTY;
        protected NonNullList<Ingredient> input = null;
        protected int width = 0;
        protected int height = 0;
        protected boolean mirrored = true;
        protected ResourceLocation group;
    
        public PickleShapedRecipes(ResourceLocation group, Block     result, Object... recipe){ this(group, new ItemStack(result), recipe); }
        public PickleShapedRecipes(ResourceLocation group, Item      result, Object... recipe){ this(group, new ItemStack(result), recipe); }
        public PickleShapedRecipes(ResourceLocation group, @Nonnull ItemStack result, Object... recipe) { this(group, result, CraftingHelper.parseShaped(recipe)); }
        public PickleShapedRecipes(ResourceLocation group, @Nonnull ItemStack result, ShapedPrimer primer)
        {
        	super(group, result, primer);
            this.group = group;
            output = result.copy();
            //Gets the tag compound of the item in the middle of the crafting table and adds it as a potion to the output itemstack
            //THE PROBLEM IS THIS LINE: the tag compound recived is always "{Potion:"minecraft:water"}"
            PicklePotionUtils.addPotionToItemStack(output, PotionUtils.getPotionTypeFromNBT(primer.input.get(4).getMatchingStacks()[0].getTagCompound()));
            this.width = primer.width;
            this.height = primer.height;
            this.input = primer.input;
            this.mirrored = primer.mirrored;
            //TODO
            System.out.println("You have created a recipe!");
        }
    
        /**
         * Returns an Item that is the result of this recipe
         */
        @Override
        @Nonnull
        public ItemStack getCraftingResult(@Nonnull InventoryCrafting var1){ return output.copy(); }
    
        @Override
        @Nonnull
        public ItemStack getRecipeOutput(){ return output; }
    
        /**
         * Used to check if a recipe matches current crafting inventory
         */
        @Override
        public boolean matches(@Nonnull InventoryCrafting inv, @Nonnull World world)
        {
            for (int x = 0; x <= inv.getWidth() - width; x++)
            {
                for (int y = 0; y <= inv.getHeight() - height; ++y)
                {
                    if (checkMatch(inv, x, y, false))
                    {
                        return true;
                    }
    
                    if (mirrored && checkMatch(inv, x, y, true))
                    {
                        return true;
                    }
                }
            }
    
            return false;
        }
    
        /**
         * Based on {@link net.minecraft.item.crafting.ShapedRecipes#checkMatch(InventoryCrafting, int, int, boolean)}
         */
        protected boolean checkMatch(InventoryCrafting inv, int startX, int startY, boolean mirror)
        {
            for (int x = 0; x < inv.getWidth(); x++)
            {
                for (int y = 0; y < inv.getHeight(); y++)
                {
                    int subX = x - startX;
                    int subY = y - startY;
                    Ingredient target = Ingredient.EMPTY;
    
                    if (subX >= 0 && subY >= 0 && subX < width && subY < height)
                    {
                        if (mirror)
                        {
                            target = input.get(width - subX - 1 + subY * width);
                        }
                        else
                        {
                            target = input.get(subX + subY * width);
                        }
                    }
    
                    if (!target.apply(inv.getStackInRowAndColumn(x, y)))
                    {
                        return false;
                    }
                }
            }
    
            return true;
        }
    
        public PickleShapedRecipes setMirrored(boolean mirror)
        {
            mirrored = mirror;
            return this;
        }
    
        @Override
        @Nonnull
        public NonNullList<Ingredient> getIngredients()
        {
            return this.input;
        }
    
        @Deprecated //Use IShapedRecipe.getRecipeWidth
        public int getWidth()
        {
            return width;
        }
    
        @Override
        public int getRecipeWidth()
        {
            return this.getWidth();
        }
    
        @Deprecated //Use IShapedRecipe.getRecipeHeight
        public int getHeight()
        {
            return height;
        }
    
        @Override
        public int getRecipeHeight()
        {
            return this.getHeight();
        }
    
        @Override
        @Nonnull
        public String getGroup()
        {
            return this.group == null ? "" : this.group.toString();
        }
    
        /**
         * Used to determine if this recipe can fit in a grid of the given width/height
         */
        @Override
        public boolean canFit(int width, int height)
        {
            return width >= this.width && height >= this.height;
        }
    }

     

    ModRecipies class:

    public class ModRecipes 
    {
    	public static final List<IRecipe> RECIPES = new ArrayList<IRecipe>();
    	
    	public static void init()
    	{
        	RECIPES.add(new PickleShapedRecipes(new ResourceLocation("complexcrops:items"), new ItemStack(ModItems.PICKLE_POTION, 4), new Object[]{
    				" C ",
    				"CPC",
    				" C ",
    				'C', ModItems.CUCUMBER,
    				'P', Items.POTIONITEM.setContainerItem(Items.GLASS_BOTTLE) }));
    	}
    }

     

    RegistryHandler Code:

    @SubscribeEvent
    	public static void onRecipeRegister(RegistryEvent.Register<IRecipe> event)
    	{
    		IRecipe[] recipes = ModRecipes.RECIPES.toArray(new IRecipe[0]);
    		int i = 0;
    		for (IRecipe recipe : recipes)
    		{
    			++i;
    			event.getRegistry().register(recipe.setRegistryName(new ResourceLocation("complexcrops:recipe" + i)));
    
    		}
    	}

     

    As commented in my Custom Recipes class, the line that transfers the potion effect from the potion to the outputted item does not work because the nbt data tag is always "{Potion:"minecraft:water"}". This means all pickles crafted have no effects. How can I fix this?

    Thank you so much for any and all help!

×
×
  • Create New...

Important Information

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