diff --git a/src/generated/resources/data/minecraft/recipe/smoke_dye.json b/src/generated/resources/data/minecraft/recipe/smoke_dye.json new file mode 100644 index 000000000..9b14894e7 --- /dev/null +++ b/src/generated/resources/data/minecraft/recipe/smoke_dye.json @@ -0,0 +1,4 @@ +{ + "type": "superbwarfare:smoke_dye", + "category": "misc" +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/datagen/ModRecipeProvider.java b/src/main/java/com/atsuishio/superbwarfare/datagen/ModRecipeProvider.java index 8d4af13ce..f79f2f0f8 100644 --- a/src/main/java/com/atsuishio/superbwarfare/datagen/ModRecipeProvider.java +++ b/src/main/java/com/atsuishio/superbwarfare/datagen/ModRecipeProvider.java @@ -8,6 +8,7 @@ import com.atsuishio.superbwarfare.item.ContainerBlockItem; import com.atsuishio.superbwarfare.recipe.AmmoBoxAddAmmoRecipe; import com.atsuishio.superbwarfare.recipe.AmmoBoxExtractAmmoRecipe; import com.atsuishio.superbwarfare.recipe.PotionMortarShellRecipe; +import com.atsuishio.superbwarfare.recipe.SmokeDyeRecipe; import net.minecraft.core.HolderLookup; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.PackOutput; @@ -36,6 +37,7 @@ public class ModRecipeProvider extends RecipeProvider { SpecialRecipeBuilder.special(PotionMortarShellRecipe::new).save(writer, "potion_mortar_shell"); SpecialRecipeBuilder.special(AmmoBoxAddAmmoRecipe::new).save(writer, "ammo_box_add_ammo"); SpecialRecipeBuilder.special(AmmoBoxExtractAmmoRecipe::new).save(writer, "ammo_box_extract_ammo"); + SpecialRecipeBuilder.special(SmokeDyeRecipe::new).save(writer, "smoke_dye"); // items // 材料 diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/projectile/M18SmokeGrenadeEntity.java b/src/main/java/com/atsuishio/superbwarfare/entity/projectile/M18SmokeGrenadeEntity.java index 086187f93..f907f4822 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/projectile/M18SmokeGrenadeEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/projectile/M18SmokeGrenadeEntity.java @@ -35,9 +35,14 @@ import software.bernie.geckolib.animation.AnimatableManager; import software.bernie.geckolib.util.GeckoLibUtil; public class M18SmokeGrenadeEntity extends ThrowableItemProjectile implements GeoEntity { + + private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); + private int count = 8; private int fuse = 100; - private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); + private float rColor = 1.0f; + private float gColor = 1.0f; + private float bColor = 1.0f; public M18SmokeGrenadeEntity(EntityType type, Level world) { super(type, world); @@ -60,6 +65,9 @@ public class M18SmokeGrenadeEntity extends ThrowableItemProjectile implements Ge super.addAdditionalSaveData(pCompound); pCompound.putFloat("Fuse", this.fuse); pCompound.putInt("Count", this.count); + pCompound.putFloat("RColor", this.rColor); + pCompound.putFloat("GColor", this.gColor); + pCompound.putFloat("BColor", this.bColor); } @Override @@ -71,6 +79,15 @@ public class M18SmokeGrenadeEntity extends ThrowableItemProjectile implements Ge if (pCompound.contains("Count")) { this.count = Mth.clamp(pCompound.getInt("Count"), 1, 64); } + if (pCompound.contains("RColor")) { + this.rColor = pCompound.getFloat("RColor"); + } + if (pCompound.contains("GColor")) { + this.gColor = pCompound.getFloat("GColor"); + } + if (pCompound.contains("BColor")) { + this.bColor = pCompound.getFloat("BColor"); + } } @Override @@ -160,7 +177,7 @@ public class M18SmokeGrenadeEntity extends ThrowableItemProjectile implements Ge if (fuse <= 0 && tickCount % 2 == 0) { if (this.level() instanceof ServerLevel serverLevel) { - ParticleTool.sendParticle(serverLevel, new CustomSmokeOption(1, 1, 1), this.getX(), this.getY() + getBbHeight(), this.getZ(), + ParticleTool.sendParticle(serverLevel, new CustomSmokeOption(this.rColor, this.gColor, this.bColor), this.getX(), this.getY() + getBbHeight(), this.getZ(), 8, 0.075, 0.01, 0.075, 0.08, true); } } @@ -196,4 +213,22 @@ public class M18SmokeGrenadeEntity extends ThrowableItemProjectile implements Ge return 0.07F; } + public float getRed() { + return rColor; + } + + public float getGreen() { + return gColor; + } + + public float getBlue() { + return bColor; + } + + public M18SmokeGrenadeEntity setColor(float r, float g, float b) { + this.rColor = r; + this.gColor = g; + this.bColor = b; + return this; + } } diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModRecipes.java b/src/main/java/com/atsuishio/superbwarfare/init/ModRecipes.java index 85e67d5b1..71410ee9c 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModRecipes.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModRecipes.java @@ -4,6 +4,7 @@ import com.atsuishio.superbwarfare.Mod; import com.atsuishio.superbwarfare.recipe.AmmoBoxAddAmmoRecipe; import com.atsuishio.superbwarfare.recipe.AmmoBoxExtractAmmoRecipe; import com.atsuishio.superbwarfare.recipe.PotionMortarShellRecipe; +import com.atsuishio.superbwarfare.recipe.SmokeDyeRecipe; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer; @@ -22,4 +23,7 @@ public class ModRecipes { RECIPE_SERIALIZERS.register("ammo_box_add_ammo", () -> new SimpleCraftingRecipeSerializer<>(AmmoBoxAddAmmoRecipe::new)); public static final DeferredHolder, SimpleCraftingRecipeSerializer> AMMO_BOX_EXTRACT_AMMO_SERIALIZER = RECIPE_SERIALIZERS.register("ammo_box_extract_ammo", () -> new SimpleCraftingRecipeSerializer<>(AmmoBoxExtractAmmoRecipe::new)); + + public static final DeferredHolder, RecipeSerializer> SMOKE_DYE_SERIALIZER = + RECIPE_SERIALIZERS.register("smoke_dye", () -> new SimpleCraftingRecipeSerializer<>(SmokeDyeRecipe::new)); } diff --git a/src/main/java/com/atsuishio/superbwarfare/item/M18SmokeGrenade.java b/src/main/java/com/atsuishio/superbwarfare/item/M18SmokeGrenade.java index 0e6944560..57d91fcc4 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/M18SmokeGrenade.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/M18SmokeGrenade.java @@ -28,12 +28,12 @@ import java.util.List; public class M18SmokeGrenade extends Item implements ProjectileItem { + public static final String TAG_COLOR = "Color"; + public M18SmokeGrenade() { super(new Properties().rarity(Rarity.UNCOMMON)); } - public static final String TAG_COLOR = "Color"; - public void setColor(ItemStack stack, int color) { NBTTool.getTag(stack).putInt(TAG_COLOR, color); } @@ -77,7 +77,10 @@ public class M18SmokeGrenade extends Item implements ProjectileItem { player.getCooldowns().addCooldown(stack.getItem(), 20); float power = Math.min(usingTime / 8f, 1.8f); - M18SmokeGrenadeEntity grenade = new M18SmokeGrenadeEntity(player, worldIn, 80 - usingTime); + int color = this.getColor(stack); + + M18SmokeGrenadeEntity grenade = new M18SmokeGrenadeEntity(player, worldIn, 80 - usingTime) + .setColor((color >> 16 & 255) / 255f, ((color >> 8) & 255) / 255f, (color & 255) / 255f); grenade.shootFromRotation(player, player.getXRot(), player.getYRot(), 0, power, 0); worldIn.addFreshEntity(grenade); @@ -96,7 +99,9 @@ public class M18SmokeGrenade extends Item implements ProjectileItem { @ParametersAreNonnullByDefault public @NotNull ItemStack finishUsingItem(ItemStack pStack, Level pLevel, LivingEntity pLivingEntity) { if (!pLevel.isClientSide) { - M18SmokeGrenadeEntity grenade = new M18SmokeGrenadeEntity(pLivingEntity, pLevel, 2); + int color = this.getColor(pStack); + M18SmokeGrenadeEntity grenade = new M18SmokeGrenadeEntity(pLivingEntity, pLevel, 2) + .setColor((color >> 16 & 255) / 255f, ((color >> 8) & 255) / 255f, (color & 255) / 255f); pLevel.addFreshEntity(grenade); if (pLivingEntity instanceof Player player) { diff --git a/src/main/java/com/atsuishio/superbwarfare/recipe/SmokeDyeRecipe.java b/src/main/java/com/atsuishio/superbwarfare/recipe/SmokeDyeRecipe.java new file mode 100644 index 000000000..c7bad3d59 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/recipe/SmokeDyeRecipe.java @@ -0,0 +1,136 @@ +package com.atsuishio.superbwarfare.recipe; + +import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.init.ModRecipes; +import com.atsuishio.superbwarfare.item.M18SmokeGrenade; +import com.google.common.collect.Lists; +import net.minecraft.core.HolderLookup; +import net.minecraft.util.FastColor; +import net.minecraft.world.item.DyeItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.CraftingBookCategory; +import net.minecraft.world.item.crafting.CraftingInput; +import net.minecraft.world.item.crafting.CustomRecipe; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.List; + +public class SmokeDyeRecipe extends CustomRecipe { + + public SmokeDyeRecipe(CraftingBookCategory pCategory) { + super(pCategory); + } + + @Override + public boolean matches(@NotNull CraftingInput input, @NotNull Level pLevel) { + ItemStack itemstack = ItemStack.EMPTY; + List list = Lists.newArrayList(); + + for (var stack : input.items()) { + if (stack.isEmpty()) continue; + if (stack.is(ModItems.M18_SMOKE_GRENADE.get())) { + if (!itemstack.isEmpty()) { + return false; + } + + itemstack = stack; + } else { + if (!(stack.getItem() instanceof DyeItem)) { + return false; + } + + list.add(stack); + } + } + return !itemstack.isEmpty() && !list.isEmpty(); + } + + @Override + @ParametersAreNonnullByDefault + public @NotNull ItemStack assemble(CraftingInput input, HolderLookup.Provider registries) { + List list = Lists.newArrayList(); + ItemStack itemstack = ItemStack.EMPTY; + + for (var stack : input.items()) { + if (!stack.isEmpty()) { + var item = stack.getItem(); + if (stack.is(ModItems.M18_SMOKE_GRENADE.get())) { + if (!itemstack.isEmpty()) { + return ItemStack.EMPTY; + } + itemstack = stack.copy(); + } else { + if (!(item instanceof DyeItem dyeItem)) { + return ItemStack.EMPTY; + } + list.add(dyeItem); + } + } + } + + return !itemstack.isEmpty() && !list.isEmpty() ? dyeItem(itemstack, list) : ItemStack.EMPTY; + } + + @Override + public boolean canCraftInDimensions(int pWidth, int pHeight) { + return pWidth * pHeight >= 2; + } + + @Override + public @NotNull RecipeSerializer getSerializer() { + return ModRecipes.SMOKE_DYE_SERIALIZER.get(); + } + + public static ItemStack dyeItem(ItemStack pStack, List pDyes) { + ItemStack itemstack; + int[] colors = new int[3]; + int i = 0; + int j = 0; + if (pStack.getItem() instanceof M18SmokeGrenade grenade) { + itemstack = pStack.copyWithCount(1); + int color = grenade.getColor(pStack); + if (color != 0xFFFFFF) { + float r = (float) (color >> 16 & 255) / 255.0F; + float g = (float) (color >> 8 & 255) / 255.0F; + float b = (float) (color & 255) / 255.0F; + i += (int) (Math.max(r, Math.max(g, b)) * 255.0F); + colors[0] += (int) (r * 255.0F); + colors[1] += (int) (g * 255.0F); + colors[2] += (int) (b * 255.0F); + ++j; + } + + for (DyeItem dyeitem : pDyes) { + var dyeColors = dyeitem.getDyeColor().getTextureDiffuseColor(); + + int r = FastColor.ARGB32.red(dyeColors); + int g = FastColor.ARGB32.green(dyeColors); + int b = FastColor.ARGB32.blue(dyeColors); + + i += Math.max(r, Math.max(g, b)); + colors[0] += r; + colors[1] += g; + colors[2] += b; + ++j; + } + } else { + return ItemStack.EMPTY; + } + + int red = colors[0] / j; + int green = colors[1] / j; + int blue = colors[2] / j; + float rate = (float) i / (float) j; + float max = (float) Math.max(red, Math.max(green, blue)); + red = (int) ((float) red * rate / max); + green = (int) ((float) green * rate / max); + blue = (int) ((float) blue * rate / max); + int color = (red << 8) + green; + color = (color << 8) + blue; + grenade.setColor(itemstack, color); + return itemstack; + } +}