User Tools

Site Tools


tutorial:projectiles

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revisionBoth sides next revision
tutorial:projectiles [2022/04/29 03:38] – updated a method call ayutactutorial:projectiles [2022/09/29 14:37] – Remove spawn packet code, since createSpawnPacket is already overriden by ProjectileEntity. patrickmsm
Line 10: Line 10:
 We will be creating a custom snowball-like projectile that applies some very nasty effects to the entity that has been hit. We will be creating a custom snowball-like projectile that applies some very nasty effects to the entity that has been hit.
  
-// If you would like to look over the source code yourself, all of the following code was done [[https://github.com/spxctreofficial/fabric-projectile-tutorial|here]]. Before the tutorial begins, I would like to let you know that I would be using PascalCase to name the methods. Feel free to change the naming scheme to however you like, but I personally swear by PascalCase. //+// If you would like to look over the source code yourself, all of the following code was done [[https://github.com/spxctreofficial/fabric-projectile-tutorial|here]]. Before the tutorial begins, I would like to let you know that I would be using PascalCase to name the methods. Feel free to change the naming scheme to however you like, but I personally swear by PascalCase. Note that this may be outdated //
  
 ===== Creating & Registering a Projectile Entity ===== ===== Creating & Registering a Projectile Entity =====
Line 83: Line 83:
  return null; // We will configure this later, once we have created the ProjectileItem.  return null; // We will configure this later, once we have created the ProjectileItem.
  }  }
 + @Override
  
  @Environment(EnvType.CLIENT)  @Environment(EnvType.CLIENT)
Line 249: Line 250:
 ===== Rendering your Projectile Entity ===== ===== Rendering your Projectile Entity =====
  
-Your projectile entity is now defined and registered, but we are not done. Without a renderer, the ''ProjectileEntity'' will crash Minecraft. To fix this, we will define and register the ''EntityRenderer'' for our ''ProjectileEntity''. To do this, we will need a ''EntityRenderer'' in the **ClientModInitializer** and a spawn packet to make sure the texture is rendered correctly. +Your projectile entity is now defined and registered, but we are not done. Without a renderer, the ''ProjectileEntity'' will crash Minecraft. To fix this, we will define and register the ''EntityRenderer'' for our ''ProjectileEntity''. To do this, we will need a ''EntityRenderer'' in the **ClientModInitializer**. Go into your **ClientModInitializer** and write the following:
-\\ +
-Before we start, we will quickly define an Identifier that we will be using a lot: our PacketID. +
-<code java> +
-public static final Identifier PacketID = new Identifier(ProjectileTutorialMod.ModID, "spawn_packet"); +
-</code> +
-\\ +
-First on the list, we should get the ''EntityRenderer'' out of the way. Go into your **ClientModInitializer** and write the following:+
 <code java [enable_line_numbers="true"]> <code java [enable_line_numbers="true"]>
  @Override  @Override
Line 266: Line 260:
  new FlyingItemEntityRenderer(context)); */  new FlyingItemEntityRenderer(context)); */
  [. . .]  [. . .]
- } 
-</code> 
- 
-In order for the projectileEntity to be registered, we will need a spawn packet. Create a new class named ''EntitySpawnPacket'', and put this in that class. 
-<code java [enable_line_numbers="true"]> 
-public class EntitySpawnPacket { 
- public static Packet<?> create(Entity e, Identifier packetID) { 
- if (e.world.isClient) 
- throw new IllegalStateException("SpawnPacketUtil.create called on the logical client!"); 
- PacketByteBuf byteBuf = new PacketByteBuf(Unpooled.buffer()); 
- byteBuf.writeVarInt(Registry.ENTITY_TYPE.getRawId(e.getType())); 
- byteBuf.writeUuid(e.getUuid()); 
- byteBuf.writeVarInt(e.getEntityId()); 
-                 
- PacketBufUtil.writeVec3d(byteBuf, e.getPos()); 
- PacketBufUtil.writeAngle(byteBuf, e.pitch); 
- PacketBufUtil.writeAngle(byteBuf, e.yaw); 
-                /* 
-                In 1.17,we use these. 
-                byteBuf.writeVarInt(e.getId()); 
-                 
-                PacketBufUtil.writeVec3d(byteBuf, e.getPos()); 
-                PacketBufUtil.writeAngle(byteBuf, e.getPitch()); 
-                PacketBufUtil.writeAngle(byteBuf, e.getYaw());               
-                */ 
- 
- return ServerPlayNetworking.createS2CPacket(packetID, byteBuf); 
- } 
- public static final class PacketBufUtil { 
- 
- /** 
- * Packs a floating-point angle into a {@code byte}. 
- * 
- * @param angle 
- *         angle 
- * @return packed angle 
- */ 
- public static byte packAngle(float angle) { 
- return (byte) MathHelper.floor(angle * 256 / 360); 
- } 
- 
- /** 
- * Unpacks a floating-point angle from a {@code byte}. 
- * 
- * @param angleByte 
- *         packed angle 
- * @return angle 
- */ 
- public static float unpackAngle(byte angleByte) { 
- return (angleByte * 360) / 256f; 
- } 
- 
- /** 
- * Writes an angle to a {@link PacketByteBuf}. 
- * 
- * @param byteBuf 
- *         destination buffer 
- * @param angle 
- *         angle 
- */ 
- public static void writeAngle(PacketByteBuf byteBuf, float angle) { 
- byteBuf.writeByte(packAngle(angle)); 
- } 
- 
- /** 
- * Reads an angle from a {@link PacketByteBuf}. 
- * 
- * @param byteBuf 
- *         source buffer 
- * @return angle 
- */ 
- public static float readAngle(PacketByteBuf byteBuf) { 
- return unpackAngle(byteBuf.readByte()); 
- } 
- 
- /** 
- * Writes a {@link Vec3d} to a {@link PacketByteBuf}. 
- * 
- * @param byteBuf 
- *         destination buffer 
- * @param vec3d 
- *         vector 
- */ 
- public static void writeVec3d(PacketByteBuf byteBuf, Vec3d vec3d) { 
- byteBuf.writeDouble(vec3d.x); 
- byteBuf.writeDouble(vec3d.y); 
- byteBuf.writeDouble(vec3d.z); 
- } 
- 
- /** 
- * Reads a {@link Vec3d} from a {@link PacketByteBuf}. 
- * 
- * @param byteBuf 
- *         source buffer 
- * @return vector 
- */ 
- public static Vec3d readVec3d(PacketByteBuf byteBuf) { 
- double x = byteBuf.readDouble(); 
- double y = byteBuf.readDouble(); 
- double z = byteBuf.readDouble(); 
- return new Vec3d(x, y, z); 
- } 
- } 
-} 
-</code> 
- 
-This will basically read and write vectors and angles that will allow the entity's texture to be rendered correctly. I will not go in-depth about spawn packets here, but you could read up on what they do and how they function. For now, we can include this and move on. 
-\\ 
-Back to our **ClientModInitializer**, we will create a new method and put the following in that method. 
- 
-<code java [enable_line_numbers="true"]> 
- public void receiveEntityPacket() { 
- ClientSidePacketRegistry.INSTANCE.register(PacketID, (ctx, byteBuf) -> { 
- EntityType<?> et = Registry.ENTITY_TYPE.get(byteBuf.readVarInt()); 
- UUID uuid = byteBuf.readUuid(); 
- int entityId = byteBuf.readVarInt(); 
- Vec3d pos = EntitySpawnPacket.PacketBufUtil.readVec3d(byteBuf); 
- float pitch = EntitySpawnPacket.PacketBufUtil.readAngle(byteBuf); 
- float yaw = EntitySpawnPacket.PacketBufUtil.readAngle(byteBuf); 
- ctx.getTaskQueue().execute(() -> { 
- if (MinecraftClient.getInstance().world == null) 
- throw new IllegalStateException("Tried to spawn entity in a null world!"); 
- Entity e = et.create(MinecraftClient.getInstance().world); 
- if (e == null) 
- throw new IllegalStateException("Failed to create instance of entity \"" + Registry.ENTITY_TYPE.getId(et) + "\"!"); 
- e.updateTrackedPosition(pos); 
- e.setPos(pos.x, pos.y, pos.z); 
- e.pitch = pitch; 
- e.yaw = yaw; 
- e.setEntityId(entityId); 
- e.setUuid(uuid); 
- MinecraftClient.getInstance().world.addEntity(entityId, e); 
- }); 
- }); 
- } 
-</code> 
- 
-Back in our ''ProjectileEntity'' class, we must add a method to make sure everything works correctly. 
-<code java [enable_line_numbers="true"]> 
-        @Override 
- public Packet createSpawnPacket() { 
- return EntitySpawnPacket.create(this, ProjectileTutorialClient.PacketID); 
- } 
-</code> 
- 
-Finally, make sure to call this method in the **onInitializeClient()** method. 
- 
-<code java [enable_line_numbers="true"]> 
-@Override 
- public void onInitializeClient() { 
- EntityRendererRegistry.INSTANCE.register(ProjectileTutorialMod.PackedSnowballEntityType, (context) -> 
- new FlyingItemEntityRenderer(context)); 
- receiveEntityPacket(); 
  }  }
 </code> </code>
tutorial/projectiles.txt · Last modified: 2024/03/08 01:56 by netuserget