mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-11-06 08:22:59 +00:00
Switch generation of resources over to data generators
See #354 - Remove Lua script to generate recipes/advancements for coloured disks, turtle upgrades and pocket upgrades. Replacing them with Lua ones. - Generate most block drops via the data generator system. Aside from cables, they all follow one of two templates.
This commit is contained in:
27
src/main/java/dan200/computercraft/data/Generators.java
Normal file
27
src/main/java/dan200/computercraft/data/Generators.java
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.data;
|
||||
|
||||
import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
|
||||
|
||||
@Mod.EventBusSubscriber( bus = Mod.EventBusSubscriber.Bus.MOD )
|
||||
public class Generators
|
||||
{
|
||||
@SubscribeEvent
|
||||
public static void gather( GatherDataEvent event )
|
||||
{
|
||||
ComputerCraftProxyCommon.registerLoot();
|
||||
|
||||
DataGenerator generator = event.getGenerator();
|
||||
generator.addProvider( new Recipes( generator ) );
|
||||
generator.addProvider( new LootTables( generator ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.data;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.DirectoryCache;
|
||||
import net.minecraft.data.IDataProvider;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.storage.loot.LootTable;
|
||||
import net.minecraft.world.storage.loot.LootTableManager;
|
||||
import net.minecraft.world.storage.loot.ValidationResults;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* An alternative to {@link net.minecraft.data.LootTableProvider}, with a more flexible interface.
|
||||
*/
|
||||
public abstract class LootTableProvider implements IDataProvider
|
||||
{
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
||||
|
||||
private final DataGenerator generator;
|
||||
|
||||
public LootTableProvider( DataGenerator generator )
|
||||
{
|
||||
this.generator = generator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act( @Nonnull DirectoryCache cache )
|
||||
{
|
||||
|
||||
ValidationResults validation = new ValidationResults();
|
||||
Map<ResourceLocation, LootTable> tables = new HashMap<>();
|
||||
registerLoot( ( id, table ) -> {
|
||||
if( tables.containsKey( id ) ) validation.addProblem( "Duplicate loot tables for " + id );
|
||||
tables.put( id, table );
|
||||
} );
|
||||
|
||||
tables.forEach( ( key, value ) -> LootTableManager.func_215302_a( validation, key, value, tables::get ) );
|
||||
|
||||
Multimap<String, String> problems = validation.getProblems();
|
||||
if( !problems.isEmpty() )
|
||||
{
|
||||
problems.forEach( ( child, problem ) ->
|
||||
ComputerCraft.log.warn( "Found validation problem in " + child + ": " + problem ) );
|
||||
throw new IllegalStateException( "Failed to validate loot tables, see logs" );
|
||||
}
|
||||
|
||||
tables.forEach( ( key, value ) -> {
|
||||
Path path = getPath( key );
|
||||
try
|
||||
{
|
||||
IDataProvider.save( GSON, cache, LootTableManager.toJson( value ), path );
|
||||
}
|
||||
catch( IOException e )
|
||||
{
|
||||
ComputerCraft.log.error( "Couldn't save loot table {}", path, e );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
protected abstract void registerLoot( BiConsumer<ResourceLocation, LootTable> add );
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "LootTables";
|
||||
}
|
||||
|
||||
private Path getPath( ResourceLocation id )
|
||||
{
|
||||
return generator.getOutputFolder()
|
||||
.resolve( "data" ).resolve( id.getNamespace() ).resolve( "loot_tables" )
|
||||
.resolve( id.getPath() + ".json" );
|
||||
}
|
||||
}
|
||||
72
src/main/java/dan200/computercraft/data/LootTables.java
Normal file
72
src/main/java/dan200/computercraft/data/LootTables.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.data;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.data.BlockNamedEntityLootCondition;
|
||||
import dan200.computercraft.shared.data.PlayerCreativeLootCondition;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.storage.loot.*;
|
||||
import net.minecraft.world.storage.loot.conditions.Alternative;
|
||||
import net.minecraft.world.storage.loot.conditions.SurvivesExplosion;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public class LootTables extends LootTableProvider
|
||||
{
|
||||
public LootTables( DataGenerator generator )
|
||||
{
|
||||
super( generator );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerLoot( BiConsumer<ResourceLocation, LootTable> add )
|
||||
{
|
||||
basicDrop( add, ComputerCraft.Blocks.diskDrive );
|
||||
basicDrop( add, ComputerCraft.Blocks.monitorNormal );
|
||||
basicDrop( add, ComputerCraft.Blocks.monitorAdvanced );
|
||||
basicDrop( add, ComputerCraft.Blocks.printer );
|
||||
basicDrop( add, ComputerCraft.Blocks.speaker );
|
||||
basicDrop( add, ComputerCraft.Blocks.wiredModemFull );
|
||||
basicDrop( add, ComputerCraft.Blocks.wirelessModemNormal );
|
||||
basicDrop( add, ComputerCraft.Blocks.wirelessModemAdvanced );
|
||||
|
||||
computerDrop( add, ComputerCraft.Blocks.computerNormal );
|
||||
computerDrop( add, ComputerCraft.Blocks.computerAdvanced );
|
||||
computerDrop( add, ComputerCraft.Blocks.turtleNormal );
|
||||
computerDrop( add, ComputerCraft.Blocks.turtleAdvanced );
|
||||
}
|
||||
|
||||
private static void basicDrop( BiConsumer<ResourceLocation, LootTable> add, Block block )
|
||||
{
|
||||
add.accept( block.getRegistryName(), LootTable
|
||||
.builder()
|
||||
.addLootPool( LootPool.builder()
|
||||
.name( "main" )
|
||||
.rolls( ConstantRange.of( 1 ) )
|
||||
.addEntry( ItemLootEntry.builder( block ) )
|
||||
.acceptCondition( SurvivesExplosion.builder() )
|
||||
).build() );
|
||||
}
|
||||
|
||||
private static void computerDrop( BiConsumer<ResourceLocation, LootTable> add, Block block )
|
||||
{
|
||||
add.accept( block.getRegistryName(), LootTable
|
||||
.builder()
|
||||
.addLootPool( LootPool.builder()
|
||||
.name( "main" )
|
||||
.rolls( ConstantRange.of( 1 ) )
|
||||
.addEntry( DynamicLootEntry.func_216162_a( new ResourceLocation( ComputerCraft.MOD_ID, "computer" ) ) )
|
||||
.acceptCondition( Alternative.builder(
|
||||
BlockNamedEntityLootCondition.builder(),
|
||||
PlayerCreativeLootCondition.builder().inverted()
|
||||
) )
|
||||
).build() );
|
||||
}
|
||||
}
|
||||
92
src/main/java/dan200/computercraft/data/RecipeWrapper.java
Normal file
92
src/main/java/dan200/computercraft/data/RecipeWrapper.java
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.data;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import net.minecraft.data.IFinishedRecipe;
|
||||
import net.minecraft.item.crafting.IRecipeSerializer;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.JSONUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Adapter for recipes which overrides the serializer and adds custom item NBT.
|
||||
*/
|
||||
public class RecipeWrapper implements IFinishedRecipe
|
||||
{
|
||||
private final IFinishedRecipe recipe;
|
||||
private final CompoundNBT resultData;
|
||||
private final IRecipeSerializer<?> serializer;
|
||||
|
||||
private RecipeWrapper( IFinishedRecipe recipe, CompoundNBT resultData, IRecipeSerializer<?> serializer )
|
||||
{
|
||||
this.resultData = resultData;
|
||||
this.recipe = recipe;
|
||||
this.serializer = serializer;
|
||||
}
|
||||
|
||||
public static Consumer<IFinishedRecipe> wrap( IRecipeSerializer<?> serializer, Consumer<IFinishedRecipe> original )
|
||||
{
|
||||
return x -> original.accept( new RecipeWrapper( x, null, serializer ) );
|
||||
}
|
||||
|
||||
public static Consumer<IFinishedRecipe> wrap( IRecipeSerializer<?> serializer, Consumer<IFinishedRecipe> original, CompoundNBT resultData )
|
||||
{
|
||||
return x -> original.accept( new RecipeWrapper( x, resultData, serializer ) );
|
||||
}
|
||||
|
||||
public static Consumer<IFinishedRecipe> wrap( IRecipeSerializer<?> serializer, Consumer<IFinishedRecipe> original, Consumer<CompoundNBT> resultData )
|
||||
{
|
||||
CompoundNBT tag = new CompoundNBT();
|
||||
resultData.accept( tag );
|
||||
return x -> original.accept( new RecipeWrapper( x, tag, serializer ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize( @Nonnull JsonObject jsonObject )
|
||||
{
|
||||
recipe.serialize( jsonObject );
|
||||
|
||||
if( resultData != null )
|
||||
{
|
||||
JsonObject object = JSONUtils.getJsonObject( jsonObject, "result" );
|
||||
object.addProperty( "nbt", resultData.toString() );
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ResourceLocation getID()
|
||||
{
|
||||
return recipe.getID();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IRecipeSerializer<?> getSerializer()
|
||||
{
|
||||
return serializer;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JsonObject getAdvancementJson()
|
||||
{
|
||||
return recipe.getAdvancementJson();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ResourceLocation getAdvancementID()
|
||||
{
|
||||
return recipe.getAdvancementID();
|
||||
}
|
||||
}
|
||||
141
src/main/java/dan200/computercraft/data/Recipes.java
Normal file
141
src/main/java/dan200/computercraft/data/Recipes.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.data;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.TurtleUpgrades;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory;
|
||||
import dan200.computercraft.shared.turtle.items.TurtleItemFactory;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
import dan200.computercraft.shared.util.ImpostorRecipe;
|
||||
import dan200.computercraft.shared.util.ImpostorShapelessRecipe;
|
||||
import net.minecraft.advancements.criterion.InventoryChangeTrigger;
|
||||
import net.minecraft.data.*;
|
||||
import net.minecraft.item.DyeColor;
|
||||
import net.minecraft.item.DyeItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.common.Tags;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Recipes extends RecipeProvider
|
||||
{
|
||||
public Recipes( DataGenerator generator )
|
||||
{
|
||||
super( generator );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerRecipes( @Nonnull Consumer<IFinishedRecipe> add )
|
||||
{
|
||||
diskColours( add );
|
||||
pocketUpgrades( add );
|
||||
turtleUpgrades( add );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a crafting recipe for a disk of every dye colour.
|
||||
*
|
||||
* @param add The callback to add recipes.
|
||||
*/
|
||||
private void diskColours( @Nonnull Consumer<IFinishedRecipe> add )
|
||||
{
|
||||
for( Colour colour : Colour.VALUES )
|
||||
{
|
||||
ShapelessRecipeBuilder
|
||||
.shapelessRecipe( ComputerCraft.Items.disk )
|
||||
.addIngredient( Tags.Items.DUSTS_REDSTONE )
|
||||
.addIngredient( Items.PAPER )
|
||||
.addIngredient( DyeItem.getItem( ofColour( colour ) ) )
|
||||
.setGroup( "computercraft:disk" )
|
||||
.addCriterion( "has_drive", InventoryChangeTrigger.Instance.forItems( ComputerCraft.Blocks.diskDrive ) )
|
||||
.build( RecipeWrapper.wrap(
|
||||
ImpostorShapelessRecipe.SERIALIZER, add,
|
||||
x -> x.putInt( "color", colour.getHex() )
|
||||
), new ResourceLocation( ComputerCraft.MOD_ID, "disk_" + (colour.ordinal() + 1) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a crafting recipe for each turtle upgrade.
|
||||
*
|
||||
* @param add The callback to add recipes.
|
||||
*/
|
||||
private void turtleUpgrades( @Nonnull Consumer<IFinishedRecipe> add )
|
||||
{
|
||||
for( ComputerFamily family : ComputerFamily.values() )
|
||||
{
|
||||
ItemStack base = TurtleItemFactory.create( -1, null, -1, family, null, null, 0, null );
|
||||
if( base.isEmpty() ) continue;
|
||||
|
||||
String nameId = family.name().toLowerCase( Locale.ROOT );
|
||||
|
||||
TurtleUpgrades.getVanillaUpgrades().forEach( upgrade -> {
|
||||
ItemStack result = TurtleItemFactory.create( -1, null, -1, family, null, upgrade, -1, null );
|
||||
ShapedRecipeBuilder
|
||||
.shapedRecipe( result.getItem() )
|
||||
.setGroup( String.format( "%s:turtle_%s", ComputerCraft.MOD_ID, nameId ) )
|
||||
.patternLine( "#T" )
|
||||
.key( '#', base.getItem() )
|
||||
.key( 'T', upgrade.getCraftingItem().getItem() )
|
||||
.addCriterion( "has_items",
|
||||
InventoryChangeTrigger.Instance.forItems( base.getItem(), upgrade.getCraftingItem().getItem() ) )
|
||||
.build(
|
||||
RecipeWrapper.wrap( ImpostorRecipe.SERIALIZER, add, result.getTag() ),
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, String.format( "turtle_%s/%s/%s",
|
||||
nameId, upgrade.getUpgradeID().getNamespace(), upgrade.getUpgradeID().getPath()
|
||||
) )
|
||||
);
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a crafting recipe for each pocket upgrade.
|
||||
*
|
||||
* @param add The callback to add recipes.
|
||||
*/
|
||||
private void pocketUpgrades( @Nonnull Consumer<IFinishedRecipe> add )
|
||||
{
|
||||
for( ComputerFamily family : ComputerFamily.values() )
|
||||
{
|
||||
ItemStack base = PocketComputerItemFactory.create( -1, null, -1, family, null );
|
||||
if( base.isEmpty() ) continue;
|
||||
|
||||
String nameId = family.name().toLowerCase( Locale.ROOT );
|
||||
|
||||
TurtleUpgrades.getVanillaUpgrades().forEach( upgrade -> {
|
||||
ItemStack result = PocketComputerItemFactory.create( -1, null, -1, family, null );
|
||||
ShapedRecipeBuilder
|
||||
.shapedRecipe( result.getItem() )
|
||||
.setGroup( String.format( "%s:pocket_%s", ComputerCraft.MOD_ID, nameId ) )
|
||||
.patternLine( "#" )
|
||||
.patternLine( "P" )
|
||||
.key( '#', base.getItem() )
|
||||
.key( 'P', upgrade.getCraftingItem().getItem() )
|
||||
.addCriterion( "has_items",
|
||||
InventoryChangeTrigger.Instance.forItems( base.getItem(), upgrade.getCraftingItem().getItem() ) )
|
||||
.build(
|
||||
RecipeWrapper.wrap( ImpostorRecipe.SERIALIZER, add, result.getTag() ),
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, String.format( "pocket_%s/%s/%s",
|
||||
nameId, upgrade.getUpgradeID().getNamespace(), upgrade.getUpgradeID().getPath()
|
||||
) )
|
||||
);
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
private static DyeColor ofColour( Colour colour )
|
||||
{
|
||||
return DyeColor.byId( 15 - colour.ordinal() );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user