Jump to content

Kriptikz

Members
  • Posts

    81
  • Joined

  • Last visited

Posts posted by Kriptikz

  1. I can find tutorials for using obj models for items and blocks, but not for entities. Can you use obj models for entities?

    I'm pretty much stuck at creating the Render class for the entity.

    Here is what I have so far:

    Spoiler
    
    public class RenderSpellProjectile extends Render<EntitySpellProjectile>
    {
    	private ResourceLocation texture = new ResourceLocation(Reference.MODID, "textures/entity/spell_projectile.png");
    	private ResourceLocation obj = new ResourceLocation(Reference.MODID, "models/obj/sphere/sphere.obj");
    		
    	//private ModelBase model1;
    	private IModel model2;
    	
    	public static final RenderFactory FACTORY = new RenderFactory();
    	
    	public RenderSpellProjectile(RenderManager renderManager)
    	{
    		super(renderManager);
    		
    		//model1 = new ModelSpellProjectile();
    		
    		try
    		{
    			model2 = OBJLoader.INSTANCE.loadModel(obj);
    		} catch (Exception e)
    		{
    			System.out.println("Unable to load sphere.obj");
    		}
    	}
    
    	@Override
    	protected ResourceLocation getEntityTexture(EntitySpellProjectile entity)
    	{
    		return texture;
    	}
    	
    	@Override
    	public void doRender(EntitySpellProjectile entity, double x, double y, double z, float entityYaw, float partialTicks)
    	{
    		// Render for model1
    		/*
    		GL11.glPushMatrix();
    		bindTexture(texture);
    		GL11.glTranslated(x, y - 1.25D, z);
    		model1.render(entity, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0625F);
    		GL11.glPopMatrix();
    		*/
    
    		// Render for model2
    		
    	}
    
    	public boolean shouldRender(EntitySpellProjectile livingEntity, ICamera camera, double camX, double camY, double camZ)
    	{
    		return true;
    	}
    
    	public static class RenderFactory implements IRenderFactory<EntitySpellProjectile>
    	{
    
    		@Override
    		public Render<? super EntitySpellProjectile> createRenderFor(RenderManager manager)
    		{
    			return new RenderSpellProjectile(manager);
    		}
    
    	}
    }

     

    That should load the model, right? If so, how do I render it in doRender()?

  2. 3 minutes ago, Jay Avery said:

    It would require the mod to be installed on the server; OP wants a mod that will function when it's only installed on the client.

    Ah, I understand now, life makes sense again. I came here to help and ended up getting helped lol. Thanks guys!

  3. 13 minutes ago, diesieben07 said:

    Except they have no way to run the code on the server, because it is a client only mod.

    Oh, I see. Isn't that what proxy's are for though? So only client stuff gets ran on client and server stuff gets ran on server? I'm guessing this would require rewrite of most of the mod though?

  4. As far as I know you should still be able to send a packet from server to client, whether on dedicated server, or a combined client, by combined client I mean like what is used in Single Player.

    So for example, you take what you had in LivingDeathEvent and instead of your code you send a packet to the client. When the client gets the packet you make it run your code.

  5. 13 hours ago, Xaser said:

    I actually used the exact same tutorials, but I must have skipped over the PlayerLoggedInEvent part and forgot about it.. that what happens when you only get to work on this stuff over the weekends i guess. Thanks!

     

    Actually, if the capability is not only for players, you may consider the OnEntityJoinWorldEvent as well

    They didn't really didn't talk about that event or how to use packets exactly, had to look elsewhere for that. Good luck with your modding.

    • Like 1
  6. I'm like brand new to modding so take my info with a grain of salt. 

    I believe the storage class should only be used to read and write the nbt and as long as it's registered and attached, the provider will automatically call the read/write nbt methods of the storage class from the serializeNBT and deseralizeNBT methods . The client won't actually save and load the nbt data though, so it will probably just be default values. So in PlayerLoggedInEvent you just send a packet from the server to the client to sync the data. From here I don't know whether you handle the increase/decrease of mana only server side or both client and server side. For me I only handle the mana server side and I use PlayerTickEvent to send a packet to the client to sync the mana.

    Here is an older tutorial, but it still works:

    http://www.planetminecraft.com/blog/forge-tutorial-capability-system/

    Other useful links:

    https://mcforge.readthedocs.io/en/latest/datastorage/capabilities/

    http://jabelarminecraft.blogspot.com/p/minecraft-17x.html

    • Like 1
  7. I'm trying to create an item that allows you to take over a living entity on right click, possibly leaving the players body where it is. To leave the players body I think I just have to create a custom entity and spawn it where the player was with players data.

    How do I go about actually taking over the living entity? I think there are two possibilities:

    1. There is a relatively easy way that allows control over a living entity and moves the players camera position to the eye height of the entity, already built into Minecraft/Minecraft Forge.

    2. Despawn the living entity (or EntityLiving::setDead()) and store living entity data in player, give the player the model of the living entity that was right clicked, and set the player position to the living entities position. Then when the player wants to switch back do the opposite.

    • Like 1
  8. Solved, I had to move the finals into addScheduledTask

    This:

    
    		@Override
    		public IMessage onMessage(MessageSyncAllPlayerData message, MessageContext ctx)
    		{
    			final EntityPlayer player = MagicMastery.proxy.getEntityPlayer(ctx);
    			final IPlayerData serverData = message.getData();
    			
    			MagicMastery.proxy.getThreadListener(ctx).addScheduledTask(() ->
    			{
    				if (player != null && serverData != null)
    				{
    					IPlayerData clientData = PlayerDataProvider.getPlayerCapability(player);
    					
    					if (clientData != null && serverData != null)
    					{
    						clientData.setIsLevitating(serverData.getIsLevitating());
    						clientData.setMana(serverData.getMana());
    						clientData.setMaxMana(serverData.getMaxMana());
    						clientData.setPlayerLevel(serverData.getPlayerLevel());
    						clientData.setPlayerXp(serverData.getPlayerXp());
    						clientData.setPlayerCurrentLevelMaxXp(serverData.getPlayerCurrentLevelMaxXp());
    						clientData.setShouldPlayerGainXp(serverData.getShouldPlayerGainXp());
    						clientData.setManaRegenPerSecond(serverData.getManaRegenPerSecond());
    						clientData.setSelectedSpell(serverData.getSelectedSpell());
    						
    						for (int i = 0; i < IPlayerData.NUMBER_OF_SPELLS; i++)
    						{
    							clientData.setSpellFromId(i, serverData.getSpellFromId(i));
    						}
    					}
    				}
    			});
    			
    			re

     

    needed to be like this:

    @Override
    		public IMessage onMessage(MessageSyncAllPlayerData message, MessageContext ctx)
    		{
    			
    			MagicMastery.proxy.getThreadListener(ctx).addScheduledTask(() ->
    			{
    				final EntityPlayer player = MagicMastery.proxy.getEntityPlayer(ctx);
    				final IPlayerData serverData = message.getData();
    				
    				if (player != null && serverData != null)
    				{
    					IPlayerData clientData = PlayerDataProvider.getPlayerCapability(player);
    					
    					if (clientData != null && serverData != null)
    					{

     

  9. 26 minutes ago, diesieben07 said:

    Yeah, that's a terrible idea, don't do that.

    Feelsbadman :(  What can go wrong with it?

    This is only a problem with SinglePlayer, when connecting to a dedicated server it works fine. There just needs to be at least a 200 millisecond delay when in SinglePlayer in order for the message to work and the data to sync.

    Is there a proper way to make the game wait at least 200 ms, only when in SinglePlayer?

  10. 22 minutes ago, diesieben07 said:

    No, Thread.sleep is a terrible idea to solve a thread inconsistency. Where did you put that code?

    	@SubscribeEvent
    	public void onPlayerLogin(PlayerLoggedInEvent event) throws InterruptedException
    	{
    		if (MagicMastery.proxy instanceof CombinedClientProxy)
    		{
    			Thread.sleep(200);
    		}
    		
    		EntityPlayer player = event.player;
    		IPlayerData playerData = PlayerDataProvider.getPlayerCapability(player);
    
    		MagicMastery.network.sendTo(new MessageSyncAllPlayerData(playerData), (EntityPlayerMP) player);
    	}

     

  11. 7 hours ago, diesieben07 said:

    data cannot possibly contain a value inside fromBytes. fromBytes is called after your message class has been constructed using the no-argument constructor, you must fill the fields in this method.

    They all have default values set in my PlayerData class, shouldn't this line create the object with all the default values:

    private IPlayerData data = new PlayerData();

    Here is some of my PlayerData:

    public class PlayerData implements IPlayerData
    {
    	private int ticksStunned;
    	private boolean isStunned = false;
    	private int stunDuration = 20;
    	private boolean isLevitating = false;
    	
    	// levitation amp of 5 is hovering, <5 goes down, >5 goes up.
    	private int levitationAmp = 5;
    	
    	private float mana = 0;
    	private float maxMana = 150;
    	private int playerLevel = 1;
    	private int playerXp = 0;
    	private int playerCurrentLevelMaxXp = 100;
    	private boolean shouldPlayerGainXp = true;
    	private float manaRegenPerSecond = 0.5F;
    	private int selectedSpell = 0;

     

    Also, I got rid of the null check and the inconsistent sync was still a problem without:

    		if (MagicMastery.proxy instanceof CombinedClientProxy)
    		{
    			Thread.sleep(200);
    		}

     

    Is using Thread.sleep here ok? It should only do that in SinglePlayer as well.

  12. 19 minutes ago, Jay Avery said:

    Post your packet and handler classes. Do you use Minecraft#addScheduledTask to process the message?

    yes, I do use Minecraft#addScheduledTask

    public class MessageSyncAllPlayerData implements IMessage
    {
    	private IPlayerData data = new PlayerData();
    	
    	public MessageSyncAllPlayerData()
    	{
    	}
    	
    	public MessageSyncAllPlayerData(IPlayerData playerData)
    	{
    		this.data = playerData;
    	}
    
    	@Override
    	public void fromBytes(ByteBuf buf)
    	{
    		if (this.data != null)
    		{
    			this.data.setIsLevitating(buf.readBoolean());
    			this.data.setMana(buf.readFloat());
    			this.data.setMaxMana(buf.readFloat());
    			this.data.setPlayerLevel(buf.readInt());
    			this.data.setPlayerXp(buf.readInt());
    			this.data.setPlayerCurrentLevelMaxXp(buf.readInt());
    			this.data.setShouldPlayerGainXp(buf.readBoolean());
    			this.data.setManaRegenPerSecond(buf.readFloat());
    			this.data.setSelectedSpell(buf.readInt());
    			
    			for (int i = 0; i < IPlayerData.NUMBER_OF_SPELLS; i++)
    			{
    				readSpellArray(buf, i);			
    			}
    			
    		}
    	}
    
    	@Override
    	public void toBytes(ByteBuf buf)
    	{
    		if (this.data != null)
    		{
    			buf.writeBoolean(this.data.getIsLevitating());
    			buf.writeFloat(this.data.getMana());
    			buf.writeFloat(this.data.getMaxMana());
    			buf.writeInt(this.data.getPlayerLevel());
    			buf.writeInt(this.data.getPlayerXp());
    			buf.writeInt(this.data.getPlayerCurrentLevelMaxXp());
    			buf.writeBoolean(this.data.getShouldPlayerGainXp());
    			buf.writeFloat(this.data.getManaRegenPerSecond());
    			buf.writeInt(this.data.getSelectedSpell());
    
    			for (int i = 0; i < IPlayerData.NUMBER_OF_SPELLS; i++)
    			{
    				writeSpellArray(buf, this.data.getSpellFromId(i));				
    			}
    			
    		}
    	}
    	
    	public void setData(IPlayerData data)
    	{
    		this.data = data;
    	}
    	
    	public IPlayerData getData()
    	{
    		return this.data;
    	}
    	
    	public void writeSpellArray(ByteBuf buf, int[] array)
    	{
    		for (int i = 0; i < 4; i++)
    		{
    			buf.writeInt(array[i]);
    		}
    	}
    	
    	public void readSpellArray(ByteBuf buf,int spellId)
    	{
    		int [] array = new int[4];
    		
    		for (int i = 0; i < 4; i++)
    		{
    			array[i] = buf.readInt();
    		}
    		
    		this.data.setSpellFromId(spellId, array);
    
    	}
    	
    	public static class MessageHandler implements IMessageHandler<MessageSyncAllPlayerData, IMessage>
    	{
    
    		@Override
    		public IMessage onMessage(MessageSyncAllPlayerData message, MessageContext ctx)
    		{
    			final EntityPlayer player = MagicMastery.proxy.getEntityPlayer(ctx);
    			final IPlayerData serverData = message.getData();
    			
    			MagicMastery.proxy.getThreadListener(ctx).addScheduledTask(() ->
    			{
    				if (player != null && serverData != null)
    				{
    					IPlayerData clientData = PlayerDataProvider.getPlayerCapability(player);
    					
    					if (clientData != null && serverData != null)
    					{
    						clientData.setIsLevitating(serverData.getIsLevitating());
    						clientData.setMana(serverData.getMana());
    						clientData.setMaxMana(serverData.getMaxMana());
    						clientData.setPlayerLevel(serverData.getPlayerLevel());
    						clientData.setPlayerXp(serverData.getPlayerXp());
    						clientData.setPlayerCurrentLevelMaxXp(serverData.getPlayerCurrentLevelMaxXp());
    						clientData.setShouldPlayerGainXp(serverData.getShouldPlayerGainXp());
    						clientData.setManaRegenPerSecond(serverData.getManaRegenPerSecond());
    						clientData.setSelectedSpell(serverData.getSelectedSpell());
    						
    						for (int i = 0; i < IPlayerData.NUMBER_OF_SPELLS; i++)
    						{
    							clientData.setSpellFromId(i, serverData.getSpellFromId(i));
    						}
    					}
    				}
    			});
    			
    			return null;
    		}
    		
    	}
    
    }

     

  13. I have a network packet that syncs all the player data from a custom capability from server to client when the player logs in. On a server this works properly every time. In SinglePlayer the data syncs inconsistently (Sometimes it syncs, sometimes it doesn't).

    	@SubscribeEvent
    	public void onPlayerLogin(PlayerLoggedInEvent event)
    	{
    		EntityPlayer player = event.player;
    		IPlayerData playerData = PlayerDataProvider.getPlayerCapability(player);
    
    		MagicMastery.network.sendTo(new MessageSyncAllPlayerData(playerData), (EntityPlayerMP) player);
    	}

     

    The weird thing is, when I put a breakpoint on this line:

    MagicMastery.network.sendTo(new MessageSyncAllPlayerData(playerData), (EntityPlayerMP) player);

    The game halts because of the breakpoint of course, so I click resume, and it syncs properly every time. 

    It seems the CombinedClient needs a second, or even half a second, to properly send/load/or whatever for this packet to work properly. I think this because it works on the server every time, and it takes the server some time to send the data to the player about the world already, so this gives my message a chance to work as well. Also when I put the breakpoint, the game pauses when it gets to the breakpoint until I click resume, giving the message time to work properly.

    I need this to sync properly on login because I have a levitation spell that allows the player to float around, and if they are floating when they log off they need to still be floating when they log back in so they don't fall.

    I could get around this by syncing the isLevitating data on player tick, but the other data won't be synced properly still. I could then sync all the other player data every 5 seconds or so but this seems unnecessary. I should really only sync the data when the player logs in and then whenever anything is changed. 

    Is there an event that takes place about a second or more after PlayerLoggedInEvent that doesn't happen too often where I can send the packet to sync all the data.

    Ugh, it's so weird this works perfectly on a server but not in SinglePlayer. It's usually the other way around lol.

     

    UPDATE: I seem to have fixed the issue by doing this:

    	@SubscribeEvent
    	public void onPlayerLogin(PlayerLoggedInEvent event) throws InterruptedException
    	{
    		if (MagicMastery.proxy instanceof CombinedClientProxy)
    		{
    			Thread.sleep(200);
    		}
    		
    		EntityPlayer player = event.player;
    		IPlayerData playerData = PlayerDataProvider.getPlayerCapability(player);
    
    		MagicMastery.network.sendTo(new MessageSyncAllPlayerData(playerData), (EntityPlayerMP) player);
    	}

     

     

    SOLVED:

    		@Override
    		public IMessage onMessage(MessageSyncAllPlayerData message, MessageContext ctx)
    		{
    			//final EntityPlayer player = MagicMastery.proxy.getEntityPlayer(ctx);
    			//final IPlayerData serverData = message.getData();
    			
    			MagicMastery.proxy.getThreadListener(ctx).addScheduledTask(() ->
    			{
                			// The finals need to go in here
                			final EntityPlayer player = MagicMastery.proxy.getEntityPlayer(ctx);
    				final IPlayerData serverData = message.getData();
                  
    				if (player != null && serverData != null)
    				{

     

  14. How do I get 0.5 block space directly in front of the player no matter which direction they are facing, even on diagonals? Also how would I transition this 0.5 or 0.2 spots to the right?

    What I'm trying to do is spawn particles above an item while its being used, I'm doing this in onUsingTick and I don't think the item has a position I can use and just move the y position, So I'm using the player position and direction they are facing. 

  15. I just created a spell like this, although I didn't test it in multiplayer yet. 

    I created a player capability with 3 variables: ticksStunned, isStunned, and stunDuration.

    So when the player is hit by the potion you would set isStunned to true and set the stunDuration.

    use PlayerTickEvent and make sure ur on phase START,

    check if the world is remote, if it is check if the player is stunned from the capability. if they are stunned increment ticksStunned. then check if they are stunned && (ticksStunned % stunDuration != 0)  and if that is true do KeyBinding.unPressAllKeys(); else set isStunned to false and reset ticksStunned to 0;

    That stops all keyboard input except the esc key(or whatever pause game key is), open inventory key, and hotbar hotkeys.

    Then u need another event for the mouse called MouseEvent, this is client side only so no need to check isRemote here.

    in here just check if the player isStunned and if they are event.setCanceled(true);

    if they aren't getting stunned for long enough or something like that isn't working right you may need to use packets to sync data from server to client or vice verse, I haven't fully tested this so idk if you can get away without packets here yet.

×
×
  • Create New...

Important Information

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