diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index 26dffcdb9..1a4302196 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -11,7 +11,7 @@ import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour; import com.simibubi.create.content.CreateItemGroup; import com.simibubi.create.content.contraptions.TorquePropagator; import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController; -import com.simibubi.create.content.curiosities.weapons.PotatoCannonProjectileTypes; +import com.simibubi.create.content.curiosities.weapons.BuiltinPotatoProjectileTypes; import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler; import com.simibubi.create.content.palettes.AllPaletteBlocks; import com.simibubi.create.content.palettes.PalettesItemGroup; @@ -121,7 +121,7 @@ public class Create { CapabilityMinecartController.register(); AllPackets.registerPackets(); SchematicInstances.register(); - PotatoCannonProjectileTypes.register(); + BuiltinPotatoProjectileTypes.register(); CHUNK_UTIL.init(); diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonProjectileTypes.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/BuiltinPotatoProjectileTypes.java similarity index 71% rename from src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonProjectileTypes.java rename to src/main/java/com/simibubi/create/content/curiosities/weapons/BuiltinPotatoProjectileTypes.java index cb1159fbe..c3856616c 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonProjectileTypes.java +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/BuiltinPotatoProjectileTypes.java @@ -1,8 +1,5 @@ package com.simibubi.create.content.curiosities.weapons; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; import java.util.UUID; import java.util.function.BiPredicate; import java.util.function.Predicate; @@ -23,7 +20,6 @@ import net.minecraft.entity.monster.ZombieVillagerEntity; import net.minecraft.entity.passive.FoxEntity; import net.minecraft.item.Food; import net.minecraft.item.Foods; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.potion.Effect; @@ -31,8 +27,6 @@ import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; import net.minecraft.util.Direction; import net.minecraft.util.Hand; -import net.minecraft.util.IItemProvider; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvent; import net.minecraft.util.SoundEvents; @@ -50,16 +44,14 @@ import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.event.entity.living.EntityTeleportEvent; import net.minecraftforge.registries.IRegistryDelegate; -public class PotatoCannonProjectileTypes { +public class BuiltinPotatoProjectileTypes { private static final GameProfile ZOMBIE_CONVERTER_NAME = new GameProfile(UUID.fromString("be12d3dc-27d3-4992-8c97-66be53fd49c5"), "Converter"); private static final WorldAttached ZOMBIE_CONVERTERS = new WorldAttached<>(w -> new FakePlayer((ServerWorld) w, ZOMBIE_CONVERTER_NAME)); - public static final Map ALL = new HashMap<>(); - public static final Map, PotatoCannonProjectileTypes> ITEM_MAP = new HashMap<>(); - public static final PotatoCannonProjectileTypes + public static final PotatoCannonProjectileType FALLBACK = create("fallback").damage(0) .register(), @@ -250,94 +242,11 @@ public class PotatoCannonProjectileTypes { .preEntityHit(setFire(12)) .soundPitch(1.0f) .registerAndAssign(AllItems.BLAZE_CAKE.get()) + ; - public static void registerType(ResourceLocation resLoc, PotatoCannonProjectileTypes type) { - synchronized (ALL) { - ALL.put(resLoc, type); - } - } - - public static void assignType(IRegistryDelegate item, PotatoCannonProjectileTypes type) { - synchronized (ITEM_MAP) { - ITEM_MAP.put(item, type); - } - } - - public static Optional getProjectileTypeOf(ItemStack item) { - if (item.isEmpty()) - return Optional.empty(); - return Optional.ofNullable(ITEM_MAP.get(item.getItem().delegate)); - } - - public static void register() {} - - private static PotatoCannonProjectileTypes.Builder create(String name) { - return new PotatoCannonProjectileTypes.Builder(Create.asResource(name)); - } - - private float gravityMultiplier = 1; - private float velocityMultiplier = 1; - private float drag = 0.99f; - private float knockback = 1; - private int reloadTicks = 10; - private int damage = 1; - private int split = 1; - private float fwoompPitch = 1; - private boolean sticky = false; - private PotatoProjectileRenderMode renderMode = new PotatoProjectileRenderMode.Billboard(); - private Predicate preEntityHit = e -> false; // True if hit should be canceled - private Predicate onEntityHit = e -> false; // True if shouldn't recover projectile - private BiPredicate onBlockHit = (w, ray) -> false; - - public float getGravityMultiplier() { - return gravityMultiplier; - } - - public float getDrag() { - return drag; - } - - public int getSplit() { - return split; - } - - public float getVelocityMultiplier() { - return velocityMultiplier; - } - - public float getKnockback() { - return knockback; - } - - public int getReloadTicks() { - return reloadTicks; - } - - public float getSoundPitch() { - return fwoompPitch; - } - - public PotatoProjectileRenderMode getRenderMode() { - return renderMode; - } - - public int getDamage() { - return damage; - } - - public boolean isSticky() { return sticky; } - - public boolean preEntityHit(EntityRayTraceResult ray) { - return preEntityHit.test(ray); - } - - public boolean onEntityHit(EntityRayTraceResult ray) { - return onEntityHit.test(ray); - } - - public boolean onBlockHit(IWorld world, BlockRayTraceResult ray) { - return onBlockHit.test(world, ray); + private static PotatoCannonProjectileType.Builder create(String name) { + return new PotatoCannonProjectileType.Builder(Create.asResource(name)); } private static Predicate setFire(int seconds) { @@ -477,103 +386,6 @@ public class PotatoCannonProjectileTypes { }; } - public static class Builder { - - protected ResourceLocation loc; - protected PotatoCannonProjectileTypes result; - - public Builder(ResourceLocation loc) { - this.result = new PotatoCannonProjectileTypes(); - this.loc = loc; - } - - public Builder damage(int damage) { - result.damage = damage; - return this; - } - - public Builder gravity(float modifier) { - result.gravityMultiplier = modifier; - return this; - } - - public Builder knockback(float knockback) { - result.knockback = knockback; - return this; - } - - public Builder drag(float drag) { - result.drag = drag; - return this; - } - - public Builder reloadTicks(int reload) { - result.reloadTicks = reload; - return this; - } - - public Builder splitInto(int split) { - result.split = split; - return this; - } - - public Builder soundPitch(float pitch) { - result.fwoompPitch = pitch; - return this; - } - - public Builder velocity(float velocity) { - result.velocityMultiplier = velocity; - return this; - } - - public Builder renderTumbling() { - result.renderMode = new PotatoProjectileRenderMode.Tumble(); - return this; - } - - public Builder renderBillboard() { - result.renderMode = new PotatoProjectileRenderMode.Billboard(); - return this; - } - - public Builder renderTowardMotion(int spriteAngle, float spin) { - result.renderMode = new PotatoProjectileRenderMode.TowardMotion(spriteAngle, spin); - return this; - } - - public Builder sticky() { - result.sticky = true; - return this; - } - - public Builder preEntityHit(Predicate callback) { - result.preEntityHit = callback; - return this; - } - - public Builder onEntityHit(Predicate callback) { - result.onEntityHit = callback; - return this; - } - - public Builder onBlockHit(BiPredicate callback) { - result.onBlockHit = callback; - return this; - } - - public PotatoCannonProjectileTypes register() { - registerType(loc, result); - return result; - } - - public PotatoCannonProjectileTypes registerAndAssign(IItemProvider... items) { - registerType(loc, result); - for (IItemProvider provider : items) - assignType(provider.asItem().delegate, result); - return result; - } - - } + public static void register() {} } diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItem.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItem.java index 7c7db65a1..46fb0767d 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItem.java @@ -49,13 +49,12 @@ public class PotatoCannonItem extends ShootableItem { public static ItemStack CLIENT_CURRENT_AMMO = ItemStack.EMPTY; public static final int MAX_DAMAGE = 100; - public PotatoCannonItem(Properties p_i48487_1_) { - super(p_i48487_1_); + public PotatoCannonItem(Properties properties) { + super(properties); } @Override - public boolean canAttackBlock(BlockState p_195938_1_, World p_195938_2_, BlockPos p_195938_3_, - PlayerEntity p_195938_4_) { + public boolean canAttackBlock(BlockState state, World world, BlockPos pos, PlayerEntity player) { return false; } @@ -137,8 +136,8 @@ public class PotatoCannonItem extends ShootableItem { .subtract(player.position() .add(0, player.getEyeHeight(), 0)); - PotatoCannonProjectileTypes projectileType = PotatoCannonProjectileTypes.getProjectileTypeOf(itemStack) - .orElse(PotatoCannonProjectileTypes.FALLBACK); + PotatoCannonProjectileType projectileType = PotatoProjectileTypeManager.getTypeForStack(itemStack) + .orElse(BuiltinPotatoProjectileTypes.FALLBACK); Vector3d lookVec = player.getLookAngle(); Vector3d motion = lookVec.add(correction) .normalize() @@ -181,8 +180,8 @@ public class PotatoCannonItem extends ShootableItem { stack.hurtAndBreak(1, player, p -> p.broadcastBreakEvent(hand)); Integer cooldown = - findAmmoInInventory(world, player, stack).flatMap(PotatoCannonProjectileTypes::getProjectileTypeOf) - .map(PotatoCannonProjectileTypes::getReloadTicks) + findAmmoInInventory(world, player, stack).flatMap(PotatoProjectileTypeManager::getTypeForStack) + .map(PotatoCannonProjectileType::getReloadTicks) .orElse(10); ShootableGadgetItemMethods.applyCooldown(player, stack, hand, this::isCannon, cooldown); @@ -200,7 +199,7 @@ public class PotatoCannonItem extends ShootableItem { private Optional findAmmoInInventory(World world, PlayerEntity player, ItemStack held) { ItemStack findAmmo = player.getProjectile(held); - return PotatoCannonProjectileTypes.getProjectileTypeOf(findAmmo) + return PotatoProjectileTypeManager.getTypeForStack(findAmmo) .map($ -> findAmmo); } @@ -215,7 +214,7 @@ public class PotatoCannonItem extends ShootableItem { if (player == null) return Optional.empty(); ItemStack findAmmo = player.getProjectile(cannon); - Optional found = PotatoCannonProjectileTypes.getProjectileTypeOf(findAmmo) + Optional found = PotatoProjectileTypeManager.getTypeForStack(findAmmo) .map($ -> findAmmo); found.ifPresent(stack -> CLIENT_CURRENT_AMMO = stack); return found; @@ -237,7 +236,7 @@ public class PotatoCannonItem extends ShootableItem { tooltip.add(new StringTextComponent("")); tooltip.add(new TranslationTextComponent(ammo.getDescriptionId()).append(new StringTextComponent(":")) .withStyle(TextFormatting.GRAY)); - PotatoCannonProjectileTypes type = PotatoCannonProjectileTypes.getProjectileTypeOf(ammo) + PotatoCannonProjectileType type = PotatoProjectileTypeManager.getTypeForStack(ammo) .get(); StringTextComponent spacing = new StringTextComponent(" "); TextFormatting green = TextFormatting.GREEN; @@ -269,7 +268,7 @@ public class PotatoCannonItem extends ShootableItem { @Override public Predicate getAllSupportedProjectiles() { - return stack -> PotatoCannonProjectileTypes.getProjectileTypeOf(stack) + return stack -> PotatoProjectileTypeManager.getTypeForStack(stack) .isPresent(); } diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonProjectileType.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonProjectileType.java new file mode 100644 index 000000000..303d83f7e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonProjectileType.java @@ -0,0 +1,295 @@ +package com.simibubi.create.content.curiosities.weapons; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.BiPredicate; +import java.util.function.Consumer; +import java.util.function.Predicate; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +import net.minecraft.item.Item; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.IItemProvider; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.ResourceLocationException; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.EntityRayTraceResult; +import net.minecraft.world.IWorld; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.IRegistryDelegate; + +public class PotatoCannonProjectileType { + + private Set> items = new HashSet<>(); + + private int reloadTicks = 10; + private int damage = 1; + private int split = 1; + private float knockback = 1; + private float drag = 0.99f; + private float velocityMultiplier = 1; + private float gravityMultiplier = 1; + private float soundPitch = 1; + private boolean sticky = false; + private PotatoProjectileRenderMode renderMode = PotatoProjectileRenderMode.Billboard.INSTANCE; + + private Predicate preEntityHit = e -> false; // True if hit should be canceled + private Predicate onEntityHit = e -> false; // True if shouldn't recover projectile + private BiPredicate onBlockHit = (w, ray) -> false; + + protected PotatoCannonProjectileType() { + } + + public Set> getItems() { + return items; + } + + public int getReloadTicks() { + return reloadTicks; + } + + public int getDamage() { + return damage; + } + + public int getSplit() { + return split; + } + + public float getKnockback() { + return knockback; + } + + public float getDrag() { + return drag; + } + + public float getVelocityMultiplier() { + return velocityMultiplier; + } + + public float getGravityMultiplier() { + return gravityMultiplier; + } + + public float getSoundPitch() { + return soundPitch; + } + + public boolean isSticky() { + return sticky; + } + + public PotatoProjectileRenderMode getRenderMode() { + return renderMode; + } + + public boolean preEntityHit(EntityRayTraceResult ray) { + return preEntityHit.test(ray); + } + + public boolean onEntityHit(EntityRayTraceResult ray) { + return onEntityHit.test(ray); + } + + public boolean onBlockHit(IWorld world, BlockRayTraceResult ray) { + return onBlockHit.test(world, ray); + } + + public static PotatoCannonProjectileType fromJson(JsonObject object) { + PotatoCannonProjectileType type = new PotatoCannonProjectileType(); + try { + JsonElement itemsElement = object.get("items"); + if (itemsElement != null && itemsElement.isJsonArray()) { + for (JsonElement element : itemsElement.getAsJsonArray()) { + if (element.isJsonPrimitive()) { + JsonPrimitive primitive = element.getAsJsonPrimitive(); + if (primitive.isString()) { + try { + Item item = ForgeRegistries.ITEMS.getValue(new ResourceLocation(primitive.getAsString())); + if (item != null) { + type.items.add(item.delegate); + } + } catch (ResourceLocationException e) { + // + } + } + } + } + } + + parseJsonPrimitive(object, "reload_ticks", JsonPrimitive::isNumber, primitive -> type.reloadTicks = primitive.getAsInt()); + parseJsonPrimitive(object, "damage", JsonPrimitive::isNumber, primitive -> type.damage = primitive.getAsInt()); + parseJsonPrimitive(object, "split", JsonPrimitive::isNumber, primitive -> type.split = primitive.getAsInt()); + parseJsonPrimitive(object, "knockback", JsonPrimitive::isNumber, primitive -> type.knockback = primitive.getAsFloat()); + parseJsonPrimitive(object, "drag", JsonPrimitive::isNumber, primitive -> type.drag = primitive.getAsFloat()); + parseJsonPrimitive(object, "velocity_multiplier", JsonPrimitive::isNumber, primitive -> type.velocityMultiplier = primitive.getAsFloat()); + parseJsonPrimitive(object, "gravity_multiplier", JsonPrimitive::isNumber, primitive -> type.gravityMultiplier = primitive.getAsFloat()); + parseJsonPrimitive(object, "sound_pitch", JsonPrimitive::isNumber, primitive -> type.soundPitch = primitive.getAsFloat()); + parseJsonPrimitive(object, "sticky", JsonPrimitive::isBoolean, primitive -> type.sticky = primitive.getAsBoolean()); + } catch (Exception e) { + // + } + return type; + } + + private static void parseJsonPrimitive(JsonObject object, String key, Predicate predicate, Consumer consumer) { + JsonElement element = object.get(key); + if (element != null && element.isJsonPrimitive()) { + JsonPrimitive primitive = element.getAsJsonPrimitive(); + if (predicate.test(primitive)) { + consumer.accept(primitive); + } + } + } + + public static void toBuffer(PotatoCannonProjectileType type, PacketBuffer buffer) { + buffer.writeVarInt(type.items.size()); + for (IRegistryDelegate delegate : type.items) { + buffer.writeResourceLocation(delegate.name()); + } + buffer.writeInt(type.reloadTicks); + buffer.writeInt(type.damage); + buffer.writeInt(type.split); + buffer.writeFloat(type.knockback); + buffer.writeFloat(type.drag); + buffer.writeFloat(type.velocityMultiplier); + buffer.writeFloat(type.gravityMultiplier); + buffer.writeFloat(type.soundPitch); + buffer.writeBoolean(type.sticky); + } + + public static PotatoCannonProjectileType fromBuffer(PacketBuffer buffer) { + PotatoCannonProjectileType type = new PotatoCannonProjectileType(); + int size = buffer.readVarInt(); + for (int i = 0; i < size; i++) { + Item item = ForgeRegistries.ITEMS.getValue(buffer.readResourceLocation()); + if (item != null) { + type.items.add(item.delegate); + } + } + type.reloadTicks = buffer.readInt(); + type.damage = buffer.readInt(); + type.split = buffer.readInt(); + type.knockback = buffer.readFloat(); + type.drag = buffer.readFloat(); + type.velocityMultiplier = buffer.readFloat(); + type.gravityMultiplier = buffer.readFloat(); + type.soundPitch = buffer.readFloat(); + type.sticky = buffer.readBoolean(); + return type; + } + + public static class Builder { + + protected ResourceLocation id; + protected PotatoCannonProjectileType result; + + public Builder(ResourceLocation id) { + this.id = id; + this.result = new PotatoCannonProjectileType(); + } + + public Builder reloadTicks(int reload) { + result.reloadTicks = reload; + return this; + } + + public Builder damage(int damage) { + result.damage = damage; + return this; + } + + public Builder splitInto(int split) { + result.split = split; + return this; + } + + public Builder knockback(float knockback) { + result.knockback = knockback; + return this; + } + + public Builder drag(float drag) { + result.drag = drag; + return this; + } + + public Builder velocity(float velocity) { + result.velocityMultiplier = velocity; + return this; + } + + public Builder gravity(float modifier) { + result.gravityMultiplier = modifier; + return this; + } + + public Builder soundPitch(float pitch) { + result.soundPitch = pitch; + return this; + } + + public Builder sticky() { + result.sticky = true; + return this; + } + + public Builder renderMode(PotatoProjectileRenderMode renderMode) { + result.renderMode = renderMode; + return this; + } + + public Builder renderBillboard() { + renderMode(PotatoProjectileRenderMode.Billboard.INSTANCE); + return this; + } + + public Builder renderTumbling() { + renderMode(PotatoProjectileRenderMode.Tumble.INSTANCE); + return this; + } + + public Builder renderTowardMotion(int spriteAngle, float spin) { + renderMode(new PotatoProjectileRenderMode.TowardMotion(spriteAngle, spin)); + return this; + } + + public Builder preEntityHit(Predicate callback) { + result.preEntityHit = callback; + return this; + } + + public Builder onEntityHit(Predicate callback) { + result.onEntityHit = callback; + return this; + } + + public Builder onBlockHit(BiPredicate callback) { + result.onBlockHit = callback; + return this; + } + + public Builder addItems(IItemProvider... items) { + for (IItemProvider provider : items) + result.items.add(provider.asItem().delegate); + return this; + } + + public PotatoCannonProjectileType register() { + PotatoProjectileTypeManager.registerBuiltinType(id, result); + return result; + } + + public PotatoCannonProjectileType registerAndAssign(IItemProvider... items) { + addItems(items); + register(); + return result; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileEntity.java index 0cd481f15..b6e188202 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileEntity.java +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileEntity.java @@ -39,7 +39,7 @@ import net.minecraftforge.items.ItemHandlerHelper; public class PotatoProjectileEntity extends DamagingProjectileEntity implements IEntityAdditionalSpawnData { - PotatoCannonProjectileTypes type; + PotatoCannonProjectileType type; ItemStack stack = ItemStack.EMPTY; Entity stuckEntity; @@ -63,10 +63,10 @@ public class PotatoProjectileEntity extends DamagingProjectileEntity implements this.stack = stack; } - public PotatoCannonProjectileTypes getProjectileType() { + public PotatoCannonProjectileType getProjectileType() { if (type == null) - type = PotatoCannonProjectileTypes.getProjectileTypeOf(stack) - .orElse(PotatoCannonProjectileTypes.FALLBACK); + type = PotatoProjectileTypeManager.getTypeForStack(stack) + .orElse(BuiltinPotatoProjectileTypes.FALLBACK); return type; } @@ -128,7 +128,7 @@ public class PotatoProjectileEntity extends DamagingProjectileEntity implements } public void tick() { - PotatoCannonProjectileTypes projectileType = getProjectileType(); + PotatoCannonProjectileType projectileType = getProjectileType(); Entity stuckEntity = getStuckEntity(); if (stuckEntity != null) { @@ -174,7 +174,7 @@ public class PotatoProjectileEntity extends DamagingProjectileEntity implements Vector3d hit = ray.getLocation(); Entity target = ray.getEntity(); - PotatoCannonProjectileTypes projectileType = getProjectileType(); + PotatoCannonProjectileType projectileType = getProjectileType(); float damage = projectileType.getDamage() * additionalDamageMult; float knockback = projectileType.getKnockback() + additionalKnockback; Entity owner = this.getOwner(); diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderMode.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderMode.java index 14908086d..799ed35e1 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderMode.java +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderMode.java @@ -1,7 +1,5 @@ package com.simibubi.create.content.curiosities.weapons; -import static com.simibubi.create.content.curiosities.weapons.PotatoProjectileRenderMode.entityRandom; - import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.utility.AngleHelper; @@ -20,6 +18,8 @@ public interface PotatoProjectileRenderMode { public static class Billboard implements PotatoProjectileRenderMode { + public static final Billboard INSTANCE = new Billboard(); + @Override @OnlyIn(Dist.CLIENT) public void transform(MatrixStack ms, PotatoProjectileEntity entity, float pt) { @@ -35,10 +35,13 @@ public interface PotatoProjectileRenderMode { .rotateX(180 + AngleHelper.deg(MathHelper.atan2(diff.y, -MathHelper.sqrt(diff.x * diff.x + diff.z * diff.z)))); } + } public static class Tumble extends Billboard { + public static final Tumble INSTANCE = new Tumble(); + @Override @OnlyIn(Dist.CLIENT) public void transform(MatrixStack ms, PotatoProjectileEntity entity, float pt) { @@ -47,6 +50,7 @@ public interface PotatoProjectileRenderMode { .rotateZ((entity.tickCount + pt) * 2 * entityRandom(entity, 16)) .rotateX((entity.tickCount + pt) * entityRandom(entity, 32)); } + } public static class TowardMotion implements PotatoProjectileRenderMode { diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileTypeManager.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileTypeManager.java new file mode 100644 index 000000000..86539ef5e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileTypeManager.java @@ -0,0 +1,160 @@ +package com.simibubi.create.content.curiosities.weapons; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.function.Supplier; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.resources.JsonReloadListener; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraft.profiler.IProfiler; +import net.minecraft.resources.IResourceManager; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.network.NetworkEvent.Context; +import net.minecraftforge.fml.network.PacketDistributor; +import net.minecraftforge.registries.IRegistryDelegate; + +public class PotatoProjectileTypeManager { + + private static final Map BUILTIN_TYPE_MAP = new HashMap<>(); + private static final Map CUSTOM_TYPE_MAP = new HashMap<>(); + private static final Map, PotatoCannonProjectileType> ITEM_TO_TYPE_MAP = new HashMap<>(); + + public static void registerBuiltinType(ResourceLocation id, PotatoCannonProjectileType type) { + synchronized (BUILTIN_TYPE_MAP) { + BUILTIN_TYPE_MAP.put(id, type); + } + } + + public static PotatoCannonProjectileType getBuiltinType(ResourceLocation id) { + return BUILTIN_TYPE_MAP.get(id); + } + + public static PotatoCannonProjectileType getCustomType(ResourceLocation id) { + return CUSTOM_TYPE_MAP.get(id); + } + + public static PotatoCannonProjectileType getTypeForItem(IRegistryDelegate item) { + return ITEM_TO_TYPE_MAP.get(item); + } + + public static Optional getTypeForStack(ItemStack item) { + if (item.isEmpty()) + return Optional.empty(); + return Optional.ofNullable(getTypeForItem(item.getItem().delegate)); + } + + public static void clear() { + CUSTOM_TYPE_MAP.clear(); + ITEM_TO_TYPE_MAP.clear(); + } + + public static void fillItemMap() { + for (Map.Entry entry : BUILTIN_TYPE_MAP.entrySet()) { + PotatoCannonProjectileType type = entry.getValue(); + for (IRegistryDelegate delegate : type.getItems()) { + ITEM_TO_TYPE_MAP.put(delegate, type); + } + } + for (Map.Entry entry : CUSTOM_TYPE_MAP.entrySet()) { + PotatoCannonProjectileType type = entry.getValue(); + for (IRegistryDelegate delegate : type.getItems()) { + ITEM_TO_TYPE_MAP.put(delegate, type); + } + } + ITEM_TO_TYPE_MAP.remove(AllItems.POTATO_CANNON.get().delegate); + } + + public static void toBuffer(PacketBuffer buffer) { + buffer.writeVarInt(CUSTOM_TYPE_MAP.size()); + for (Map.Entry entry : CUSTOM_TYPE_MAP.entrySet()) { + buffer.writeResourceLocation(entry.getKey()); + PotatoCannonProjectileType.toBuffer(entry.getValue(), buffer); + } + } + + public static void fromBuffer(PacketBuffer buffer) { + clear(); + + int size = buffer.readVarInt(); + for (int i = 0; i < size; i++) { + CUSTOM_TYPE_MAP.put(buffer.readResourceLocation(), PotatoCannonProjectileType.fromBuffer(buffer)); + } + + fillItemMap(); + } + + public static void syncTo(ServerPlayerEntity player) { + AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), new SyncPacket()); + } + + public static void syncToAll() { + AllPackets.channel.send(PacketDistributor.ALL.noArg(), new SyncPacket()); + } + + public static class ReloadListener extends JsonReloadListener { + + private static final Gson GSON = new Gson(); + + public static final ReloadListener INSTANCE = new ReloadListener(); + + protected ReloadListener() { + super(GSON, "potato_cannon_projectile_types"); + } + + @Override + protected void apply(Map map, IResourceManager resourceManager, IProfiler profiler) { + clear(); + + for (Map.Entry entry : map.entrySet()) { + JsonElement element = entry.getValue(); + if (element.isJsonObject()) { + ResourceLocation id = entry.getKey(); + JsonObject object = element.getAsJsonObject(); + PotatoCannonProjectileType type = PotatoCannonProjectileType.fromJson(object); + CUSTOM_TYPE_MAP.put(id, type); + } + } + + fillItemMap(); + } + + } + + public static class SyncPacket extends SimplePacketBase { + + private PacketBuffer buffer; + + public SyncPacket() { + } + + public SyncPacket(PacketBuffer buffer) { + this.buffer = buffer; + } + + @Override + public void write(PacketBuffer buffer) { + toBuffer(buffer); + } + + @Override + public void handle(Supplier context) { + context.get().enqueueWork(() -> { + fromBuffer(buffer); + }); + context.get().setPacketHandled(true); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/events/CommonEvents.java b/src/main/java/com/simibubi/create/events/CommonEvents.java index 3631e9b0b..ca6acbd9f 100644 --- a/src/main/java/com/simibubi/create/events/CommonEvents.java +++ b/src/main/java/com/simibubi/create/events/CommonEvents.java @@ -8,6 +8,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.tra import com.simibubi.create.content.contraptions.fluids.recipe.FluidTransferRecipes; import com.simibubi.create.content.contraptions.fluids.recipe.PotionMixingRecipeManager; import com.simibubi.create.content.contraptions.wrench.WrenchItem; +import com.simibubi.create.content.curiosities.weapons.PotatoProjectileTypeManager; import com.simibubi.create.content.curiosities.zapper.ZapperInteractionHandler; import com.simibubi.create.content.curiosities.zapper.ZapperItem; import com.simibubi.create.content.logistics.item.LinkedControllerServerHandler; @@ -42,7 +43,6 @@ import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.world.BlockEvent.FluidPlaceBlockEvent; import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.WorldEvent; -import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.event.server.FMLServerStoppingEvent; @@ -118,7 +118,7 @@ public class CommonEvents { WrenchItem.wrenchInstaKillsMinecarts(event); } - @SubscribeEvent(priority = EventPriority.NORMAL) + @SubscribeEvent public static void registerCommands(RegisterCommandsEvent event) { AllCommands.register(event.getDispatcher()); } @@ -128,6 +128,7 @@ public class CommonEvents { event.addListener(RecipeFinder.LISTENER); event.addListener(PotionMixingRecipeManager.LISTENER); event.addListener(FluidTransferRecipes.LISTENER); + event.addListener(PotatoProjectileTypeManager.ReloadListener.INSTANCE); } @SubscribeEvent diff --git a/src/main/java/com/simibubi/create/foundation/mixin/PlayerListMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/PlayerListMixin.java new file mode 100644 index 000000000..acc2a16dc --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/PlayerListMixin.java @@ -0,0 +1,25 @@ +package com.simibubi.create.foundation.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.simibubi.create.content.curiosities.weapons.PotatoProjectileTypeManager; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.network.NetworkManager; +import net.minecraft.server.management.PlayerList; + +@Mixin(PlayerList.class) +public class PlayerListMixin { + @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/item/crafting/ServerRecipeBook;sendInitialRecipeBook(Lnet/minecraft/entity/player/ServerPlayerEntity;)V", shift = At.Shift.AFTER), method = "placeNewPlayer(Lnet/minecraft/network/NetworkManager;Lnet/minecraft/entity/player/ServerPlayerEntity;)V") + private void afterSendRecipeBookOnPlaceNewPlayer(NetworkManager networkManager, ServerPlayerEntity player, CallbackInfo ci) { + PotatoProjectileTypeManager.syncTo(player); + } + + @Inject(at = @At("TAIL"), method = "reloadResources()V") + private void onReloadResources(CallbackInfo ci) { + PotatoProjectileTypeManager.syncToAll(); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java index 079bc0cbd..81c9a9a2a 100644 --- a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java +++ b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java @@ -25,6 +25,7 @@ import com.simibubi.create.content.curiosities.bell.SoulPulseEffectPacket; import com.simibubi.create.content.curiosities.symmetry.SymmetryEffectPacket; import com.simibubi.create.content.curiosities.tools.BlueprintAssignCompleteRecipePacket; import com.simibubi.create.content.curiosities.tools.ExtendoGripInteractionPacket; +import com.simibubi.create.content.curiosities.weapons.PotatoProjectileTypeManager; import com.simibubi.create.content.curiosities.weapons.PotatoCannonPacket; import com.simibubi.create.content.curiosities.zapper.ZapperBeamPacket; import com.simibubi.create.content.logistics.block.depot.EjectorElytraPacket; @@ -117,6 +118,7 @@ public enum AllPackets { POTATO_CANNON(PotatoCannonPacket.class, PotatoCannonPacket::new, PLAY_TO_CLIENT), SOUL_PULSE(SoulPulseEffectPacket.class, SoulPulseEffectPacket::new, PLAY_TO_CLIENT), PERSISTENT_DATA(ISyncPersistentData.Packet.class, ISyncPersistentData.Packet::new, PLAY_TO_CLIENT), + SYNC_POTATO_PROJECTILE_TYPES(PotatoProjectileTypeManager.SyncPacket.class, PotatoProjectileTypeManager.SyncPacket::new, PLAY_TO_CLIENT), ; diff --git a/src/main/resources/create.mixins.json b/src/main/resources/create.mixins.json index dc2d36193..19029a55a 100644 --- a/src/main/resources/create.mixins.json +++ b/src/main/resources/create.mixins.json @@ -5,6 +5,7 @@ "compatibilityLevel": "JAVA_8", "refmap": "create.refmap.json", "mixins": [ + "PlayerListMixin" ], "client": [ "BreakProgressMixin",