1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-11-06 16:33:00 +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:
SquidDev
2020-01-29 16:41:26 +00:00
parent bf6d017ad1
commit d6ea3aab1c
211 changed files with 3495 additions and 1511 deletions

View 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 ) );
}
}

View File

@@ -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" );
}
}

View 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() );
}
}

View 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();
}
}

View 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() );
}
}

View File

@@ -40,4 +40,9 @@ public final class BlockNamedEntityLootCondition implements ILootCondition
{
return Collections.singleton( LootParameters.BLOCK_ENTITY );
}
public static IBuilder builder()
{
return () -> INSTANCE;
}
}

View File

@@ -40,4 +40,9 @@ public final class PlayerCreativeLootCondition implements ILootCondition
{
return Collections.singleton( LootParameters.THIS_ENTITY );
}
public static IBuilder builder()
{
return () -> INSTANCE;
}
}

View File

@@ -47,14 +47,20 @@ import net.minecraftforge.fml.event.server.FMLServerStoppedEvent;
public final class ComputerCraftProxyCommon
{
@SubscribeEvent
@SuppressWarnings( "deprecation" )
public static void init( FMLCommonSetupEvent event )
{
NetworkHandler.setup();
registerProviders();
ArgumentSerializers.register();
net.minecraftforge.fml.DeferredWorkQueue.runLater( () -> {
registerProviders();
ArgumentSerializers.register();
registerLoot();
} );
}
public static void registerLoot()
{
LootConditionManager.registerCondition( ConstantLootConditionSerializer.of(
new ResourceLocation( ComputerCraft.MOD_ID, "block_named" ),
BlockNamedEntityLootCondition.class,