Skip to content

Commit

Permalink
Tinkers' Construct Documentation (#157)
Browse files Browse the repository at this point in the history
* Basic docs

* Finish docs

* Add example script

* Add .register()

* Split entity melting

* Changes

* Update en_us.lang

* Gen example script

* Fix errors

* Split casting into different files

* Better descriptions

* forgor the script 💀

* Use resource handler

* add register description

* use clear for entity melting

* Improve alloying description

* alloying removal examples

* Ahhh

* Use description defaults

* use clear()

* `

* the schizophrenia is getting worse

* Add missing lang key

* add property annotations
Testure authored May 23, 2024
1 parent 9f793ff commit 3de1eb2
Showing 13 changed files with 694 additions and 477 deletions.
99 changes: 99 additions & 0 deletions examples/postInit/tconstruct.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@

// Auto generated groovyscript example file
// MODS_LOADED: tconstruct

println 'mod \'tconstruct\' detected, running script'

// Alloying:
// Modifies what fluids can be mixed together in the Smeltery.

mods.tconstruct.alloying.removeByInputs(fluid('cobalt')*2,fluid('ardite')*2)
mods.tconstruct.alloying.removeByInputsAndOutput(fluid('knightslime')*72,fluid('iron')*72,fluid('stone')*144,fluid('purpleslime')*125)
mods.tconstruct.alloying.removeByOutput(fluid('pigiron'))
// mods.tconstruct.alloying.removeAll()

mods.tconstruct.alloying.recipeBuilder()
.fluidOutput(fluid('iron') * 3)
.fluidInput(fluid('clay') * 1,fluid('lava') * 2)
.register()


mods.tconstruct.alloying.add(fluid('lava') * 144, fluid('water') * 500, fluid('iron') * 5, fluid('clay') * 60)

// Casting Basin:
// Pours out fluid into a basin to solidify it into a solid, optionally with a cast itemstack.

mods.tconstruct.casting_basin.removeByCast(item('minecraft:planks:0'))
mods.tconstruct.casting_basin.removeByInput(fluid('clay'))
mods.tconstruct.casting_basin.removeByOutput(item('minecraft:iron_block'))
// mods.tconstruct.casting_basin.removeAll()

mods.tconstruct.casting_basin.recipeBuilder()
.fluidInput(fluid('water'))
.output(item('minecraft:dirt'))
.cast(item('minecraft:cobblestone'))
.coolingTime(40)
.register()


// Casting Table:
// Pours out fluid onto a table to solidify it into a solid, optionally with a cast itemstack.

mods.tconstruct.casting_table.removeByCast(item('minecraft:bucket'))
mods.tconstruct.casting_table.removeByInput(fluid('iron'))
mods.tconstruct.casting_table.removeByOutput(item('minecraft:gold_ingot'))
// mods.tconstruct.casting_table.removeAll()

mods.tconstruct.casting_table.recipeBuilder()
.fluidInput(fluid('lava') * 50)
.output(item('minecraft:diamond'))
.coolingTime(750)
.consumesCast(true)
.cast(ore('gemEmerald'))
.register()


// Drying Rack:
// Convert an item into a different item by hanging it out to dry.

// mods.tconstruct.drying.removeAll()

mods.tconstruct.drying.recipeBuilder()
.input(item('minecraft:clay'))
.output(item('minecraft:dirt'))
.time(45)
.register()



// Entity Melting:
// Allows mobs to create a bit of fluid when hurt by the Smeltery.

// mods.tconstruct.entity_melting.removeAll()

mods.tconstruct.entity_melting.recipeBuilder()
.fluidOutput(fluid('iron') * 500)
.input(resource('minecraft:pig'))
.register()


// Melting:
// Modifies what items can be melted down in the Smeltery.

// mods.tconstruct.melting.removeAll()

mods.tconstruct.melting.recipeBuilder()
.input(item('minecraft:gravel'))
.fluidOutput(fluid('lava') * 25)
.time(80)
.register()



// Smeltery Fuel:
// Modifies what fluids are accepted as fuels for the Smeltery and how long each fuels the Smeltery.

// mods.tconstruct.smeltery_fuel.removeAll()

mods.tconstruct.smeltery_fuel.addFuel(fluid('water'), 250)

24 changes: 0 additions & 24 deletions examples/postInit/tinkersconstruct.groovy

This file was deleted.

Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@

import com.cleanroommc.groovyscript.api.GroovyBlacklist;
import com.cleanroommc.groovyscript.api.GroovyLog;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.core.mixin.tconstruct.TinkerRegistryAccessor;
import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -13,8 +14,10 @@
import java.util.Arrays;
import java.util.List;

@RegistryDescription
public class Alloying extends VirtualizedRegistry<AlloyRecipe> {

@RecipeBuilderDescription(example = @Example(".fluidOutput(fluid('iron') * 3).fluidInput(fluid('clay') * 1,fluid('lava') * 2)"))
public RecipeBuilder recipeBuilder() {
return new RecipeBuilder();
}
@@ -26,6 +29,7 @@ public void onReload() {
restoreFromBackup().forEach(TinkerRegistryAccessor.getAlloyRegistry()::add);
}

@MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("fluid('lava') * 144, fluid('water') * 500, fluid('iron') * 5, fluid('clay') * 60"))
public AlloyRecipe add(FluidStack output, FluidStack... inputs) {
AlloyRecipe recipe = new AlloyRecipe(output, inputs);
add(recipe);
@@ -45,6 +49,7 @@ public boolean remove(AlloyRecipe recipe) {
return true;
}

@MethodDescription(example = @Example("fluid('pigiron')"))
public boolean removeByOutput(FluidStack output) {
if (TinkerRegistryAccessor.getAlloyRegistry().removeIf(recipe -> {
boolean found = recipe.getResult().isFluidEqual(output);
@@ -59,6 +64,7 @@ public boolean removeByOutput(FluidStack output) {
return false;
}

@MethodDescription(description = "groovyscript.wiki.tconstruct.alloying.removeByInputs", example = @Example("fluid('cobalt')*2,fluid('ardite')*2"))
public boolean removeByInputs(FluidStack... inputs) {
List<FluidStack> list = Arrays.asList(inputs);
if (TinkerRegistryAccessor.getAlloyRegistry().removeIf(recipe -> {
@@ -74,6 +80,7 @@ public boolean removeByInputs(FluidStack... inputs) {
return false;
}

@MethodDescription(example = @Example("fluid('knightslime')*72,fluid('iron')*72,fluid('stone')*144,fluid('purpleslime')*125"))
public boolean removeByInputsAndOutput(FluidStack output, FluidStack... inputs) {
List<FluidStack> list = Arrays.asList(inputs);
if (TinkerRegistryAccessor.getAlloyRegistry().removeIf(recipe -> {
@@ -89,15 +96,19 @@ public boolean removeByInputsAndOutput(FluidStack output, FluidStack... inputs)
return false;
}

@MethodDescription(priority = 2000, example = @Example(commented = true))
public void removeAll() {
TinkerRegistryAccessor.getAlloyRegistry().forEach(this::addBackup);
TinkerRegistryAccessor.getAlloyRegistry().forEach(TinkerRegistryAccessor.getAlloyRegistry()::remove);
TinkerRegistryAccessor.getAlloyRegistry().clear();
}

@MethodDescription(type = MethodDescription.Type.QUERY)
public SimpleObjectStream<AlloyRecipe> streamRecipes() {
return new SimpleObjectStream<>(TinkerRegistryAccessor.getAlloyRegistry()).setRemover(this::remove);
}

@Property(property = "fluidInput", valid = {@Comp(value = "2", type = Comp.Type.GTE), @Comp(value = "Integer.MAX_VALUE", type = Comp.Type.LTE)})
@Property(property = "fluidOutput", valid = @Comp("1"))
public class RecipeBuilder extends AbstractRecipeBuilder<AlloyRecipe> {

@Override
@@ -111,6 +122,7 @@ public void validate(GroovyLog.Msg msg) {
}

@Override
@RecipeBuilderRegistrationMethod
public @Nullable AlloyRecipe register() {
if (!validate()) return null;
AlloyRecipe recipe = new AlloyRecipe(fluidOutput.get(0), fluidInput.toArray(new FluidStack[0]));

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package com.cleanroommc.groovyscript.compat.mods.tinkersconstruct;

import com.cleanroommc.groovyscript.api.GroovyBlacklist;
import com.cleanroommc.groovyscript.api.GroovyLog;
import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.tinkersconstruct.recipe.MeltingRecipeBuilder;
import com.cleanroommc.groovyscript.core.mixin.tconstruct.TinkerRegistryAccessor;
import com.cleanroommc.groovyscript.helper.Alias;
import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import org.jetbrains.annotations.Nullable;
import slimeknights.tconstruct.library.smeltery.CastingRecipe;
import slimeknights.tconstruct.library.smeltery.ICastingRecipe;

@RegistryDescription
public class CastingBasin extends VirtualizedRegistry<ICastingRecipe> {

@RecipeBuilderDescription(example = @Example(".fluidInput(fluid('water')).output(item('minecraft:dirt')).cast(item('minecraft:cobblestone')).coolingTime(40)"))
public RecipeBuilder recipeBuilder() {
return new RecipeBuilder();
}

public CastingBasin() {
super(Alias.generateOfClass(CastingBasin.class).andGenerate("Basin"));
}

@Override
@GroovyBlacklist
public void onReload() {
removeScripted().forEach(TinkerRegistryAccessor.getBasinCastRegistry()::remove);
restoreFromBackup().forEach(TinkerRegistryAccessor.getBasinCastRegistry()::add);
}

public void add(ICastingRecipe recipe) {
if (recipe == null) return;
addScripted(recipe);
TinkerRegistryAccessor.getBasinCastRegistry().add(recipe);
}

public boolean remove(ICastingRecipe recipe) {
if (recipe == null) return false;
addBackup(recipe);
TinkerRegistryAccessor.getBasinCastRegistry().remove(recipe);
return true;
}

@MethodDescription(example = @Example("item('minecraft:iron_block')"))
public boolean removeByOutput(ItemStack output) {
if (TinkerRegistryAccessor.getBasinCastRegistry().removeIf(recipe -> {
boolean found = ItemStack.areItemStacksEqual(recipe.getResult(ItemStack.EMPTY, FluidRegistry.WATER), output);
if (found) addBackup(recipe);
return found;
})) return true;

GroovyLog.msg("Error removing Tinkers Construct Casting Basin recipe")
.add("could not find recipe with output {}", output)
.error()
.post();
return false;
}

@MethodDescription(example = @Example("fluid('clay')"))
public boolean removeByInput(FluidStack input) {
if (TinkerRegistryAccessor.getBasinCastRegistry().removeIf(recipe -> {
boolean found = recipe.getFluid(ItemStack.EMPTY, input.getFluid()).isFluidEqual(input);
if (found) addBackup(recipe);
return found;
})) return true;

GroovyLog.msg("Error removing Tinkers Construct Casting Basin recipe")
.add("could not find recipe with input {}", input)
.error()
.post();
return false;
}

@MethodDescription(example = @Example("item('minecraft:planks:0')"))
public boolean removeByCast(IIngredient cast) {
ItemStack castStack = cast.getMatchingStacks()[0];
if (TinkerRegistryAccessor.getBasinCastRegistry().removeIf(recipe -> {
boolean found = recipe.matches(castStack, recipe.getFluid(castStack, FluidRegistry.WATER).getFluid());
if (found) addBackup(recipe);
return found;
})) return true;

GroovyLog.msg("Error removing Tinkers Construct Casting Basin recipe")
.add("could not find recipe with cast {}", cast)
.error()
.post();
return false;
}

@MethodDescription(priority = 2000, example = @Example(commented = true))
public void removeAll() {
TinkerRegistryAccessor.getBasinCastRegistry().forEach(this::addBackup);
TinkerRegistryAccessor.getBasinCastRegistry().clear();
}

@MethodDescription(type = MethodDescription.Type.QUERY)
public SimpleObjectStream<ICastingRecipe> streamRecipes() {
return new SimpleObjectStream<>(TinkerRegistryAccessor.getBasinCastRegistry()).setRemover(this::remove);
}

@Property(property = "fluidInput", valid = @Comp("1"))
@Property(property = "output", valid = @Comp("1"))
public class RecipeBuilder extends AbstractRecipeBuilder<ICastingRecipe> {

@Property
private IIngredient cast;
@Property(defaultValue = "200", valid = @Comp(value = "1", type = Comp.Type.GTE))
private int time = 200;
@Property
private boolean consumesCast = false;

@RecipeBuilderMethodDescription(field = "time")
public RecipeBuilder coolingTime(int time) {
this.time = Math.max(time, 1);
return this;
}

@RecipeBuilderMethodDescription
public RecipeBuilder consumesCast(boolean consumesCast) {
this.consumesCast = consumesCast;
return this;
}

@RecipeBuilderMethodDescription
public RecipeBuilder consumesCast() {
return consumesCast(!consumesCast);
}

@RecipeBuilderMethodDescription
public RecipeBuilder cast(IIngredient ingredient) {
this.cast = ingredient;
return this;
}

@Override
public String getErrorMsg() {
return "Error adding Tinkers Construct Casting Basin recipe";
}

@Override
public void validate(GroovyLog.Msg msg) {
validateFluids(msg, 1, 1, 0, 0);
validateItems(msg, 0, 0, 1, 1);
}

@Override
@RecipeBuilderRegistrationMethod
public @Nullable ICastingRecipe register() {
if (!validate()) return null;
CastingRecipe recipe = new CastingRecipe(output.get(0), cast != null ? MeltingRecipeBuilder.recipeMatchFromIngredient(cast)
: null, fluidInput.get(0), time, consumesCast, false);
add(recipe);
return recipe;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package com.cleanroommc.groovyscript.compat.mods.tinkersconstruct;

import com.cleanroommc.groovyscript.api.GroovyBlacklist;
import com.cleanroommc.groovyscript.api.GroovyLog;
import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.tinkersconstruct.recipe.MeltingRecipeBuilder;
import com.cleanroommc.groovyscript.core.mixin.tconstruct.TinkerRegistryAccessor;
import com.cleanroommc.groovyscript.helper.Alias;
import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import org.jetbrains.annotations.Nullable;
import slimeknights.tconstruct.library.smeltery.CastingRecipe;
import slimeknights.tconstruct.library.smeltery.ICastingRecipe;

@RegistryDescription
public class CastingTable extends VirtualizedRegistry<ICastingRecipe> {

@RecipeBuilderDescription(example = @Example(".fluidInput(fluid('lava') * 50).output(item('minecraft:diamond')).coolingTime(750).consumesCast(true).cast(ore('gemEmerald'))"))
public RecipeBuilder recipeBuilder() {
return new RecipeBuilder();
}

public CastingTable() {
super(Alias.generateOfClass(CastingTable.class).andGenerate("Table"));
}

@Override
@GroovyBlacklist
public void onReload() {
removeScripted().forEach(TinkerRegistryAccessor.getTableCastRegistry()::remove);
restoreFromBackup().forEach(TinkerRegistryAccessor.getTableCastRegistry()::add);
}

public void add(ICastingRecipe recipe) {
if (recipe == null) return;
addScripted(recipe);
TinkerRegistryAccessor.getTableCastRegistry().add(recipe);
}

public boolean remove(ICastingRecipe recipe) {
if (recipe == null) return false;
addBackup(recipe);
TinkerRegistryAccessor.getTableCastRegistry().remove(recipe);
return true;
}

@MethodDescription(example = @Example("item('minecraft:gold_ingot')"))
public boolean removeByOutput(ItemStack output) {
if (TinkerRegistryAccessor.getTableCastRegistry().removeIf(recipe -> {
boolean found = recipe.getResult(ItemStack.EMPTY, FluidRegistry.WATER).isItemEqual(output);
if (found) addBackup(recipe);
return found;
})) return true;

GroovyLog.msg("Error removing Tinkers Construct Casting Table recipe")
.add("could not find recipe with output {}", output)
.error()
.post();
return false;
}

@MethodDescription(example = @Example("fluid('iron')"))
public boolean removeByInput(FluidStack input) {
if (TinkerRegistryAccessor.getTableCastRegistry().removeIf(recipe -> {
boolean found = recipe.getFluid(ItemStack.EMPTY, input.getFluid()).isFluidEqual(input);
if (found) addBackup(recipe);
return found;
})) return true;

GroovyLog.msg("Error removing Tinkers Construct Casting Table recipe")
.add("could not find recipe with input {}", input)
.error()
.post();
return false;
}

@MethodDescription(example = @Example("item('minecraft:bucket')"))
public boolean removeByCast(IIngredient cast) {
if (TinkerRegistryAccessor.getTableCastRegistry().removeIf(recipe -> {
boolean found = recipe.matches(cast.getMatchingStacks()[0], recipe.getFluid(cast.getMatchingStacks()[0], FluidRegistry.WATER).getFluid());
if (found) addBackup(recipe);
return found;
})) return true;

GroovyLog.msg("Error removing Tinkers Construct Casting Table recipe")
.add("could not find recipe with cast {}", cast)
.error()
.post();
return false;
}

@MethodDescription(priority = 2000, example = @Example(commented = true))
public void removeAll() {
TinkerRegistryAccessor.getTableCastRegistry().forEach(this::addBackup);
TinkerRegistryAccessor.getTableCastRegistry().clear();
}

@MethodDescription(type = MethodDescription.Type.QUERY)
public SimpleObjectStream<ICastingRecipe> streamRecipes() {
return new SimpleObjectStream<>(TinkerRegistryAccessor.getTableCastRegistry()).setRemover(this::remove);
}

@Property(property = "fluidInput", valid = @Comp("1"))
@Property(property = "output", valid = @Comp("1"))
public class RecipeBuilder extends AbstractRecipeBuilder<ICastingRecipe> {

@Property
private IIngredient cast;
@Property(defaultValue = "200", valid = @Comp(value = "1", type = Comp.Type.GTE))
private int time = 200;
@Property
private boolean consumesCast = false;

@RecipeBuilderMethodDescription(field = "time")
public RecipeBuilder coolingTime(int time) {
this.time = Math.max(time, 1);
return this;
}

@RecipeBuilderMethodDescription
public RecipeBuilder consumesCast(boolean consumesCast) {
this.consumesCast = consumesCast;
return this;
}

@RecipeBuilderMethodDescription
public RecipeBuilder consumesCast() {
return consumesCast(!consumesCast);
}

@RecipeBuilderMethodDescription
public RecipeBuilder cast(IIngredient ingredient) {
this.cast = ingredient;
return this;
}

@Override
public String getErrorMsg() {
return "Error adding Tinkers Construct Casting Table recipe";
}

@Override
public void validate(GroovyLog.Msg msg) {
validateFluids(msg, 1, 1, 0, 0);
validateItems(msg, 0, 0, 1, 1);
}

@Override
@RecipeBuilderRegistrationMethod
public @Nullable ICastingRecipe register() {
if (!validate()) return null;
CastingRecipe recipe = new CastingRecipe(output.get(0), cast != null ? MeltingRecipeBuilder.recipeMatchFromIngredient(cast)
: null, fluidInput.get(0), time, consumesCast, false);
add(recipe);
return recipe;
}
}
}
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
import com.cleanroommc.groovyscript.api.GroovyBlacklist;
import com.cleanroommc.groovyscript.api.GroovyLog;
import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.tinkersconstruct.recipe.MeltingRecipeBuilder;
import com.cleanroommc.groovyscript.core.mixin.tconstruct.TinkerRegistryAccessor;
import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
@@ -13,8 +14,10 @@
import org.jetbrains.annotations.Nullable;
import slimeknights.tconstruct.library.DryingRecipe;

@RegistryDescription
public class Drying extends VirtualizedRegistry<DryingRecipe> {

@RecipeBuilderDescription(example = @Example(".input(item('minecraft:clay')).output(item('minecraft:dirt')).time(45)"))
public RecipeBuilder recipeBuilder() {
return new RecipeBuilder();
}
@@ -26,6 +29,7 @@ public void onReload() {
restoreFromBackup().forEach(TinkerRegistryAccessor.getDryingRegistry()::add);
}

@MethodDescription(type = MethodDescription.Type.ADDITION)
public DryingRecipe add(IIngredient input, ItemStack output, int time) {
DryingRecipe recipe = new DryingRecipe(MeltingRecipeBuilder.recipeMatchFromIngredient(input), output, time);
add(recipe);
@@ -45,6 +49,7 @@ public boolean remove(DryingRecipe recipe) {
return true;
}

@MethodDescription
public boolean removeByInput(IIngredient input) {
NonNullList<ItemStack> matching = NonNullList.from(ItemStack.EMPTY, input.getMatchingStacks());
if (TinkerRegistryAccessor.getDryingRegistry().removeIf(recipe -> {
@@ -60,6 +65,7 @@ public boolean removeByInput(IIngredient input) {
return false;
}

@MethodDescription
public boolean removeByOutput(ItemStack output) {
if (TinkerRegistryAccessor.getDryingRegistry().removeIf(recipe -> {
boolean found = ItemStack.areItemStacksEqual(recipe.output, output);
@@ -74,6 +80,7 @@ public boolean removeByOutput(ItemStack output) {
return false;
}

@MethodDescription
public boolean removeByInputAndOutput(IIngredient input, ItemStack output) {
NonNullList<ItemStack> matching = NonNullList.from(ItemStack.EMPTY, input.getMatchingStacks());
if (TinkerRegistryAccessor.getDryingRegistry().removeIf(recipe -> {
@@ -89,19 +96,25 @@ public boolean removeByInputAndOutput(IIngredient input, ItemStack output) {
return false;
}

@MethodDescription(priority = 2000, example = @Example(commented = true))
public void removeAll() {
TinkerRegistryAccessor.getDryingRegistry().forEach(this::addBackup);
TinkerRegistryAccessor.getDryingRegistry().forEach(TinkerRegistryAccessor.getDryingRegistry()::remove);
TinkerRegistryAccessor.getDryingRegistry().clear();
}

@MethodDescription(type = MethodDescription.Type.QUERY)
public SimpleObjectStream<DryingRecipe> streamRecipes() {
return new SimpleObjectStream<>(TinkerRegistryAccessor.getDryingRegistry()).setRemover(this::remove);
}

@Property(property = "input", valid = @Comp("1"))
@Property(property = "output", valid = @Comp("1"))
public class RecipeBuilder extends AbstractRecipeBuilder<DryingRecipe> {

@Property(defaultValue = "20", valid = @Comp(value = "1", type = Comp.Type.GTE))
private int time = 20;

@RecipeBuilderMethodDescription
public RecipeBuilder time(int time) {
this.time = time;
return this;
@@ -119,6 +132,7 @@ public void validate(GroovyLog.Msg msg) {
}

@Override
@RecipeBuilderRegistrationMethod
public @Nullable DryingRecipe register() {
if (!validate()) return null;
DryingRecipe recipe = new DryingRecipe(MeltingRecipeBuilder.recipeMatchFromIngredient(input.get(0)), output.get(0), time);
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package com.cleanroommc.groovyscript.compat.mods.tinkersconstruct;

import com.cleanroommc.groovyscript.api.GroovyBlacklist;
import com.cleanroommc.groovyscript.api.GroovyLog;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.tinkersconstruct.recipe.EntityMeltingRecipe;
import com.cleanroommc.groovyscript.core.mixin.tconstruct.TinkerRegistryAccessor;
import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
import com.cleanroommc.groovyscript.helper.recipe.IRecipeBuilder;
import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
import net.minecraft.entity.EntityList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fml.common.registry.EntityEntry;
import org.jetbrains.annotations.Nullable;

import java.util.List;
import java.util.stream.Collectors;

@RegistryDescription
public class EntityMelting extends VirtualizedRegistry<EntityMeltingRecipe> {

@RecipeBuilderDescription(example = @Example(".fluidOutput(fluid('iron') * 500).input(resource('minecraft:pig'))"))
public RecipeBuilder recipeBuilder() {
return new RecipeBuilder();
}

@Override
@GroovyBlacklist
public void onReload() {
removeScripted().forEach(recipe -> TinkerRegistryAccessor.getEntityMeltingRegistry().remove(recipe.name, recipe.result));
restoreFromBackup().forEach(recipe -> TinkerRegistryAccessor.getEntityMeltingRegistry().put(recipe.name, recipe.result));
}

@MethodDescription(type = MethodDescription.Type.QUERY)
protected List<EntityMeltingRecipe> getAllRecipes() {
return TinkerRegistryAccessor.getEntityMeltingRegistry().entrySet().stream().map(EntityMeltingRecipe::fromMapEntry).collect(Collectors.toList());
}

public EntityMeltingRecipe add(EntityEntry entity, FluidStack output) {
EntityMeltingRecipe recipe = new EntityMeltingRecipe(entity, output);
add(recipe);
return recipe;
}

public void add(EntityMeltingRecipe recipe) {
if (recipe == null || recipe.name == null) return;
addScripted(recipe);
TinkerRegistryAccessor.getEntityMeltingRegistry().put(recipe.name, recipe.result);
}

public boolean remove(EntityMeltingRecipe recipe) {
if (recipe == null || recipe.name == null) return false;
addBackup(recipe);
TinkerRegistryAccessor.getEntityMeltingRegistry().remove(recipe.name, recipe.result);
return true;
}

@MethodDescription
public boolean removeByInput(EntityEntry entity) {
ResourceLocation name = entity.getRegistryName();
if (TinkerRegistryAccessor.getEntityMeltingRegistry().entrySet().removeIf(entry -> {
boolean found = entry.getKey().equals(name);
if (found) addBackup(new EntityMeltingRecipe(entry.getKey(), entry.getValue()));
return found;
})) return true;

GroovyLog.msg("Error removing Tinkers Construct Entity Melting recipe")
.add("could not find recipe with input {}", name)
.error()
.post();
return false;
}

@MethodDescription
public boolean removeByOutput(FluidStack output) {
if (TinkerRegistryAccessor.getEntityMeltingRegistry().entrySet().removeIf(entry -> {
boolean found = entry.getValue().isFluidEqual(output);
if (found) addBackup(new EntityMeltingRecipe(entry.getKey(), entry.getValue()));
return found;
})) return true;

GroovyLog.msg("Error removing Tinkers Construct Entity Melting recipe")
.add("could not find recipe with output {}", output)
.error()
.post();
return false;
}

@MethodDescription(priority = 2000, example = @Example(commented = true))
public void removeAll() {
TinkerRegistryAccessor.getEntityMeltingRegistry().forEach((name, result) -> addBackup(new EntityMeltingRecipe(name, result)));
TinkerRegistryAccessor.getEntityMeltingRegistry().clear();
}

@MethodDescription(description = "groovyscript.wiki.streamRecipes", type = MethodDescription.Type.QUERY)
public SimpleObjectStream<EntityMeltingRecipe> streamRecipes() {
return new SimpleObjectStream<>(getAllRecipes()).setRemover(this::remove);
}

public class RecipeBuilder implements IRecipeBuilder<EntityMeltingRecipe> {

@Property(valid = @Comp(value = "null", type = Comp.Type.NOT))
private FluidStack output;
@Property(valid = @Comp(value = "null", type = Comp.Type.NOT))
private ResourceLocation input;

@RecipeBuilderMethodDescription(field = "output")
public RecipeBuilder fluidOutput(FluidStack stack) {
this.output = stack;
return this;
}

@RecipeBuilderMethodDescription
public RecipeBuilder input(ResourceLocation name) {
this.input = name;
return this;
}

@RecipeBuilderMethodDescription
public RecipeBuilder input(String name) {
return input(new ResourceLocation(name));
}

@RecipeBuilderMethodDescription
public RecipeBuilder input(String modid, String name) {
return input(new ResourceLocation(modid, name));
}

@RecipeBuilderMethodDescription
public RecipeBuilder input(EntityEntry entity) {
return input(entity.getRegistryName());
}

private String getErrorMsg() {
return "Error adding Tinkers Construct Entity Melting recipe";
}

private void validate(GroovyLog.Msg msg) {
msg.add(input == null || EntityList.getClass(input) == null, "Expected valid entity name, got " + input);
msg.add(output == null || output.amount < 1, "Expected 1 output fluid but found none!");
}

@Override
public boolean validate() {
GroovyLog.Msg msg = GroovyLog.msg(this.getErrorMsg()).error();
this.validate(msg);
return !msg.postIfNotEmpty();
}

@Override
@RecipeBuilderRegistrationMethod
public @Nullable EntityMeltingRecipe register() {
if (!validate()) return null;
EntityMeltingRecipe recipe = new EntityMeltingRecipe(input, output);
add(recipe);
return recipe;
}
}
}
Original file line number Diff line number Diff line change
@@ -3,30 +3,23 @@
import com.cleanroommc.groovyscript.api.GroovyBlacklist;
import com.cleanroommc.groovyscript.api.GroovyLog;
import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.compat.mods.tinkersconstruct.recipe.EntityMeltingRecipe;
import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
import com.cleanroommc.groovyscript.api.documentation.annotations.RecipeBuilderDescription;
import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
import com.cleanroommc.groovyscript.compat.mods.tinkersconstruct.recipe.MeltingRecipeBuilder;
import com.cleanroommc.groovyscript.compat.mods.tinkersconstruct.recipe.MeltingRecipeRegistry;
import com.cleanroommc.groovyscript.core.mixin.tconstruct.TinkerRegistryAccessor;
import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
import com.cleanroommc.groovyscript.helper.recipe.IRecipeBuilder;
import com.cleanroommc.groovyscript.registry.AbstractReloadableStorage;
import com.cleanroommc.groovyscript.registry.VirtualizedRegistry;
import net.minecraft.entity.EntityList;
import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fml.common.registry.EntityEntry;
import org.jetbrains.annotations.Nullable;
import slimeknights.tconstruct.library.smeltery.MeltingRecipe;

import java.util.List;
import java.util.stream.Collectors;

@RegistryDescription
public class Melting extends MeltingRecipeRegistry {

public final EntityMelting entityMelting = new EntityMelting();

@RecipeBuilderDescription(example = @Example(".input(item('minecraft:gravel')).fluidOutput(fluid('lava') * 25).time(80)"))
public RecipeBuilder recipeBuilder() {
return new RecipeBuilder(this);
}
@@ -36,9 +29,9 @@ public RecipeBuilder recipeBuilder() {
public void onReload() {
removeScripted().forEach(TinkerRegistryAccessor.getMeltingRegistry()::remove);
restoreFromBackup().forEach(TinkerRegistryAccessor.getMeltingRegistry()::add);
entityMelting.onReload();
}

@MethodDescription(type = MethodDescription.Type.ADDITION)
public MeltingRecipe add(IIngredient input, FluidStack output, int temp) {
MeltingRecipe recipe = new MeltingRecipe(MeltingRecipeBuilder.recipeMatchFromIngredient(input, output.amount), output, temp);
add(recipe);
@@ -58,6 +51,7 @@ public boolean remove(MeltingRecipe recipe) {
return true;
}

@MethodDescription
public boolean removeByInput(IIngredient input) {
NonNullList<ItemStack> matching = NonNullList.from(ItemStack.EMPTY, input.getMatchingStacks());
if (TinkerRegistryAccessor.getMeltingRegistry().removeIf(recipe -> {
@@ -73,6 +67,7 @@ public boolean removeByInput(IIngredient input) {
return false;
}

@MethodDescription
public boolean removeByOutput(FluidStack output) {
if (TinkerRegistryAccessor.getMeltingRegistry().removeIf(recipe -> {
boolean found = recipe.getResult().isFluidEqual(output);
@@ -87,6 +82,7 @@ public boolean removeByOutput(FluidStack output) {
return false;
}

@MethodDescription
public boolean removeByInputAndOutput(IIngredient input, FluidStack output) {
NonNullList<ItemStack> matching = NonNullList.from(ItemStack.EMPTY, input.getMatchingStacks());
if (TinkerRegistryAccessor.getMeltingRegistry().removeIf(recipe -> {
@@ -102,11 +98,13 @@ public boolean removeByInputAndOutput(IIngredient input, FluidStack output) {
return false;
}

@MethodDescription(priority = 2000, example = @Example(commented = true))
public void removeAll() {
TinkerRegistryAccessor.getMeltingRegistry().forEach(this::addBackup);
TinkerRegistryAccessor.getMeltingRegistry().forEach(TinkerRegistryAccessor.getMeltingRegistry()::remove);
TinkerRegistryAccessor.getMeltingRegistry().clear();
}

@MethodDescription(type = MethodDescription.Type.QUERY)
public SimpleObjectStream<MeltingRecipe> streamRecipes() {
return new SimpleObjectStream<>(TinkerRegistryAccessor.getMeltingRegistry()).setRemover(this::remove);
}
@@ -117,143 +115,4 @@ public RecipeBuilder(Melting melting) {
super(melting, "Tinkers Construct Melting recipe");
}
}

public static class EntityMelting extends VirtualizedRegistry<EntityMeltingRecipe> {

@Override
@GroovyBlacklist
protected AbstractReloadableStorage<EntityMeltingRecipe> createRecipeStorage() {
return new AbstractReloadableStorage<>() {
@Override
@GroovyBlacklist
protected boolean compareRecipe(EntityMeltingRecipe recipe, EntityMeltingRecipe recipe2) {
return recipe.equals(recipe2);
}
};
}

public RecipeBuilder recipeBuilder() {
return new RecipeBuilder();
}

@Override
@GroovyBlacklist
public void onReload() {
removeScripted().forEach(recipe -> TinkerRegistryAccessor.getEntityMeltingRegistry().remove(recipe.name, recipe.result));
restoreFromBackup().forEach(recipe -> TinkerRegistryAccessor.getEntityMeltingRegistry().put(recipe.name, recipe.result));
}

protected List<EntityMeltingRecipe> getAllRecipes() {
return TinkerRegistryAccessor.getEntityMeltingRegistry().entrySet().stream().map(EntityMeltingRecipe::fromMapEntry).collect(Collectors.toList());
}

public EntityMeltingRecipe add(EntityEntry entity, FluidStack output) {
EntityMeltingRecipe recipe = new EntityMeltingRecipe(entity, output);
add(recipe);
return recipe;
}

public void add(EntityMeltingRecipe recipe) {
if (recipe == null || recipe.name == null) return;
addScripted(recipe);
TinkerRegistryAccessor.getEntityMeltingRegistry().put(recipe.name, recipe.result);
}

public boolean remove(EntityMeltingRecipe recipe) {
if (recipe == null || recipe.name == null) return false;
addBackup(recipe);
TinkerRegistryAccessor.getEntityMeltingRegistry().remove(recipe.name, recipe.result);
return true;
}

public boolean removeByInput(EntityEntry entity) {
ResourceLocation name = entity.getRegistryName();
if (TinkerRegistryAccessor.getEntityMeltingRegistry().entrySet().removeIf(entry -> {
boolean found = entry.getKey().equals(name);
if (found) addBackup(new EntityMeltingRecipe(entry.getKey(), entry.getValue()));
return found;
})) return true;

GroovyLog.msg("Error removing Tinkers Construct Entity Melting recipe")
.add("could not find recipe with input {}", name)
.error()
.post();
return false;
}

public boolean removeByOutput(FluidStack output) {
if (TinkerRegistryAccessor.getEntityMeltingRegistry().entrySet().removeIf(entry -> {
boolean found = entry.getValue().isFluidEqual(output);
if (found) addBackup(new EntityMeltingRecipe(entry.getKey(), entry.getValue()));
return found;
})) return true;

GroovyLog.msg("Error removing Tinkers Construct Entity Melting recipe")
.add("could not find recipe with output {}", output)
.error()
.post();
return false;
}

public void removeAll() {
TinkerRegistryAccessor.getEntityMeltingRegistry().forEach((name, result) -> addBackup(new EntityMeltingRecipe(name, result)));
TinkerRegistryAccessor.getEntityMeltingRegistry().forEach(TinkerRegistryAccessor.getEntityMeltingRegistry()::remove);
}

public SimpleObjectStream<EntityMeltingRecipe> streamRecipes() {
return new SimpleObjectStream<>(getAllRecipes()).setRemover(this::remove);
}

public class RecipeBuilder implements IRecipeBuilder<EntityMeltingRecipe> {

private FluidStack output;
private ResourceLocation input;

public RecipeBuilder fluidOutput(FluidStack stack) {
this.output = stack;
return this;
}

public RecipeBuilder input(ResourceLocation name) {
this.input = name;
return this;
}

public RecipeBuilder input(String name) {
return input(new ResourceLocation(name));
}

public RecipeBuilder input(String modid, String name) {
return input(new ResourceLocation(modid, name));
}

public RecipeBuilder input(EntityEntry entity) {
return input(entity.getRegistryName());
}

private String getErrorMsg() {
return "Error adding Tinkers Construct Entity Melting recipe";
}

private void validate(GroovyLog.Msg msg) {
msg.add(input == null || EntityList.getClass(input) == null, "Expected valid entity name, got " + input);
msg.add(output == null || output.amount < 1, "Expected 1 output fluid but found none!");
}

@Override
public boolean validate() {
GroovyLog.Msg msg = GroovyLog.msg(this.getErrorMsg()).error();
this.validate(msg);
return !msg.postIfNotEmpty();
}

@Override
public @Nullable EntityMeltingRecipe register() {
if (!validate()) return null;
EntityMeltingRecipe recipe = new EntityMeltingRecipe(input, output);
add(recipe);
return recipe;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -2,6 +2,9 @@

import com.cleanroommc.groovyscript.api.GroovyBlacklist;
import com.cleanroommc.groovyscript.api.GroovyLog;
import com.cleanroommc.groovyscript.api.documentation.annotations.Example;
import com.cleanroommc.groovyscript.api.documentation.annotations.MethodDescription;
import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
import com.cleanroommc.groovyscript.compat.mods.tinkersconstruct.recipe.SmelteryFuelRecipe;
import com.cleanroommc.groovyscript.core.mixin.tconstruct.TinkerRegistryAccessor;
import com.cleanroommc.groovyscript.helper.SimpleObjectStream;
@@ -12,6 +15,7 @@
import java.util.List;
import java.util.stream.Collectors;

@RegistryDescription(category = RegistryDescription.Category.ENTRIES)
public class SmelteryFuel extends VirtualizedRegistry<SmelteryFuelRecipe> {

@Override
@@ -37,12 +41,14 @@ protected List<SmelteryFuelRecipe> getAllRecipes() {
return TinkerRegistryAccessor.getSmelteryFuels().entrySet().stream().map(SmelteryFuelRecipe::fromMapEntry).collect(Collectors.toList());
}

@MethodDescription(type = MethodDescription.Type.ADDITION, example = @Example("fluid('water'), 250"))
public SmelteryFuelRecipe addFuel(FluidStack fluid, int duration) {
SmelteryFuelRecipe recipe = new SmelteryFuelRecipe(fluid, duration);
add(recipe);
return recipe;
}

@MethodDescription
public boolean removeFuel(FluidStack fluid) {
if (TinkerRegistryAccessor.getSmelteryFuels().entrySet().removeIf(entry -> {
boolean found = entry.getKey().isFluidEqual(fluid);
@@ -70,11 +76,13 @@ public boolean remove(SmelteryFuelRecipe recipe) {
return true;
}

@MethodDescription(priority = 2000, example = @Example(commented = true))
public void removeAll() {
TinkerRegistryAccessor.getSmelteryFuels().forEach((fluid, duration) -> addBackup(new SmelteryFuelRecipe(fluid, duration)));
TinkerRegistryAccessor.getSmelteryFuels().forEach(TinkerRegistryAccessor.getSmelteryFuels()::remove);
TinkerRegistryAccessor.getSmelteryFuels().clear();
}

@MethodDescription(type = MethodDescription.Type.QUERY)
public SimpleObjectStream<SmelteryFuelRecipe> streamRecipes() {
return new SimpleObjectStream<>(getAllRecipes()).setRemover(this::remove);
}
Original file line number Diff line number Diff line change
@@ -16,18 +16,21 @@ public class TinkersConstruct extends ModPropertyContainer {

public final Drying drying = new Drying();
public final Melting melting = new Melting();
public final EntityMelting entityMelting = new EntityMelting();
public final SmelteryFuel smelteryFuel = new SmelteryFuel();
public final Alloying alloying = new Alloying();
public final Casting casting = new Casting();
public final CastingTable castingTable = new CastingTable();
public final CastingBasin castingBasin = new CastingBasin();
public final Materials materials = new Materials();

public TinkersConstruct() {
addRegistry(drying);
addRegistry(melting);
addRegistry(entityMelting);
addRegistry(smelteryFuel);
addRegistry(alloying);
addRegistry(casting.table);
addRegistry(casting.basin);
addRegistry(castingTable);
addRegistry(castingBasin);
addRegistry(materials);
}

Original file line number Diff line number Diff line change
@@ -2,15 +2,21 @@

import com.cleanroommc.groovyscript.api.GroovyLog;
import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.Comp;
import com.cleanroommc.groovyscript.api.documentation.annotations.Property;
import com.cleanroommc.groovyscript.api.documentation.annotations.RecipeBuilderMethodDescription;
import com.cleanroommc.groovyscript.api.documentation.annotations.RecipeBuilderRegistrationMethod;
import com.cleanroommc.groovyscript.core.mixin.tconstruct.MeltingRecipeAccessor;
import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
import org.jetbrains.annotations.Nullable;
import slimeknights.mantle.util.RecipeMatch;
import slimeknights.tconstruct.library.smeltery.MeltingRecipe;

@Property(property = "input", valid = @Comp("1"))
public class MeltingRecipeBuilder extends AbstractRecipeBuilder<MeltingRecipe> {

@Property(defaultValue = "300", valid = @Comp(value = "1", type = Comp.Type.GTE))
private int temp = 300;
private final MeltingRecipeRegistry registry;
private final String recipeName;
@@ -29,11 +35,13 @@ public MeltingRecipeBuilder(MeltingRecipeRegistry registry, String recipeName) {
this.recipeName = recipeName;
}

@RecipeBuilderMethodDescription(field = "temp")
public MeltingRecipeBuilder temperature(int temp) {
this.temp = temp + 300;
return this;
}

@RecipeBuilderMethodDescription(field = "temp")
public MeltingRecipeBuilder time(int time) {
int t = fluidOutput.get(0) != null ? fluidOutput.get(0).getFluid().getTemperature() : 300;
this.temp = MeltingRecipeAccessor.invokeCalcTemperature(t, time);
@@ -53,6 +61,7 @@ public void validate(GroovyLog.Msg msg) {
}

@Override
@RecipeBuilderRegistrationMethod
public @Nullable MeltingRecipe register() {
if (!validate()) return null;
int amount = fluidOutput.get(0).amount;
43 changes: 43 additions & 0 deletions src/main/resources/assets/groovyscript/lang/en_us.lang
Original file line number Diff line number Diff line change
@@ -71,6 +71,7 @@ groovyscript.wiki.craftingrecipe.ingredients.value=Sets the items required for t

groovyscript.wiki.removeByInput=Removes all recipes that match the given input
groovyscript.wiki.removeByOutput=Removes all recipes that match the given output
groovyscript.wiki.removeByInputAndOutput=Removes all recipes that match the given input and the given output
groovyscript.wiki.removeByOre=Removes all recipes that match the given ore
groovyscript.wiki.removeByCatalyst=Removes all recipes that match the given catalyst
groovyscript.wiki.removeByInputAndCatalyst=This removes all recipes that match the given input and Catalyst
@@ -1358,6 +1359,48 @@ groovyscript.wiki.rustic.evaporating_basin.description=Converts fluids into item
groovyscript.wiki.rustic.evaporating_basin.time.value=Sets the time in ticks the recipe will take


# Tinkers
groovyscript.wiki.tconstruct.smeltery_fuel.title=Smeltery Fuel
groovyscript.wiki.tconstruct.smeltery_fuel.description=Modifies what fluids are accepted as fuels for the Smeltery and how long each fuels the Smeltery.
groovyscript.wiki.tconstruct.smeltery_fuel.addFuel=Adds the given fluid as a smeltery fuel with the given burn time
groovyscript.wiki.tconstruct.smeltery_fuel.removeFuel=Removes the given fluid from being a smeltery fuel

groovyscript.wiki.tconstruct.drying.title=Drying Rack
groovyscript.wiki.tconstruct.drying.description=Convert an item into a different item by hanging it out to dry.
groovyscript.wiki.tconstruct.drying.add=Adds a new recipe in the format `input`, `output`, `time`
groovyscript.wiki.tconstruct.drying.time.value=The time in ticks it takes for the item to dry

groovyscript.wiki.tconstruct.casting_table.title=Casting Table
groovyscript.wiki.tconstruct.casting_table.description=Pours out fluid onto a table to solidify it into a solid, optionally with a cast itemstack.
groovyscript.wiki.tconstruct.casting_table.removeByCast=Removes all recipes that use the given item as a cast
groovyscript.wiki.tconstruct.casting_table.cast.value=The item to use as a cast. null for no cast
groovyscript.wiki.tconstruct.casting_table.time.value=The time in ticks it takes for the recipe to complete
groovyscript.wiki.tconstruct.casting_table.consumesCast.value=Whether the cast item is destroyed

groovyscript.wiki.tconstruct.casting_basin.title=Casting Basin
groovyscript.wiki.tconstruct.casting_basin.description=Pours out fluid into a basin to solidify it into a solid, optionally with a cast itemstack.
groovyscript.wiki.tconstruct.casting_basin.removeByCast=Removes all recipes that use the given item as a cast
groovyscript.wiki.tconstruct.casting_basin.cast.value=The item to use as a cast. null for no cast
groovyscript.wiki.tconstruct.casting_basin.time.value=The time in ticks it takes for the recipe to complete
groovyscript.wiki.tconstruct.casting_basin.consumesCast.value=Whether the cast item is destroyed

groovyscript.wiki.tconstruct.melting.title=Melting
groovyscript.wiki.tconstruct.melting.description=Modifies what items can be melted down in the Smeltery.
groovyscript.wiki.tconstruct.melting.add=Adds a new recipe in the format `input`, `output`, `time`
groovyscript.wiki.tconstruct.melting.temp.value=Required temperature for melting. Also determines the speed of the melt

groovyscript.wiki.tconstruct.entity_melting.title=Entity Melting
groovyscript.wiki.tconstruct.entity_melting.description=Allows mobs to create a bit of fluid when hurt by the Smeltery.
groovyscript.wiki.tconstruct.entity_melting.input.value=The entity to melt
groovyscript.wiki.tconstruct.entity_melting.output.value=The fluid created each damage tick

groovyscript.wiki.tconstruct.alloying.title=Alloying
groovyscript.wiki.tconstruct.alloying.description=Modifies what fluids can be mixed together in the Smeltery.
groovyscript.wiki.tconstruct.alloying.add=Adds a new recipe in the format `output`, `inputs`
groovyscript.wiki.tconstruct.alloying.removeByInputsAndOutput=Removes all recipes that match the given output and the given inputs
groovyscript.wiki.tconstruct.alloying.removeByInputs=Removes all recipes that match the given inputs


# Thaumcraft
groovyscript.wiki.thaumcraft.arcane_workbench.title=Arcane Workbench
groovyscript.wiki.thaumcraft.arcane_workbench.description=A special crafting table, allowing additional requirements in the form of Vis Crystals, Vis, and having a specific research.

0 comments on commit 3de1eb2

Please sign in to comment.