Some bomb fixes, colored spell book overlay are now separate files

This commit is contained in:
WinDanesz
2026-05-05 02:43:22 +02:00
parent e7b8f7681c
commit bbe4634535
25 changed files with 324 additions and 183 deletions
@@ -179,6 +179,8 @@ public class CommonProxy {
public void handleConquerShrinePacket(PacketConquerShrine.Message message){}
public void handleBombExplosionPacket(PacketBombExplosion.Message message){}
// SECTION Misc
// ===============================================================================================================
@@ -717,6 +717,65 @@ public class ClientProxy extends CommonProxy {
}else Wizardry.logger.warn("Received a PacketConquerShrine, but there was no shrine core at the position sent");
}
@Override
public void handleBombExplosionPacket(PacketBombExplosion.Message message){
net.minecraft.world.World world = Minecraft.getMinecraft().world;
double x = message.x, y = message.y, z = message.z;
float blastMultiplier = message.blastMultiplier;
switch(message.bombType){
case PacketBombExplosion.FIREBOMB:
ParticleBuilder.create(Type.FLASH).pos(x, y, z).scale(5 * blastMultiplier).clr(1, 0.6f, 0).spawn(world);
for(int i = 0; i < 60 * blastMultiplier; i++){
ParticleBuilder.create(Type.MAGIC_FIRE, world.rand, x, y, z, 2 * blastMultiplier, false)
.time(10 + world.rand.nextInt(4)).scale(2 + world.rand.nextFloat()).spawn(world);
ParticleBuilder.create(Type.DARK_MAGIC, world.rand, x, y, z, 2 * blastMultiplier, false)
.clr(1.0f, 0.2f + world.rand.nextFloat() * 0.4f, 0.0f).spawn(world);
}
world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, x, y, z, 0, 0, 0);
break;
case PacketBombExplosion.POISON_BOMB:
ParticleBuilder.create(Type.FLASH).pos(x, y, z).scale(5 * blastMultiplier)
.clr(0.2f + world.rand.nextFloat() * 0.3f, 0.6f, 0.0f).spawn(world);
for(int i = 0; i < 60 * blastMultiplier; i++){
ParticleBuilder.create(Type.SPARKLE, world.rand, x, y, z, 2 * blastMultiplier, false).time(35)
.scale(2).clr(0.2f + world.rand.nextFloat() * 0.3f, 0.6f, 0.0f).spawn(world);
ParticleBuilder.create(Type.DARK_MAGIC, world.rand, x, y, z, 2 * blastMultiplier, false)
.clr(0.2f + world.rand.nextFloat() * 0.2f, 0.8f, 0.0f).spawn(world);
}
world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, x, y, z, 0, 0, 0);
break;
case PacketBombExplosion.SMOKE_BOMB:
ParticleBuilder.create(Type.FLASH).pos(x, y, z).scale(5 * blastMultiplier).clr(0, 0, 0).spawn(world);
world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, x, y, z, 0, 0, 0);
for(int i = 0; i < 60 * blastMultiplier; i++){
float brightness = world.rand.nextFloat() * 0.1f + 0.1f;
ParticleBuilder.create(Type.CLOUD, world.rand, x, y, z, 2 * blastMultiplier, false)
.clr(brightness, brightness, brightness).time(80 + world.rand.nextInt(12)).shaded(true).spawn(world);
brightness = world.rand.nextFloat() * 0.3f;
ParticleBuilder.create(Type.DARK_MAGIC, world.rand, x, y, z, 2 * blastMultiplier, false)
.clr(brightness, brightness, brightness).spawn(world);
}
break;
case PacketBombExplosion.SPARK_BOMB:
ParticleBuilder.spawnShockParticles(world, x, y, z);
for(int id : message.secondaryTargetIDs){
net.minecraft.entity.Entity target = world.getEntityByID(id);
if(target instanceof net.minecraft.entity.EntityLivingBase){
ParticleBuilder.create(Type.LIGHTNING).pos(x, y, z).target(target).spawn(world);
ParticleBuilder.spawnShockParticles(world, target.posX,
target.posY + target.height / 2, target.posZ);
}
}
break;
}
}
// Rendering
// ===============================================================================================================
@@ -881,48 +940,13 @@ public class ClientProxy extends CommonProxy {
}
public void registerItemColorHandlers() {
Minecraft.getMinecraft().getItemColors().registerItemColorHandler((stack, tintIndex) -> {
if (Wizardry.settings.spellBookColors && tintIndex == 1) { // layer 1 is the overlay
Spell spell = Spell.byMetadata(stack.getMetadata());
if (shouldDisplayDiscovered(spell, stack)) {
// Even if the spell is discovered, the charm might be required for colouration
if(Wizardry.settings.spellBookColorsRequireArchivistsEyeglass && !ItemArtefact.isArtefactActive(getThePlayer(), WizardryItems.charm_spell_discovery)) {
return -1;
}
Element element = spell.getElement();
if (element != null) {
switch (element) {
case MAGIC:
return 0xAAAAAA; // GRAY
case FIRE:
return 0xAA0000; // DARK_RED
case ICE:
return 0x55FFFF; // AQUA
case LIGHTNING:
return 0x00AAAA; // DARK_AQUA
case NECROMANCY:
return 0xAA00AA; // DARK_PURPLE
case EARTH:
return 0x00AA00; // DARK_GREEN
case SORCERY:
return 0x55FF55; // GREEN
case HEALING:
return 0xFFFF55; // YELLOW
}
}
}
}
return -1;
}, WizardryItems.spell_book);
// Spell book overlay textures are now per-element, so no runtime tinting is needed.
}
public void registerModelProperties() {
Item spellBook = WizardryItems.spell_book;
ResourceLocation discoveredProperty = new ResourceLocation(Wizardry.MODID, "discovered");
spellBook.addPropertyOverride(discoveredProperty, (stack, world, entity) -> {
spellBook.addPropertyOverride(new ResourceLocation(Wizardry.MODID, "discovered"), (stack, world, entity) -> {
if (!Wizardry.settings.spellBookColors) return 0.0f;
boolean discovered = shouldDisplayDiscovered(Spell.byMetadata(stack.getMetadata()), stack);
@@ -938,5 +962,27 @@ public class ClientProxy extends CommonProxy {
return discovered ? 1.0f : 0.0f;
});
// Returns ordinal+1 for each element (1=MAGIC through 8=HEALING), or 0 if not yet discovered.
// Drives per-element bookmark texture selection via model overrides in spell_book.json.
spellBook.addPropertyOverride(new ResourceLocation(Wizardry.MODID, "element"), (stack, world, entity) -> {
if (!Wizardry.settings.spellBookColors) return 0.0f;
Spell spell = Spell.byMetadata(stack.getMetadata());
boolean discovered = shouldDisplayDiscovered(spell, stack);
if(!discovered) return 0.0f;
if(Wizardry.settings.spellBookColorsRequireArchivistsEyeglass){
if(entity instanceof EntityPlayer){
if(!ItemArtefact.isArtefactActive((EntityPlayer)entity, WizardryItems.charm_spell_discovery)) return 0.0f;
} else {
return 0.0f;
}
}
Element element = spell.getElement();
return element == null ? 0.0f : (float)(element.ordinal() + 1);
});
}
}
@@ -1,18 +1,18 @@
package electroblob.wizardry.entity.projectile;
import electroblob.wizardry.packet.PacketBombExplosion;
import electroblob.wizardry.packet.WizardryPacketHandler;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.EntityUtils;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.ParticleBuilder;
import electroblob.wizardry.util.ParticleBuilder.Type;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import java.util.List;
@@ -29,41 +29,28 @@ public class EntityFirebomb extends EntityBomb {
@Override
protected void onImpact(RayTraceResult rayTrace){
Entity entityHit = rayTrace.entityHit;
if(entityHit != null){
// This is if the firebomb gets a direct hit
float damage = Spells.firebomb.getProperty(Spell.DIRECT_DAMAGE).floatValue() * damageMultiplier;
entityHit.attackEntityFrom(
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.FIRE).setProjectile(),
damage);
if(!MagicDamage.isEntityImmune(DamageType.FIRE, entityHit))
entityHit.setFire(Spells.firebomb.getProperty(Spell.BURN_DURATION).intValue());
}
// Particle effect
if(world.isRemote){
ParticleBuilder.create(Type.FLASH).pos(this.getPositionVector()).scale(5 * blastMultiplier).clr(1, 0.6f, 0)
.spawn(world);
for(int i = 0; i < 60 * blastMultiplier; i++){
ParticleBuilder.create(Type.MAGIC_FIRE, rand, posX, posY, posZ, 2*blastMultiplier, false)
.time(10 + rand.nextInt(4)).scale(2 + rand.nextFloat()).spawn(world);
ParticleBuilder.create(Type.DARK_MAGIC, rand, posX, posY, posZ, 2*blastMultiplier, false)
.clr(1.0f, 0.2f + rand.nextFloat() * 0.4f, 0.0f).spawn(world);
}
this.world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.posX, this.posY, this.posZ, 0, 0, 0);
}
if(!this.world.isRemote){
Entity entityHit = rayTrace.entityHit;
if(entityHit != null){
// This is if the firebomb gets a direct hit
float damage = Spells.firebomb.getProperty(Spell.DIRECT_DAMAGE).floatValue() * damageMultiplier;
entityHit.attackEntityFrom(
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.FIRE).setProjectile(),
damage);
if(!MagicDamage.isEntityImmune(DamageType.FIRE, entityHit))
entityHit.setFire(Spells.firebomb.getProperty(Spell.BURN_DURATION).intValue());
}
// Notify clients to play the explosion effect
WizardryPacketHandler.net.sendToAllAround(
new PacketBombExplosion.Message(PacketBombExplosion.FIREBOMB, posX, posY, posZ, blastMultiplier),
new NetworkRegistry.TargetPoint(world.provider.getDimension(), posX, posY, posZ, 64));
this.playSound(WizardrySounds.ENTITY_FIREBOMB_SMASH, 1.5F, rand.nextFloat() * 0.4F + 0.6F);
this.playSound(WizardrySounds.ENTITY_FIREBOMB_FIRE, 1, 1);
@@ -82,9 +69,9 @@ public class EntityFirebomb extends EntityBomb {
target.setFire(Spells.firebomb.getProperty(Spell.BURN_DURATION).intValue());
}
}
this.setDead();
}
this.setDead();
}
}
@@ -1,20 +1,20 @@
package electroblob.wizardry.entity.projectile;
import electroblob.wizardry.packet.PacketBombExplosion;
import electroblob.wizardry.packet.WizardryPacketHandler;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.EntityUtils;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.ParticleBuilder;
import electroblob.wizardry.util.ParticleBuilder.Type;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.MobEffects;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import java.util.List;
@@ -31,44 +31,30 @@ public class EntityPoisonBomb extends EntityBomb {
@Override
protected void onImpact(RayTraceResult rayTrace){
Entity entityHit = rayTrace.entityHit;
if(entityHit != null){
// This is if the poison bomb gets a direct hit
float damage = Spells.poison_bomb.getProperty(Spell.DIRECT_DAMAGE).floatValue() * damageMultiplier;
entityHit.attackEntityFrom(
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.POISON).setProjectile(),
damage);
if(entityHit instanceof EntityLivingBase && !MagicDamage.isEntityImmune(DamageType.POISON, entityHit))
((EntityLivingBase)entityHit).addPotionEffect(new PotionEffect(MobEffects.POISON,
Spells.poison_bomb.getProperty(Spell.DIRECT_EFFECT_DURATION).intValue(),
Spells.poison_bomb.getProperty(Spell.DIRECT_EFFECT_STRENGTH).intValue()));
}
// Particle effect
if(world.isRemote){
ParticleBuilder.create(Type.FLASH).pos(this.getPositionVector()).scale(5 * blastMultiplier)
.clr(0.2f + rand.nextFloat() * 0.3f, 0.6f, 0.0f).spawn(world);
for(int i = 0; i < 60 * blastMultiplier; i++){
ParticleBuilder.create(Type.SPARKLE, rand, posX, posY, posZ, 2*blastMultiplier, false).time(35)
.scale(2).clr(0.2f + rand.nextFloat() * 0.3f, 0.6f, 0.0f).spawn(world);
ParticleBuilder.create(Type.DARK_MAGIC, rand, posX, posY, posZ, 2*blastMultiplier, false)
.clr(0.2f + rand.nextFloat() * 0.2f, 0.8f, 0.0f).spawn(world);
}
// Spawning this after the other particles fixes the rendering colour bug. It's a bit of a cheat, but it
// works pretty well.
this.world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.posX, this.posY, this.posZ, 0, 0, 0);
}
if(!this.world.isRemote){
Entity entityHit = rayTrace.entityHit;
if(entityHit != null){
// This is if the poison bomb gets a direct hit
float damage = Spells.poison_bomb.getProperty(Spell.DIRECT_DAMAGE).floatValue() * damageMultiplier;
entityHit.attackEntityFrom(
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.POISON).setProjectile(),
damage);
if(entityHit instanceof EntityLivingBase && !MagicDamage.isEntityImmune(DamageType.POISON, entityHit))
((EntityLivingBase)entityHit).addPotionEffect(new PotionEffect(MobEffects.POISON,
Spells.poison_bomb.getProperty(Spell.DIRECT_EFFECT_DURATION).intValue(),
Spells.poison_bomb.getProperty(Spell.DIRECT_EFFECT_STRENGTH).intValue()));
}
// Notify clients to play the explosion effect
WizardryPacketHandler.net.sendToAllAround(
new PacketBombExplosion.Message(PacketBombExplosion.POISON_BOMB, posX, posY, posZ, blastMultiplier),
new NetworkRegistry.TargetPoint(world.provider.getDimension(), posX, posY, posZ, 64));
this.playSound(WizardrySounds.ENTITY_POISON_BOMB_SMASH, 1.5F, rand.nextFloat() * 0.4F + 0.6F);
this.playSound(WizardrySounds.ENTITY_POISON_BOMB_POISON, 1.2F, 1.0f);
@@ -88,8 +74,8 @@ public class EntityPoisonBomb extends EntityBomb {
Spells.poison_bomb.getProperty(Spell.SPLASH_EFFECT_STRENGTH).intValue()));
}
}
this.setDead();
}
this.setDead();
}
}
@@ -1,17 +1,17 @@
package electroblob.wizardry.entity.projectile;
import electroblob.wizardry.packet.PacketBombExplosion;
import electroblob.wizardry.packet.WizardryPacketHandler;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.EntityUtils;
import electroblob.wizardry.util.ParticleBuilder;
import electroblob.wizardry.util.ParticleBuilder.Type;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.MobEffects;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import java.util.List;
@@ -29,27 +29,13 @@ public class EntitySmokeBomb extends EntityBomb {
@Override
protected void onImpact(RayTraceResult rayTrace){
// Particle effect
if(world.isRemote){
ParticleBuilder.create(Type.FLASH).pos(this.getPositionVector()).scale(5 * blastMultiplier).clr(0, 0, 0).spawn(world);
this.world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.posX, this.posY, this.posZ, 0, 0, 0);
for(int i = 0; i < 60 * blastMultiplier; i++){
float brightness = rand.nextFloat() * 0.1f + 0.1f;
ParticleBuilder.create(Type.CLOUD, rand, posX, posY, posZ, 2*blastMultiplier, false)
.clr(brightness, brightness, brightness).time(80 + this.rand.nextInt(12)).shaded(true).spawn(world);
brightness = rand.nextFloat() * 0.3f;
ParticleBuilder.create(Type.DARK_MAGIC, rand, posX, posY, posZ, 2*blastMultiplier, false)
.clr(brightness, brightness, brightness).spawn(world);
}
}
if(!this.world.isRemote){
// Notify clients to play the explosion effect
WizardryPacketHandler.net.sendToAllAround(
new PacketBombExplosion.Message(PacketBombExplosion.SMOKE_BOMB, posX, posY, posZ, blastMultiplier),
new NetworkRegistry.TargetPoint(world.provider.getDimension(), posX, posY, posZ, 64));
this.playSound(WizardrySounds.ENTITY_SMOKE_BOMB_SMASH, 1.5F, rand.nextFloat() * 0.4F + 0.6F);
this.playSound(WizardrySounds.ENTITY_SMOKE_BOMB_SMOKE, 1.2F, 1.0f);
@@ -65,8 +51,8 @@ public class EntitySmokeBomb extends EntityBomb {
target.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, duration, 0));
}
}
this.setDead();
}
this.setDead();
}
}
@@ -1,5 +1,7 @@
package electroblob.wizardry.entity.projectile;
import electroblob.wizardry.packet.PacketBombExplosion;
import electroblob.wizardry.packet.WizardryPacketHandler;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.spell.Spell;
@@ -13,7 +15,9 @@ import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import java.util.ArrayList;
import java.util.List;
public class EntitySparkBomb extends EntityBomb {
@@ -31,47 +35,37 @@ public class EntitySparkBomb extends EntityBomb {
@Override
protected void onImpact(RayTraceResult rayTrace){
this.playSound(WizardrySounds.ENTITY_SPARK_BOMB_HIT_BLOCK, 0.5f, 0.5f);
Entity entityHit = rayTrace.entityHit;
if(!this.world.isRemote){
if(entityHit != null){
// This is if the spark bomb gets a direct hit
float damage = Spells.spark_bomb.getProperty(Spell.DIRECT_DAMAGE).floatValue() * damageMultiplier;
Entity entityHit = rayTrace.entityHit;
this.playSound(WizardrySounds.ENTITY_SPARK_BOMB_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
if(entityHit != null){
// This is if the spark bomb gets a direct hit
float damage = Spells.spark_bomb.getProperty(Spell.DIRECT_DAMAGE).floatValue() * damageMultiplier;
entityHit.attackEntityFrom(
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK).setProjectile(),
damage);
this.playSound(WizardrySounds.ENTITY_SPARK_BOMB_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
}
entityHit.attackEntityFrom(
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK).setProjectile(),
damage);
}
// Particle effect
if(world.isRemote){
ParticleBuilder.spawnShockParticles(world, posX, posY + height/2, posZ);
}
double seekerRange = Spells.spark_bomb.getProperty(Spell.EFFECT_RADIUS).doubleValue() * blastMultiplier;
double seekerRange = Spells.spark_bomb.getProperty(Spell.EFFECT_RADIUS).doubleValue() * blastMultiplier;
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(seekerRange, this.posX, this.posY,
this.posZ, this.world);
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(seekerRange, this.posX, this.posY,
this.posZ, this.world);
List<Integer> secondaryTargetIDs = new ArrayList<>();
for(int i = 0; i < Math.min(targets.size(), Spells.spark_bomb.getProperty(SECONDARY_MAX_TARGETS).intValue()); i++){
for(int i = 0; i < Math.min(targets.size(), Spells.spark_bomb.getProperty(SECONDARY_MAX_TARGETS).intValue()); i++){
boolean flag = targets.get(i) != entityHit && targets.get(i) != this.getThrower()
&& !(targets.get(i) instanceof EntityPlayer
&& ((EntityPlayer)targets.get(i)).isCreative());
boolean flag = targets.get(i) != entityHit && targets.get(i) != this.getThrower()
&& !(targets.get(i) instanceof EntityPlayer
&& ((EntityPlayer)targets.get(i)).isCreative());
// Detects (client side) if target is the thrower, to stop particles being spawned around them.
//if(flag && world.isRemote && targets.get(i).getEntityId() == this.playerID) flag = false;
if(flag){
EntityLivingBase target = targets.get(i);
if(!this.world.isRemote){
if(flag){
EntityLivingBase target = targets.get(i);
target.playSound(WizardrySounds.ENTITY_SPARK_BOMB_CHAIN, 1.0F, rand.nextFloat() * 0.4F + 1.5F);
@@ -79,11 +73,18 @@ public class EntitySparkBomb extends EntityBomb {
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK),
Spells.spark_bomb.getProperty(Spell.SPLASH_DAMAGE).floatValue() * damageMultiplier);
}else{
ParticleBuilder.create(Type.LIGHTNING).pos(this.getPositionVector()).target(target).spawn(world);
ParticleBuilder.spawnShockParticles(world, target.posX, target.posY + target.height/2, target.posZ);
secondaryTargetIDs.add(target.getEntityId());
}
}
// Notify clients to play the explosion effect, including lightning arcs to secondary targets
int[] idArray = secondaryTargetIDs.stream().mapToInt(Integer::intValue).toArray();
WizardryPacketHandler.net.sendToAllAround(
new PacketBombExplosion.Message(PacketBombExplosion.SPARK_BOMB, posX, posY + height / 2, posZ,
blastMultiplier, idArray),
new NetworkRegistry.TargetPoint(world.provider.getDimension(), posX, posY, posZ, 64));
this.playSound(WizardrySounds.ENTITY_SPARK_BOMB_HIT_BLOCK, 0.5f, 0.5f);
}
this.setDead();
@@ -0,0 +1,79 @@
package electroblob.wizardry.packet;
import electroblob.wizardry.Wizardry;
import io.netty.buffer.ByteBuf;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
/**
* <b>[Server -> Client]</b> This packet is sent when a bomb entity impacts something. It is used to guarantee that the
* client always sees the explosion effect, even in singleplayer where the server may remove the entity before the
* client's own simulation can call {@code onImpact()}.
*/
public class PacketBombExplosion implements IMessageHandler<PacketBombExplosion.Message, IMessage> {
/** Bomb type constants, matching the order bombs are handled in {@link electroblob.wizardry.CommonProxy}. */
public static final int FIREBOMB = 0;
public static final int POISON_BOMB = 1;
public static final int SMOKE_BOMB = 2;
public static final int SPARK_BOMB = 3;
@Override
public IMessage onMessage(Message message, MessageContext ctx){
if(ctx.side.isClient()){
net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(
() -> Wizardry.proxy.handleBombExplosionPacket(message));
}
return null;
}
public static class Message implements IMessage {
/** One of the bomb type constants defined in {@link PacketBombExplosion}. */
public int bombType;
public double x, y, z;
public float blastMultiplier;
/** Entity IDs of secondary targets struck by the spark bomb chain. Empty for other bomb types. */
public int[] secondaryTargetIDs;
// Required no-arg constructor
public Message(){}
public Message(int bombType, double x, double y, double z, float blastMultiplier){
this(bombType, x, y, z, blastMultiplier, new int[0]);
}
public Message(int bombType, double x, double y, double z, float blastMultiplier, int[] secondaryTargetIDs){
this.bombType = bombType;
this.x = x;
this.y = y;
this.z = z;
this.blastMultiplier = blastMultiplier;
this.secondaryTargetIDs = secondaryTargetIDs;
}
@Override
public void fromBytes(ByteBuf buf){
bombType = buf.readInt();
x = buf.readDouble();
y = buf.readDouble();
z = buf.readDouble();
blastMultiplier = buf.readFloat();
int count = buf.readInt();
secondaryTargetIDs = new int[count];
for(int i = 0; i < count; i++) secondaryTargetIDs[i] = buf.readInt();
}
@Override
public void toBytes(ByteBuf buf){
buf.writeInt(bombType);
buf.writeDouble(x);
buf.writeDouble(y);
buf.writeDouble(z);
buf.writeFloat(blastMultiplier);
buf.writeInt(secondaryTargetIDs.length);
for(int id : secondaryTargetIDs) buf.writeInt(id);
}
}
}
@@ -35,6 +35,7 @@ public class WizardryPacketHandler {
registerMessage(PacketSpellQuickAccess.class, PacketSpellQuickAccess.Message.class);
registerMessage(PacketRequestDonationPerks.class, PacketRequestDonationPerks.Message.class);
registerMessage(PacketSyncDonationPerks.class, PacketSyncDonationPerks.Message.class);
registerMessage(PacketBombExplosion.class, PacketBombExplosion.Message.class);
}
private static int nextPacketId = 0;
@@ -1,17 +1,14 @@
{
"parent": "ebwizardry:item/spell_book_undiscovered",
"overrides": [
{
"predicate": {
"festive": 1
},
"model": "ebwizardry:item/festive_spell_book"
},
{
"predicate": {
"ebwizardry:discovered": 1
},
"model": "ebwizardry:item/spell_book_discovered"
}
{"predicate": {"ebwizardry:element": 1}, "model": "ebwizardry:item/spell_book_discovered_magic"},
{"predicate": {"ebwizardry:element": 2}, "model": "ebwizardry:item/spell_book_discovered_fire"},
{"predicate": {"ebwizardry:element": 3}, "model": "ebwizardry:item/spell_book_discovered_ice"},
{"predicate": {"ebwizardry:element": 4}, "model": "ebwizardry:item/spell_book_discovered_lightning"},
{"predicate": {"ebwizardry:element": 5}, "model": "ebwizardry:item/spell_book_discovered_necromancy"},
{"predicate": {"ebwizardry:element": 6}, "model": "ebwizardry:item/spell_book_discovered_earth"},
{"predicate": {"ebwizardry:element": 7}, "model": "ebwizardry:item/spell_book_discovered_sorcery"},
{"predicate": {"ebwizardry:element": 8}, "model": "ebwizardry:item/spell_book_discovered_healing"},
{"predicate": {"festive": 1}, "model": "ebwizardry:item/festive_spell_book"}
]
}
@@ -0,0 +1,7 @@
{
"parent": "item/generated",
"textures": {
"layer0": "ebwizardry:items/spell_book",
"layer1": "ebwizardry:items/spell_book_overlay_earth"
}
}
@@ -0,0 +1,7 @@
{
"parent": "item/generated",
"textures": {
"layer0": "ebwizardry:items/spell_book",
"layer1": "ebwizardry:items/spell_book_overlay_fire"
}
}
@@ -0,0 +1,7 @@
{
"parent": "item/generated",
"textures": {
"layer0": "ebwizardry:items/spell_book",
"layer1": "ebwizardry:items/spell_book_overlay_healing"
}
}
@@ -0,0 +1,7 @@
{
"parent": "item/generated",
"textures": {
"layer0": "ebwizardry:items/spell_book",
"layer1": "ebwizardry:items/spell_book_overlay_ice"
}
}
@@ -0,0 +1,7 @@
{
"parent": "item/generated",
"textures": {
"layer0": "ebwizardry:items/spell_book",
"layer1": "ebwizardry:items/spell_book_overlay_lightning"
}
}
@@ -0,0 +1,7 @@
{
"parent": "item/generated",
"textures": {
"layer0": "ebwizardry:items/spell_book",
"layer1": "ebwizardry:items/spell_book_overlay_magic"
}
}
@@ -0,0 +1,7 @@
{
"parent": "item/generated",
"textures": {
"layer0": "ebwizardry:items/spell_book",
"layer1": "ebwizardry:items/spell_book_overlay_necromancy"
}
}
@@ -0,0 +1,7 @@
{
"parent": "item/generated",
"textures": {
"layer0": "ebwizardry:items/spell_book",
"layer1": "ebwizardry:items/spell_book_overlay_sorcery"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B