Skip to content

Commit

Permalink
配方谓词与配方结果实现
Browse files Browse the repository at this point in the history
  • Loading branch information
Gu-ZT committed Mar 25, 2024
1 parent d9ed87b commit c019ebd
Show file tree
Hide file tree
Showing 16 changed files with 550 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ default int lastNonSpace(@NotNull String entry) {
return stack;
}

@SuppressWarnings("DuplicatedCode")
default NonNullList<BlockState> getBlockResults(@NotNull JsonArray array) {
NonNullList<BlockState> results = NonNullList.create();
for (JsonElement element : array) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import dev.dubhe.anvilcraft.data.recipe.anvil.outcome.DamageAnvil;
import dev.dubhe.anvilcraft.data.recipe.anvil.outcome.SetBlock;
import dev.dubhe.anvilcraft.data.recipe.anvil.outcome.SpawnItem;
import dev.dubhe.anvilcraft.data.recipe.anvil.predicate.HasBlock;
import dev.dubhe.anvilcraft.data.recipe.anvil.predicate.HasBlockIngredient;
import dev.dubhe.anvilcraft.data.recipe.anvil.predicate.HasItem;
import dev.dubhe.anvilcraft.data.recipe.anvil.predicate.HasItemIngredient;
import dev.dubhe.anvilcraft.util.IItemStackInjector;
Expand Down Expand Up @@ -153,5 +158,10 @@ public enum Type implements RecipeType<AnvilRecipe> {
static {
RecipePredicate.register("has_item", HasItem::new, HasItem::new);
RecipePredicate.register("has_item_ingredient", HasItemIngredient::new, HasItemIngredient::new);
RecipePredicate.register("has_block", HasBlock::new, HasBlock::new);
RecipePredicate.register("has_block_ingredient", HasBlockIngredient::new, HasBlockIngredient::new);
RecipeOutcome.register("damage_anvil", DamageAnvil::new, DamageAnvil::new);
RecipeOutcome.register("set_block", SetBlock::new, SetBlock::new);
RecipeOutcome.register("spawn_item", SpawnItem::new, SpawnItem::new);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.dubhe.anvilcraft.data.recipe.anvil;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.GsonHelper;
Expand All @@ -19,7 +20,7 @@ static void register(String id, Function<JsonObject, RecipeOutcome> jsonDecoder,
RecipeOutcome.NETWORK_DECODER.put(id, networkDecoder);
}

String getId();
String getType();

boolean process(AnvilCraftingContainer container);

Expand All @@ -40,4 +41,6 @@ static void register(String id, Function<JsonObject, RecipeOutcome> jsonDecoder,
}

void toNetwork(FriendlyByteBuf buffer);

JsonElement toJson();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package dev.dubhe.anvilcraft.data.recipe.anvil.outcome;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer;
import dev.dubhe.anvilcraft.data.recipe.anvil.RecipeOutcome;
import lombok.Getter;
import net.minecraft.network.FriendlyByteBuf;
import org.jetbrains.annotations.NotNull;

@Getter
public class DamageAnvil implements RecipeOutcome {
private final String type = "damage_anvil";

public DamageAnvil() {
}

public DamageAnvil(FriendlyByteBuf buffer) {
}

public DamageAnvil(JsonObject serializedRecipe) {
}

@Override
public boolean process(@NotNull AnvilCraftingContainer container) {
container.setAnvilDamage(true);
return true;
}

@Override
public void toNetwork(@NotNull FriendlyByteBuf buffer) {
buffer.writeUtf(this.getType());
}

@Override
public JsonElement toJson() {
JsonObject object = new JsonObject();
object.addProperty("type", this.getType());
return object;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package dev.dubhe.anvilcraft.data.recipe.anvil.outcome;

import com.google.gson.*;
import dev.dubhe.anvilcraft.AnvilCraft;
import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer;
import dev.dubhe.anvilcraft.data.recipe.anvil.RecipeOutcome;
import dev.dubhe.anvilcraft.util.IBlockStateInjector;
import lombok.Getter;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.GsonHelper;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;

public class SetBlock implements RecipeOutcome {
@Getter
private final String type = "set_block";
private final Vec3 offset;
private final double chance;
private final BlockState result;

public SetBlock(Vec3 offset, double chance, BlockState result) {
this.offset = offset;
this.chance = chance;
this.result = result;
}

public SetBlock(@NotNull FriendlyByteBuf buffer) {
this.offset = new Vec3(buffer.readVector3f());
this.chance = buffer.readDouble();
this.result = IBlockStateInjector.fromJson(AnvilCraft.GSON.fromJson(buffer.readUtf(), JsonElement.class));
}

public SetBlock(@NotNull JsonObject serializedRecipe) {
JsonArray array = GsonHelper.getAsJsonArray(serializedRecipe, "offset");
double[] vec3 = {0.0d, 0.0d, 0.0d};
for (int i = 0; i < array.size() && i < 3; i++) {
JsonElement element = array.get(i);
if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) {
vec3[i] = element.getAsDouble();
} else throw new JsonSyntaxException("Expected offset to be a Double, was " + GsonHelper.getType(element));
}
this.offset = new Vec3(vec3[0], vec3[1], vec3[2]);
this.chance = GsonHelper.getAsDouble(serializedRecipe, "chance");
this.result = IBlockStateInjector.fromJson(GsonHelper.getAsJsonObject(serializedRecipe, "result"));
}

@Override
public boolean process(@NotNull AnvilCraftingContainer container) {
Level level = container.getLevel();
RandomSource random = level.getRandom();
if (random.nextDouble() > this.chance) return true;
BlockPos pos = container.getPos();
Vec3 vec3 = pos.getCenter().add(this.offset);
BlockPos blockPos = BlockPos.containing(vec3.x, vec3.y, vec3.z);
return level.setBlock(blockPos, this.result, 3);
}

@Override
public void toNetwork(@NotNull FriendlyByteBuf buffer) {
buffer.writeUtf(this.getType());
buffer.writeVector3f(this.offset.toVector3f());
buffer.writeDouble(this.chance);
buffer.writeUtf(this.result.toJson().toString());
}

@Override
public JsonElement toJson() {
double[] vec3 = {this.offset.x(), this.offset.y(), this.offset.z()};
JsonArray offset = new JsonArray();
for (double v : vec3) {
offset.add(new JsonPrimitive(v));
}
JsonObject object = new JsonObject();
object.addProperty("type", this.getType());
object.add("offset", offset);
object.addProperty("change", this.chance);
return object;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package dev.dubhe.anvilcraft.data.recipe.anvil.outcome;

import com.google.gson.*;
import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer;
import dev.dubhe.anvilcraft.data.recipe.anvil.RecipeOutcome;
import dev.dubhe.anvilcraft.util.IBlockStateInjector;
import dev.dubhe.anvilcraft.util.IItemStackInjector;
import lombok.Getter;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.GsonHelper;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;

public class SpawnItem implements RecipeOutcome {
@Getter
private final String type = "spawn_item";
private final Vec3 offset;
private final double chance;
private final ItemStack result;

public SpawnItem(Vec3 offset, double chance, ItemStack result) {
this.offset = offset;
this.chance = chance;
this.result = result;
}

public SpawnItem(@NotNull FriendlyByteBuf buffer) {
this.offset = new Vec3(buffer.readVector3f());
this.chance = buffer.readDouble();
this.result = buffer.readItem();
}

public SpawnItem(@NotNull JsonObject serializedRecipe) {
JsonArray array = GsonHelper.getAsJsonArray(serializedRecipe, "offset");
double[] vec3 = {0.0d, 0.0d, 0.0d};
for (int i = 0; i < array.size() && i < 3; i++) {
JsonElement element = array.get(i);
if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) {
vec3[i] = element.getAsDouble();
} else throw new JsonSyntaxException("Expected offset to be a Double, was " + GsonHelper.getType(element));
}
this.offset = new Vec3(vec3[0], vec3[1], vec3[2]);
this.chance = GsonHelper.getAsDouble(serializedRecipe, "chance");
this.result = IItemStackInjector.fromJson(GsonHelper.getAsJsonObject(serializedRecipe, "result"));
}

@Override
public boolean process(@NotNull AnvilCraftingContainer container) {
Level level = container.getLevel();
RandomSource random = level.getRandom();
if (random.nextDouble() > this.chance) return true;
BlockPos pos = container.getPos();
Vec3 vec3 = pos.getCenter().add(this.offset);
ItemEntity entity = new ItemEntity(level, vec3.x, vec3.y, vec3.z, this.result.copy(), 0.0d, 0.0d, 0.0d);
return level.addFreshEntity(entity);
}

@Override
public void toNetwork(@NotNull FriendlyByteBuf buffer) {
buffer.writeUtf(this.getType());
buffer.writeVector3f(this.offset.toVector3f());
buffer.writeDouble(this.chance);
buffer.writeItem(this.result);
}

@Override
public JsonElement toJson() {
JsonObject object = new JsonObject();
double[] vec3 = {this.offset.x(), this.offset.y(), this.offset.z()};
JsonArray offset = new JsonArray();
for (double v : vec3) {
offset.add(new JsonPrimitive(v));
}
object.addProperty("type", this.getType());
object.add("offset", offset);
object.addProperty("change", this.chance);
this.result.toJson();
return object;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package dev.dubhe.anvilcraft.data.recipe.anvil.predicate;

import com.google.gson.*;
import dev.dubhe.anvilcraft.AnvilCraft;
import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer;
import dev.dubhe.anvilcraft.data.recipe.anvil.RecipePredicate;
import lombok.Getter;
import net.minecraft.advancements.critereon.BlockPredicate;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;

public class HasBlock implements RecipePredicate {
@Getter
private final String type = "has_block";
protected final Vec3 offset;
protected final BlockPredicate matchBlock;

public HasBlock(Vec3 offset, BlockPredicate matchBlock) {
this.offset = offset;
this.matchBlock = matchBlock;
}

public HasBlock(JsonObject serializedRecipe) {
JsonArray array = GsonHelper.getAsJsonArray(serializedRecipe, "offset");
double[] vec3 = {0.0d, 0.0d, 0.0d};
for (int i = 0; i < array.size() && i < 3; i++) {
JsonElement element = array.get(i);
if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) {
vec3[i] = element.getAsDouble();
} else throw new JsonSyntaxException("Expected offset to be a Double, was " + GsonHelper.getType(element));
}
this.offset = new Vec3(vec3[0], vec3[1], vec3[2]);
if (!serializedRecipe.has("match_block")) throw new JsonSyntaxException("Missing match_block");
this.matchBlock = BlockPredicate.fromJson(serializedRecipe.get("match_block"));
}

public HasBlock(@NotNull FriendlyByteBuf buffer) {
this.offset = new Vec3(buffer.readVector3f());
this.matchBlock = BlockPredicate.fromJson(AnvilCraft.GSON.fromJson(buffer.readUtf(), JsonElement.class));
}

@Override
public boolean matches(@NotNull AnvilCraftingContainer container) {
Level level = container.getLevel();
if (!(level instanceof ServerLevel level1)) return false;
BlockPos pos = container.getPos();
Vec3 vec3 = pos.getCenter().add(this.offset);
BlockPos blockPos = BlockPos.containing(vec3.x, vec3.y, vec3.z);
return this.matchBlock.matches(level1, blockPos);
}

@Override
public boolean process(AnvilCraftingContainer container) {
return true;
}

@Override
public void toNetwork(FriendlyByteBuf buffer) {
buffer.writeUtf(this.getType());
buffer.writeVector3f(this.offset.toVector3f());
buffer.writeUtf(this.matchBlock.serializeToJson().toString());
}

@Override
public @NotNull JsonElement toJson() {
double[] vec3 = {this.offset.x(), this.offset.y(), this.offset.z()};
JsonArray offset = new JsonArray();
for (double v : vec3) {
offset.add(new JsonPrimitive(v));
}
JsonElement matchBlock = this.matchBlock.serializeToJson();
JsonObject object = new JsonObject();
object.addProperty("type", this.getType());
object.add("offset", offset);
object.add("match_block", matchBlock);
return object;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package dev.dubhe.anvilcraft.data.recipe.anvil.predicate;

import com.google.gson.JsonObject;
import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer;
import lombok.Getter;
import net.minecraft.advancements.critereon.BlockPredicate;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;

@Getter
public class HasBlockIngredient extends HasBlock {
private final String type = "has_block_ingredient";

public HasBlockIngredient(Vec3 offset, BlockPredicate matchBlock) {
super(offset, matchBlock);
}

public HasBlockIngredient(JsonObject serializedRecipe) {
super(serializedRecipe);
}

public HasBlockIngredient(@NotNull FriendlyByteBuf buffer) {
super(buffer);
}

@Override
public boolean process(@NotNull AnvilCraftingContainer container) {
Level level = container.getLevel();
BlockPos pos = container.getPos();
Vec3 vec3 = pos.getCenter().add(this.offset);
BlockPos blockPos = BlockPos.containing(vec3.x, vec3.y, vec3.z);
return level.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 3);
}
}
Loading

0 comments on commit c019ebd

Please sign in to comment.