diff --git a/src/main/java/net/dries007/tfc/ConfigTFC.java b/src/main/java/net/dries007/tfc/ConfigTFC.java index 095f0eafbf..8a4e77eb17 100644 --- a/src/main/java/net/dries007/tfc/ConfigTFC.java +++ b/src/main/java/net/dries007/tfc/ConfigTFC.java @@ -201,6 +201,40 @@ public static class GeneralCFG @Config.RangeInt(min = 1, max = 10_000) public int richOreMetalAmount = 35; + @Config.Comment("The amount of times a chunk can be worked. Note: While sluices increase work by 1, Goldpan increase by 6.") + @Config.LangKey("config." + MOD_ID + ".general.maxWorkChunk") + @Config.RangeInt(min = 1, max = 10_000) + public int maxWorkChunk = 300; + + @Config.Comment("The radius sluice works on chunks.") + @Config.LangKey("config." + MOD_ID + ".general.sluiceRadius") + @Config.RangeInt(min = 0, max = 10) + public int sluiceRadius = 1; + + @Config.Comment("The amount of ticks a sluice uses to work.") + @Config.LangKey("config." + MOD_ID + ".general.sluiceTicks") + @Config.RangeInt(min = 20) + public int sluiceTicks = 100; + + @Config.Comment("Chance that a sluice operation produce small ore.") + @Config.RangeDouble(min = 0, max = 1) + @Config.LangKey("config." + MOD_ID + ".general.sluiceOreChance") + public double sluiceOreChance = 0.05; + + @Config.Comment("Chance that a sluice operation produce gems.") + @Config.RangeDouble(min = 0, max = 1) + @Config.LangKey("config." + MOD_ID + ".general.sluiceGemChance") + public double sluiceGemChance = 0.05; + + @Config.Comment("Chance that a diamond is dropped when sluice produce gems.") + @Config.RangeDouble(min = 0, max = 1) + @Config.LangKey("config." + MOD_ID + ".general.sluiceDiamondGemChance") + public double sluiceDiamondGemChance = 0.01; + + @Config.Comment("If true, limits for gold pan and sluice are ignored.") + @Config.LangKey("config." + MOD_ID + ".general.overworkChunk") + public boolean overworkChunk = false; + @Config.Comment({"If true, this will force the gamerule naturalRegeneration to be false. ", "Note: this DOES NOT AFFECT TFC's natural regeneration. If you set naturalRegeneration to true, then you will have both TFC regeneration and normal vanilla regeneration (which is much faster)"}) @Config.LangKey("config." + MOD_ID + ".general.forceNoVanillaNaturalRegeneration") public boolean forceNoVanillaNaturalRegeneration = true; diff --git a/src/main/java/net/dries007/tfc/api/types/Ore.java b/src/main/java/net/dries007/tfc/api/types/Ore.java index 92b97a5cb5..ce0ffa9649 100644 --- a/src/main/java/net/dries007/tfc/api/types/Ore.java +++ b/src/main/java/net/dries007/tfc/api/types/Ore.java @@ -23,6 +23,7 @@ public class Ore extends IForgeRegistryEntry.Impl private final boolean graded; private final Metal metal; private final boolean canMelt; + private final double chunkChance, panChance; /** * Creates a registry object for an ore type @@ -30,29 +31,43 @@ public class Ore extends IForgeRegistryEntry.Impl * @param name The registry name of the ore * @param metal The metal, or null if it's a non-metal ore * @param canMelt If the metal can be melted directly from the ore + * @param chunkChance the chance a chunk contains this ore when gold panning. + * @param panChance the chance to drop this ore when gold panning */ - public Ore(ResourceLocation name, @Nullable Metal metal, boolean canMelt) + public Ore(ResourceLocation name, @Nullable Metal metal, boolean canMelt, double chunkChance, double panChance) { this.graded = (metal != null); this.metal = metal; this.canMelt = canMelt; + this.chunkChance = chunkChance; + this.panChance = panChance; setRegistryName(name); } - public Ore(ResourceLocation name, @Nonnull ResourceLocation metal, boolean canMelt) + public Ore(ResourceLocation name, @Nonnull ResourceLocation metal, boolean canMelt, double chunkChance, double panChance) { - this(name, TFCRegistries.METALS.getValue(metal), canMelt); + this(name, TFCRegistries.METALS.getValue(metal), canMelt, chunkChance, panChance); } public Ore(ResourceLocation name, @Nonnull ResourceLocation metal) { - this(name, TFCRegistries.METALS.getValue(metal), true); + this(name, TFCRegistries.METALS.getValue(metal), true, 0, 0); + } + + public Ore(ResourceLocation name, @Nonnull ResourceLocation metal, boolean canMelt) + { + this(name, TFCRegistries.METALS.getValue(metal), canMelt, 0, 0); + } + + public Ore(ResourceLocation name, @Nonnull ResourceLocation metal, double chunkChance, double panChance) + { + this(name, TFCRegistries.METALS.getValue(metal), true, chunkChance, panChance); } public Ore(ResourceLocation name) { - this(name, (Metal) null, false); + this(name, (Metal) null, false, 0, 0); } public boolean isGraded() @@ -60,6 +75,21 @@ public boolean isGraded() return graded; } + public boolean canPan() + { + return chunkChance > 0; + } + + public double getPanChance() + { + return panChance; + } + + public double getChunkChance() + { + return chunkChance; + } + @Nullable public Metal getMetal() { diff --git a/src/main/java/net/dries007/tfc/client/ClientRegisterEvents.java b/src/main/java/net/dries007/tfc/client/ClientRegisterEvents.java index 4d1c585923..5fd4c72357 100644 --- a/src/main/java/net/dries007/tfc/client/ClientRegisterEvents.java +++ b/src/main/java/net/dries007/tfc/client/ClientRegisterEvents.java @@ -236,6 +236,7 @@ public ModelResourceLocation getModelLocation(@Nonnull ItemStack stack) ClientRegistry.bindTileEntitySpecialRenderer(TEAnvilTFC.class, new TESRAnvil()); ClientRegistry.bindTileEntitySpecialRenderer(TELoom.class, new TESRLoom()); ClientRegistry.bindTileEntitySpecialRenderer(TECrucible.class, new TESRCrucible()); + ClientRegistry.bindTileEntitySpecialRenderer(TESluice.class, new TESRSluice()); } @SubscribeEvent diff --git a/src/main/java/net/dries007/tfc/client/FluidSpriteCache.java b/src/main/java/net/dries007/tfc/client/FluidSpriteCache.java index 15ce4f8075..7b2e7e2dcc 100644 --- a/src/main/java/net/dries007/tfc/client/FluidSpriteCache.java +++ b/src/main/java/net/dries007/tfc/client/FluidSpriteCache.java @@ -14,16 +14,30 @@ public class FluidSpriteCache { - private static final Map CACHE = new HashMap<>(); + private static final Map CACHESTILL = new HashMap<>(); + private static final Map CACHEFLOWING = new HashMap<>(); - public static TextureAtlasSprite getSprite(Fluid fluid) + public static TextureAtlasSprite getStillSprite(Fluid fluid) { - TextureAtlasSprite sprite = CACHE.get(fluid); + TextureAtlasSprite sprite = CACHESTILL.get(fluid); if (sprite == null) { sprite = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(fluid.getStill().toString()); - CACHE.put(fluid, sprite); + CACHESTILL.put(fluid, sprite); + } + + return sprite; + } + + public static TextureAtlasSprite getFlowingSprite(Fluid fluid) + { + TextureAtlasSprite sprite = CACHEFLOWING.get(fluid); + + if (sprite == null) + { + sprite = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(fluid.getFlowing().toString()); + CACHEFLOWING.put(fluid, sprite); } return sprite; @@ -31,6 +45,7 @@ public static TextureAtlasSprite getSprite(Fluid fluid) public static void clear() { - CACHE.clear(); + CACHEFLOWING.clear(); + CACHESTILL.clear(); } } diff --git a/src/main/java/net/dries007/tfc/client/gui/GuiBarrel.java b/src/main/java/net/dries007/tfc/client/gui/GuiBarrel.java index e4f0f855b0..0e5aa7e486 100644 --- a/src/main/java/net/dries007/tfc/client/gui/GuiBarrel.java +++ b/src/main/java/net/dries007/tfc/client/gui/GuiBarrel.java @@ -158,7 +158,7 @@ protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, i if (fillHeightPixels > 0) { Fluid fluid = fs.getFluid(); - TextureAtlasSprite sprite = FluidSpriteCache.getSprite(fluid); + TextureAtlasSprite sprite = FluidSpriteCache.getStillSprite(fluid); int positionX = guiLeft + 8; int positionY = guiTop + 54; diff --git a/src/main/java/net/dries007/tfc/client/render/TESRBarrel.java b/src/main/java/net/dries007/tfc/client/render/TESRBarrel.java index 52a351ed9f..bec957abea 100644 --- a/src/main/java/net/dries007/tfc/client/render/TESRBarrel.java +++ b/src/main/java/net/dries007/tfc/client/render/TESRBarrel.java @@ -68,7 +68,7 @@ public void render(TEBarrel te, double x, double y, double z, float partialTicks { Fluid fluid = fluidStack.getFluid(); - TextureAtlasSprite sprite = FluidSpriteCache.getSprite(fluid); + TextureAtlasSprite sprite = FluidSpriteCache.getStillSprite(fluid); GlStateManager.enableAlpha(); GlStateManager.enableBlend(); diff --git a/src/main/java/net/dries007/tfc/client/render/TESRCrucible.java b/src/main/java/net/dries007/tfc/client/render/TESRCrucible.java index e2aa019de4..5275de02ef 100644 --- a/src/main/java/net/dries007/tfc/client/render/TESRCrucible.java +++ b/src/main/java/net/dries007/tfc/client/render/TESRCrucible.java @@ -39,7 +39,7 @@ public void render(TECrucible te, double x, double y, double z, float partialTic GlStateManager.pushMatrix(); GlStateManager.translate(x, y, z); - TextureAtlasSprite sprite = FluidSpriteCache.getSprite(metalFluid); + TextureAtlasSprite sprite = FluidSpriteCache.getStillSprite(metalFluid); GlStateManager.enableAlpha(); GlStateManager.enableBlend(); diff --git a/src/main/java/net/dries007/tfc/client/render/TESRSluice.java b/src/main/java/net/dries007/tfc/client/render/TESRSluice.java new file mode 100644 index 0000000000..83a36f59e1 --- /dev/null +++ b/src/main/java/net/dries007/tfc/client/render/TESRSluice.java @@ -0,0 +1,114 @@ +/* + * Work under Copyright. Licensed under the EUPL. + * See the project README.md and LICENSE.txt for more information. + */ + +package net.dries007.tfc.client.render; + +import org.lwjgl.opengl.GL11; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.fluids.Fluid; + +import net.dries007.tfc.client.FluidSpriteCache; +import net.dries007.tfc.objects.te.TESluice; + +public class TESRSluice extends TileEntitySpecialRenderer +{ + @Override + public void render(TESluice te, double x, double y, double z, float partialTicks, int destroyStage, float alpha) + { + Fluid flowing = te.getFlowingFluid(); + if (flowing == null) return; + + GlStateManager.pushMatrix(); + GlStateManager.translate(x, y, z); + + EnumFacing facing = te.getBlockFacing(); + //noinspection ConstantConditions + switch (facing) + { + case WEST: + GlStateManager.translate(0, 0, 1); + GlStateManager.rotate(90F, 0, 1, 0); + break; + case SOUTH: + GlStateManager.translate(1, 0, 1); + GlStateManager.rotate(180F, 0, 1, 0); + break; + case EAST: + GlStateManager.translate(1, 0, 0); + GlStateManager.rotate(270F, 0, 1, 0); + break; + default: + } + + + TextureAtlasSprite sprite = FluidSpriteCache.getFlowingSprite(flowing); + + GlStateManager.enableAlpha(); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + + int color = flowing.getColor(); + + float r = ((color >> 16) & 0xFF) / 255F; + float g = ((color >> 8) & 0xFF) / 255F; + float b = (color & 0xFF) / 255F; + float a = ((color >> 24) & 0xFF) / 255F; + + GlStateManager.color(r, g, b, a); + + rendererDispatcher.renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); + + BufferBuilder buffer = Tessellator.getInstance().getBuffer(); + + //Top + buffer.begin(GL11.GL_POLYGON, DefaultVertexFormats.POSITION_TEX_NORMAL); + + buffer.pos(0.05D, 1.033D, 0).tex(sprite.getMinU(), sprite.getMinV()).normal(0, 0, 1).endVertex(); + buffer.pos(0.05D, -0.15D, 2.45D).tex(sprite.getMinU(), sprite.getMaxV()).normal(0, 0, 1).endVertex(); + buffer.pos(0.95D, -0.15D, 2.45D).tex(sprite.getMaxU(), sprite.getMaxV()).normal(0, 0, 1).endVertex(); + buffer.pos(0.95D, 1.033D, 0).tex(sprite.getMaxU(), sprite.getMinV()).normal(0, 0, 1).endVertex(); + + Tessellator.getInstance().draw(); + + //Bottom + buffer.begin(GL11.GL_POLYGON, DefaultVertexFormats.POSITION_TEX_NORMAL); + + buffer.pos(0.05D, 0.833D, 0).tex(sprite.getMinU(), sprite.getMinV()).normal(0, 0, 1).endVertex(); + buffer.pos(0.05D, -0.3D, 2.45D).tex(sprite.getMinU(), sprite.getMaxV()).normal(0, 0, 1).endVertex(); + buffer.pos(0.95D, -0.3D, 2.45D).tex(sprite.getMaxU(), sprite.getMaxV()).normal(0, 0, 1).endVertex(); + buffer.pos(0.95D, 0.833D, 0).tex(sprite.getMaxU(), sprite.getMinV()).normal(0, 0, 1).endVertex(); + + Tessellator.getInstance().draw(); + + //Left + buffer.begin(GL11.GL_POLYGON, DefaultVertexFormats.POSITION_TEX_NORMAL); + + buffer.pos(0.05D, -0.15D, 2.45D).tex(sprite.getMinU(), sprite.getMaxV()).normal(0, 0, 1).endVertex(); + buffer.pos(0.05D, 1.033D, 0).tex(sprite.getMinU(), sprite.getMinV()).normal(0, 0, 1).endVertex(); + buffer.pos(0.05D, 0.833D, 0).tex(sprite.getMaxU(), sprite.getMinV()).normal(0, 0, 1).endVertex(); + buffer.pos(0.05D, -0.3D, 2.45D).tex(sprite.getMaxU(), sprite.getMaxV()).normal(0, 0, 1).endVertex(); + + Tessellator.getInstance().draw(); + + //Right + buffer.begin(GL11.GL_POLYGON, DefaultVertexFormats.POSITION_TEX_NORMAL); + + buffer.pos(0.95D, 1.033D, 0).tex(sprite.getMinU(), sprite.getMinV()).normal(0, 0, 1).endVertex(); + buffer.pos(0.95D, -0.15D, 2.45D).tex(sprite.getMinU(), sprite.getMaxV()).normal(0, 0, 1).endVertex(); + buffer.pos(0.95D, -0.3D, 2.45D).tex(sprite.getMaxU(), sprite.getMaxV()).normal(0, 0, 1).endVertex(); + buffer.pos(0.95D, 0.833D, 0).tex(sprite.getMaxU(), sprite.getMinV()).normal(0, 0, 1).endVertex(); + + Tessellator.getInstance().draw(); + + GlStateManager.popMatrix(); + } +} diff --git a/src/main/java/net/dries007/tfc/command/CommandFindVeins.java b/src/main/java/net/dries007/tfc/command/CommandFindVeins.java index cd44e8991f..888239f243 100644 --- a/src/main/java/net/dries007/tfc/command/CommandFindVeins.java +++ b/src/main/java/net/dries007/tfc/command/CommandFindVeins.java @@ -7,18 +7,24 @@ import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Set; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import com.google.common.collect.ImmutableSet; import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; import net.minecraft.command.WrongUsageException; import net.minecraft.server.MinecraftServer; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; import net.minecraft.util.text.TextComponentString; +import net.dries007.tfc.api.types.Ore; +import net.dries007.tfc.util.Helpers; import net.dries007.tfc.world.classic.worldgen.WorldGenOreVeins; import net.dries007.tfc.world.classic.worldgen.vein.Vein; import net.dries007.tfc.world.classic.worldgen.vein.VeinRegistry; @@ -38,7 +44,7 @@ public String getName() @Nonnull public String getUsage(ICommandSender sender) { - return "/findveins [all|] -> Finds all instances of a specific vein, or all veins within a certian chunk radius"; + return "/findveins [all|] -> Finds all instances of a specific vein, or all veins within a certain chunk radius"; } @Override @@ -51,6 +57,7 @@ public void execute(MinecraftServer server, ICommandSender sender, String[] args final int radius = parseInt(args[1], 1, 1000); final List veins = WorldGenOreVeins.getNearbyVeins(sender.getCommandSenderEntity().chunkCoordX, sender.getCommandSenderEntity().chunkCoordZ, sender.getEntityWorld().getSeed(), radius); + final Map> map = Helpers.getChunkOres(sender.getEntityWorld(), sender.getCommandSenderEntity().chunkCoordX, sender.getCommandSenderEntity().chunkCoordZ, radius); if (!args[0].equals("all")) { final VeinType type = VeinRegistry.INSTANCE.getVein(args[0]); @@ -61,6 +68,7 @@ public void execute(MinecraftServer server, ICommandSender sender, String[] args // Search for veins matching type veins.removeIf(x -> x.type != type); } + veins.removeIf(x -> !map.getOrDefault(new ChunkPos(x.pos), ImmutableSet.of()).contains(x.type.ore)); //Check if the vein generated veins.forEach(x -> sender.sendMessage(new TextComponentString("> Vein: " + x.type + " at " + x.pos))); } diff --git a/src/main/java/net/dries007/tfc/objects/blocks/BlocksTFC.java b/src/main/java/net/dries007/tfc/objects/blocks/BlocksTFC.java index cd6e664364..266d28bedd 100644 --- a/src/main/java/net/dries007/tfc/objects/blocks/BlocksTFC.java +++ b/src/main/java/net/dries007/tfc/objects/blocks/BlocksTFC.java @@ -286,6 +286,7 @@ public static void registerBlocks(RegistryEvent.Register event) inventoryItemBlocks.add(new ItemBlockTFC(register(r, "bellows", new BlockBellows(), CT_MISC))); inventoryItemBlocks.add(new ItemBlockTFC(register(r, "bloomery", new BlockBloomery(), CT_MISC))); inventoryItemBlocks.add(new ItemBlockTFC(register(r, "nest_box", new BlockNestBox(), CT_MISC))); + inventoryItemBlocks.add(new ItemBlockSluice(register(r, "sluice", new BlockSluice(), CT_MISC))); normalItemBlocks.add(new ItemBlockTFC(register(r, "sea_ice", new BlockIceTFC(FluidsTFC.SALT_WATER.get()), CT_MISC))); @@ -632,6 +633,7 @@ public static void registerBlocks(RegistryEvent.Register event) register(TEMetalSheet.class, "metal_sheet"); register(TEQuern.class, "quern"); register(TELargeVessel.class, "large_vessel"); + register(TESluice.class, "sluice"); } public static boolean isWater(IBlockState current) diff --git a/src/main/java/net/dries007/tfc/objects/blocks/devices/BlockSluice.java b/src/main/java/net/dries007/tfc/objects/blocks/devices/BlockSluice.java new file mode 100644 index 0000000000..7bd9c82ecb --- /dev/null +++ b/src/main/java/net/dries007/tfc/objects/blocks/devices/BlockSluice.java @@ -0,0 +1,130 @@ +/* + * Work under Copyright. Licensed under the EUPL. + * See the project README.md and LICENSE.txt for more information. + */ + +package net.dries007.tfc.objects.blocks.devices; + +import java.util.Random; +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockHorizontal; +import net.minecraft.block.material.Material; +import net.minecraft.block.properties.PropertyBool; +import net.minecraft.block.state.BlockStateContainer; +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fluids.BlockFluidBase; + +import mcp.MethodsReturnNonnullByDefault; +import net.dries007.tfc.objects.te.TESluice; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public class BlockSluice extends BlockHorizontal +{ + public static final PropertyBool UPPER = PropertyBool.create("upper"); //true if this is the upper half + + public BlockSluice() + { + super(Material.WOOD); + setDefaultState(blockState.getBaseState().withProperty(UPPER, false)); + setHardness(8.0f); + setHarvestLevel("axe", 0); + } + + @SuppressWarnings("deprecation") + @Override + public IBlockState getStateFromMeta(int meta) + { + return this.getDefaultState().withProperty(FACING, EnumFacing.byHorizontalIndex(meta)).withProperty(UPPER, meta > 3); + } + + @Override + public int getMetaFromState(IBlockState state) + { + return state.getValue(FACING).getHorizontalIndex() + (state.getValue(UPPER) ? 4 : 0); + } + + @SuppressWarnings("deprecation") + public boolean isFullCube(IBlockState state) + { + return false; + } + + @SuppressWarnings("deprecation") + public boolean isOpaqueCube(IBlockState state) + { + return false; + } + + @SuppressWarnings("deprecation") + public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos) + { + EnumFacing enumfacing = state.getValue(FACING); + + if (!state.getValue(UPPER)) + { + if (worldIn.getBlockState(pos.offset(enumfacing)).getBlock() != this) + { + worldIn.setBlockToAir(pos); + } + } + else if (worldIn.getBlockState(pos.offset(enumfacing.getOpposite())).getBlock() != this) + { + if (!worldIn.isRemote) + { + spawnAsEntity(worldIn, pos, new ItemStack(this)); + } + worldIn.setBlockToAir(pos); + } + + //Keep flowing liquids from reaching the top of this block + IBlockState blockState = worldIn.getBlockState(pos.up()); + if (blockState.getBlock() instanceof BlockFluidBase && blockState.getValue(BlockFluidBase.LEVEL) < 15) + { + worldIn.setBlockToAir(pos.up()); + } + } + + @Override + public Item getItemDropped(IBlockState state, Random rand, int fortune) + { + return state.getValue(UPPER) ? Item.getItemFromBlock(this) : Items.AIR; + } + + public void dropBlockAsItemWithChance(World worldIn, BlockPos pos, IBlockState state, float chance, int fortune) + { + if (state.getValue(UPPER)) + { + super.dropBlockAsItemWithChance(worldIn, pos, state, chance, fortune); + } + } + + @Override + protected BlockStateContainer createBlockState() + { + return new BlockStateContainer(this, FACING, UPPER); + } + + @Override + public boolean hasTileEntity(IBlockState state) + { + return state.getValue(UPPER); + } + + @Nullable + @Override + public TileEntity createTileEntity(World world, IBlockState state) + { + return state.getValue(UPPER) ? new TESluice() : null; + } +} diff --git a/src/main/java/net/dries007/tfc/objects/items/ItemGoldPan.java b/src/main/java/net/dries007/tfc/objects/items/ItemGoldPan.java index 173e297934..e660670a3a 100644 --- a/src/main/java/net/dries007/tfc/objects/items/ItemGoldPan.java +++ b/src/main/java/net/dries007/tfc/objects/items/ItemGoldPan.java @@ -5,8 +5,10 @@ package net.dries007.tfc.objects.items; +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; import javax.annotation.Nonnull; -import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import net.minecraft.block.material.Material; @@ -16,17 +18,27 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; import net.minecraft.item.ItemStack; -import net.minecraft.util.ActionResult; -import net.minecraft.util.EnumActionResult; -import net.minecraft.util.EnumHand; -import net.minecraft.util.NonNullList; +import net.minecraft.util.*; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; import mcp.MethodsReturnNonnullByDefault; +import net.dries007.tfc.Constants; import net.dries007.tfc.api.capability.size.Size; import net.dries007.tfc.api.capability.size.Weight; +import net.dries007.tfc.api.registries.TFCRegistries; +import net.dries007.tfc.api.types.Ore; +import net.dries007.tfc.api.types.Rock; +import net.dries007.tfc.client.TFCSounds; +import net.dries007.tfc.objects.blocks.stone.BlockRockVariant; +import net.dries007.tfc.objects.items.metal.ItemSmallOre; +import net.dries007.tfc.util.Helpers; +import net.dries007.tfc.world.classic.chunkdata.ChunkDataTFC; + +import static net.dries007.tfc.api.util.TFCConstants.MOD_ID; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault @@ -43,15 +55,15 @@ public ItemGoldPan() } @Override - public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) + public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { - //todo: move to public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) - ItemStack stack = playerIn.getHeldItem(handIn); - if (worldIn.isRemote) return new ActionResult<>(EnumActionResult.PASS, stack); - if (handIn != EnumHand.MAIN_HAND) return new ActionResult<>(EnumActionResult.PASS, stack); - if (canPan(worldIn, playerIn) == null) return new ActionResult<>(EnumActionResult.FAIL, stack); - playerIn.setActiveHand(handIn); - return new ActionResult<>(EnumActionResult.SUCCESS, stack); + if (hand != EnumHand.MAIN_HAND) + { + return EnumActionResult.PASS; + } + if (player.getHeldItem(hand).getItemDamage() > 0 && !canPan(worldIn, player)) return EnumActionResult.FAIL; + player.setActiveHand(hand); + return EnumActionResult.SUCCESS; } @Override @@ -67,9 +79,79 @@ public EnumAction getItemUseAction(ItemStack stack) } @Override - public int getMaxItemUseDuration(ItemStack stack) + @Nonnull + public ItemStack onItemUseFinish(@Nonnull ItemStack stack, World world, EntityLivingBase entityLiving) { - return 72; + if (!stack.isEmpty() && !world.isRemote && entityLiving instanceof EntityPlayer) + { + EntityPlayer player = (EntityPlayer) entityLiving; + if (stack.getItemDamage() > 0) + { + //Check if player still is looking at water + if (canPan(world, player)) + { + Chunk chunk = world.getChunk(player.getPosition()); + ChunkDataTFC chunkDataTFC = ChunkDataTFC.get(chunk); + if (chunkDataTFC.canWork(6)) + { + Random rand = new Random(world.getSeed() + chunk.getPos().x * 241179128412L + chunk.getPos().z * 327910215471L); + List chunkOres = TFCRegistries.ORES.getValuesCollection() + .stream().filter(Ore::canPan).filter(x -> rand.nextDouble() < x.getChunkChance()) + .collect(Collectors.toList()); + + chunkOres.forEach(x -> { + if (Constants.RNG.nextDouble() < x.getPanChance()) + { + Helpers.spawnItemStack(world, player.getPosition(), new ItemStack(ItemSmallOre.get(x))); + } + }); + chunkDataTFC.addWork(6); + stack.setItemDamage(0); + if (Constants.RNG.nextFloat() < 0.01) // 1/100 chance, same as 1.7.10 + { + stack.shrink(1); + world.playSound(null, entityLiving.getPosition(), TFCSounds.CERAMIC_BREAK, SoundCategory.PLAYERS, 1.0f, 1.0f); + } + } + else + { + player.sendMessage(new TextComponentTranslation(MOD_ID + ".tooltip.goldpan.chunkworked")); + } + } + } + else + { + //Try to fill the gold pan + RayTraceResult result = rayTrace(world, player, false); + //noinspection ConstantConditions + if (result == null || result.typeOfHit != RayTraceResult.Type.BLOCK) return stack; + BlockPos pos = result.getBlockPos(); + IBlockState state = world.getBlockState(pos); + if (!(state.getBlock() instanceof BlockRockVariant)) return stack; + Rock.Type type = ((BlockRockVariant) state.getBlock()).getType(); + if (type == Rock.Type.SAND) + { + stack.setItemDamage(1); + } + else if (type == Rock.Type.GRAVEL) + { + stack.setItemDamage(2); + } + else if (type == Rock.Type.CLAY) + { + stack.setItemDamage(3); + } + else if (type == Rock.Type.DIRT || type == Rock.Type.GRASS) + { + stack.setItemDamage(4); + } + if (stack.getItemDamage() > 0 && Constants.RNG.nextFloat() < 0.10f) + { + world.setBlockToAir(pos); + } + } + } + return stack; } @Override @@ -82,23 +164,9 @@ public void getSubItems(CreativeTabs tab, NonNullList items) } @Override - public void onUsingTick(ItemStack stack, EntityLivingBase entityLivingBase, int countLeft) + public int getMaxItemUseDuration(ItemStack stack) { - if (!(entityLivingBase instanceof EntityPlayer)) return; - final EntityPlayer player = ((EntityPlayer) entityLivingBase); - final RayTraceResult result = canPan(player.world, player); - if (result == null) - { - player.resetActiveHand(); - return; - } - final int total = getMaxItemUseDuration(stack); - final int count = total - countLeft; - final BlockPos pos = result.getBlockPos().add(0, 1, 0); - final World world = player.world; - final float chance = itemRand.nextFloat(); - - //todo: this is a copypaste from firestarter, it needs to pan, not start fires. + return stack.getItemDamage() > 0 ? 54 : 24; } @Nonnull @@ -121,17 +189,13 @@ public boolean canStack(ItemStack stack) return false; } - @Nullable - private RayTraceResult canPan(World world, EntityPlayer player) + private boolean canPan(World world, EntityPlayer player) { RayTraceResult result = rayTrace(world, player, true); //noinspection ConstantConditions - if (result == null) return null; - if (result.typeOfHit != RayTraceResult.Type.BLOCK) return null; + if (result == null) return false; + if (result.typeOfHit != RayTraceResult.Type.BLOCK) return false; BlockPos pos = result.getBlockPos(); - final IBlockState current = player.world.getBlockState(pos); - pos = pos.add(0, 1, 0); - if (world.getBlockState(pos).getMaterial() != Material.WATER) return null; - return result; + return world.getBlockState(pos).getMaterial() == Material.WATER; } } diff --git a/src/main/java/net/dries007/tfc/objects/items/itemblock/ItemBlockSluice.java b/src/main/java/net/dries007/tfc/objects/items/itemblock/ItemBlockSluice.java new file mode 100644 index 0000000000..b59d2a1cee --- /dev/null +++ b/src/main/java/net/dries007/tfc/objects/items/itemblock/ItemBlockSluice.java @@ -0,0 +1,85 @@ +/* + * Work under Copyright. Licensed under the EUPL. + * See the project README.md and LICENSE.txt for more information. + */ + +package net.dries007.tfc.objects.items.itemblock; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; + +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import mcp.MethodsReturnNonnullByDefault; +import net.dries007.tfc.api.capability.size.Size; +import net.dries007.tfc.api.capability.size.Weight; +import net.dries007.tfc.objects.blocks.devices.BlockSluice; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public class ItemBlockSluice extends ItemBlockTFC +{ + public ItemBlockSluice(Block block) + { + super(block); + } + + @Nonnull + @Override + public Size getSize(@Nonnull ItemStack stack) + { + return Size.HUGE; + } + + @Nonnull + @Override + public Weight getWeight(@Nonnull ItemStack stack) + { + return Weight.HEAVY; + } + + + public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) + { + if (worldIn.isRemote) + { + return EnumActionResult.SUCCESS; + } + else if (facing != EnumFacing.UP) + { + return EnumActionResult.FAIL; + } + else + { + if (!worldIn.getBlockState(pos).getMaterial().isReplaceable() || !worldIn.getBlockState(pos.offset(player.getHorizontalFacing())).getMaterial().isReplaceable()) + { + pos = pos.up(); //try the above + } + if (!worldIn.getBlockState(pos).getMaterial().isReplaceable() || !worldIn.getBlockState(pos.offset(player.getHorizontalFacing())).getMaterial().isReplaceable()) + { + return EnumActionResult.FAIL; + } + ItemStack stack = player.getHeldItem(hand); + BlockPos upperPos = pos.offset(player.getHorizontalFacing()); + //Creating a thatch bed + if (player.canPlayerEdit(upperPos, facing, stack) && player.canPlayerEdit(pos, facing, stack)) + { + stack.shrink(1); + IBlockState lowerState = this.block.getDefaultState().withProperty(BlockSluice.FACING, player.getHorizontalFacing()).withProperty(BlockSluice.UPPER, false); + IBlockState upperState = this.block.getDefaultState().withProperty(BlockSluice.FACING, player.getHorizontalFacing()).withProperty(BlockSluice.UPPER, true); + worldIn.setBlockState(pos, lowerState); + worldIn.setBlockState(upperPos, upperState); + return EnumActionResult.SUCCESS; + } + } + return EnumActionResult.PASS; + } +} diff --git a/src/main/java/net/dries007/tfc/objects/te/TESluice.java b/src/main/java/net/dries007/tfc/objects/te/TESluice.java new file mode 100644 index 0000000000..ed13d8c925 --- /dev/null +++ b/src/main/java/net/dries007/tfc/objects/te/TESluice.java @@ -0,0 +1,254 @@ +/* + * Work under Copyright. Licensed under the EUPL. + * See the project README.md and LICENSE.txt for more information. + */ + +package net.dries007.tfc.objects.te; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import com.google.common.collect.Lists; +import net.minecraft.block.Block; +import net.minecraft.block.BlockHorizontal; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EntitySelectors; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ITickable; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.chunk.Chunk; +import net.minecraftforge.fluids.BlockFluidBase; +import net.minecraftforge.fluids.Fluid; + +import net.dries007.tfc.ConfigTFC; +import net.dries007.tfc.Constants; +import net.dries007.tfc.api.types.Ore; +import net.dries007.tfc.api.types.Rock; +import net.dries007.tfc.objects.Gem; +import net.dries007.tfc.objects.blocks.devices.BlockSluice; +import net.dries007.tfc.objects.blocks.stone.BlockRockVariant; +import net.dries007.tfc.objects.fluids.FluidsTFC; +import net.dries007.tfc.objects.items.ItemGem; +import net.dries007.tfc.objects.items.metal.ItemSmallOre; +import net.dries007.tfc.util.Helpers; +import net.dries007.tfc.world.classic.chunkdata.ChunkDataTFC; + +public class TESluice extends TEBase implements ITickable +{ + private static final int MAX_SOIL = 50; + private int soil; + private int ticksRemaining, delayTimer; + + protected static Predicate ALLOWED_FLUIDS; + + public TESluice() + { + super(); + ALLOWED_FLUIDS = x -> x == FluidsTFC.FRESH_WATER.get() || x == FluidsTFC.LIMEWATER.get(); //placeholder, missed commit for SALT_WATER + } + + @Nullable + public BlockFluidBase getFlowingFluidBlock() + { + if (!hasWorld() || !(world.getBlockState(pos).getBlock() instanceof BlockSluice)) + { + return null; + } + EnumFacing sluiceFacing = world.getBlockState(pos).getValue(BlockHorizontal.FACING); + BlockPos fluidInputPos = pos.up().offset(sluiceFacing); + IBlockState state = world.getBlockState(fluidInputPos); + Block block = state.getBlock(); + if (block instanceof BlockFluidBase) + { + return ((BlockFluidBase) block); + } + return null; + } + + @Override + public void update() + { + if (!world.isRemote) + { + if (ticksRemaining > 0) + { + if (--ticksRemaining <= 0) + { + if (Constants.RNG.nextDouble() < ConfigTFC.GENERAL.sluiceOreChance) + { + ChunkPos myPos = world.getChunk(pos).getPos(); + int radius = ConfigTFC.GENERAL.sluiceRadius; + //Copy from Helper method, but only look for workable chunks + List chunks = new ArrayList<>(); + for (int x = myPos.x - radius; x <= myPos.x + radius; x++) + { + for (int z = myPos.z - radius; z <= myPos.z + radius; z++) + { + Chunk chunk = world.getChunk(x, z); + ChunkDataTFC chunkData = ChunkDataTFC.get(chunk); + if (chunkData.canWork(1) && chunkData.getChunkOres().size() > 0) + { + chunks.add(chunk); + } + } + } + if (chunks.size() > 0) + { + Chunk workingChunk = chunks.get(Constants.RNG.nextInt(chunks.size())); + ChunkDataTFC chunkData = ChunkDataTFC.get(workingChunk); + chunkData.addWork(); + List oreList = Lists.newArrayList(chunkData.getChunkOres()); + Ore drop = oreList.get(Constants.RNG.nextInt(oreList.size())); + ItemStack output = new ItemStack(ItemSmallOre.get(drop)); + Helpers.spawnItemStack(world, getFrontWaterPos(), output); + } + } + if (Constants.RNG.nextDouble() < ConfigTFC.GENERAL.sluiceGemChance) + { + Gem dropGem; + if (Constants.RNG.nextDouble() < ConfigTFC.GENERAL.sluiceDiamondGemChance) + { + dropGem = Gem.DIAMOND; + } + else + { + dropGem = Gem.getRandomDropGem(Constants.RNG); + } + Gem.Grade grade = Gem.Grade.randomGrade(Constants.RNG); + Helpers.spawnItemStack(world, getFrontWaterPos(), ItemGem.get(dropGem, grade, 1)); + } + consumeSoil(); + } + } + if (--delayTimer <= 0) + { + delayTimer = 20; + Fluid flowing = getFlowingFluid(); + //Try placing the output block if has input flow and is allowed fluid + if (flowing != null && ALLOWED_FLUIDS.test(flowing)) + { + BlockPos frontPos = getFrontWaterPos(); + if (world.getBlockState(frontPos).getMaterial().isReplaceable()) + { + world.setBlockState(frontPos, flowing.getBlock().getDefaultState()); + } + } + //Consume inputs + if (soil < MAX_SOIL) + { + for (EntityItem entityItem : world.getEntitiesWithinAABB(EntityItem.class, new AxisAlignedBB(pos).grow(1), EntitySelectors.IS_ALIVE)) + { + ItemStack stack = entityItem.getItem(); + if (stack.getItem() instanceof ItemBlock && ((ItemBlock) stack.getItem()).getBlock() instanceof BlockRockVariant) + { + BlockRockVariant rockBlock = (BlockRockVariant) ((ItemBlock) stack.getItem()).getBlock(); + if (rockBlock.getType() == Rock.Type.SAND || rockBlock.getType() == Rock.Type.GRAVEL) + { + soil += 20; + if (soil > MAX_SOIL) + { + soil = MAX_SOIL; + } + stack.shrink(1); + if (stack.getCount() <= 0) + { + entityItem.setDead(); + break; + } + } + } + } + } + if (ticksRemaining <= 0) + { + consumeSoil(); + } + } + } + } + + @Nullable + public Fluid getFlowingFluid() + { + BlockFluidBase block = getFlowingFluidBlock(); + return block == null ? null : block.getFluid(); + } + + @Nullable + public EnumFacing getBlockFacing() + { + if (!hasWorld() || !(world.getBlockState(pos).getBlock() instanceof BlockSluice)) + { + return null; + } + return world.getBlockState(pos).getValue(BlockHorizontal.FACING); + } + + private BlockPos getFrontWaterPos() + { + //noinspection ConstantConditions + return pos.down().offset(getBlockFacing().getOpposite(), 2); + } + + /** + * Checks if this sluice has flowing fluid (only allowed ones) + * + * @return true if the entrance and the output blocks are the same fluid and in the allowed predicate + */ + private boolean hasFlow() + { + + Fluid fluid = getFlowingFluid(); + if (fluid == null || !ALLOWED_FLUIDS.test(fluid)) + { + return false; + } + IBlockState frontState = world.getBlockState(getFrontWaterPos()); + Block block = frontState.getBlock(); + if (block instanceof BlockFluidBase) + { + return ((BlockFluidBase) block).getFluid() == fluid; + } + return false; + } + + @Override + public void readFromNBT(@Nonnull NBTTagCompound nbt) + { + super.readFromNBT(nbt); + soil = nbt.getInteger("soil"); + ticksRemaining = nbt.getInteger("ticksRemaining"); + } + + @Nonnull + @Override + public NBTTagCompound writeToNBT(NBTTagCompound nbt) + { + nbt.setInteger("soil", soil); + nbt.setInteger("ticksRemaining", ticksRemaining); + return super.writeToNBT(nbt); + } + + private void consumeSoil() + { + if (soil > 0 && hasFlow()) + { + soil--; + ticksRemaining = ConfigTFC.GENERAL.sluiceTicks; + } + else + { + soil = 0; + ticksRemaining = 0; + } + } +} diff --git a/src/main/java/net/dries007/tfc/types/DefaultMetals.java b/src/main/java/net/dries007/tfc/types/DefaultMetals.java index 3d358fc3aa..1d9896e084 100644 --- a/src/main/java/net/dries007/tfc/types/DefaultMetals.java +++ b/src/main/java/net/dries007/tfc/types/DefaultMetals.java @@ -100,11 +100,11 @@ public final class DefaultMetals public static void onPreRegisterOre(TFCRegistryEvent.RegisterPreBlock event) { event.getRegistry().registerAll( - new Ore(NATIVE_COPPER, COPPER), - new Ore(NATIVE_GOLD, GOLD), - new Ore(NATIVE_PLATINUM, PLATINUM), + new Ore(NATIVE_COPPER, COPPER, 0.75D, 0.33D), + new Ore(NATIVE_GOLD, GOLD, 0.25D, 0.15D), + new Ore(NATIVE_PLATINUM, PLATINUM, 1D, 0.002D), new Ore(HEMATITE, PIG_IRON, false), - new Ore(NATIVE_SILVER, SILVER), + new Ore(NATIVE_SILVER, SILVER, 0.50D, 0.15D), new Ore(CASSITERITE, TIN), new Ore(GALENA, LEAD), new Ore(BISMUTHINITE, BISMUTH), diff --git a/src/main/java/net/dries007/tfc/util/Helpers.java b/src/main/java/net/dries007/tfc/util/Helpers.java index 097c62035e..92846f30d8 100644 --- a/src/main/java/net/dries007/tfc/util/Helpers.java +++ b/src/main/java/net/dries007/tfc/util/Helpers.java @@ -25,12 +25,14 @@ import net.minecraft.world.EnumSkyBlock; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; import net.minecraftforge.fml.common.network.ByteBufUtils; import net.minecraftforge.registries.IForgeRegistryEntry; import io.netty.buffer.ByteBuf; import net.dries007.tfc.Constants; import net.dries007.tfc.api.registries.TFCRegistries; +import net.dries007.tfc.api.types.Ore; import net.dries007.tfc.api.types.Plant; import net.dries007.tfc.api.types.Rock; import net.dries007.tfc.api.util.TFCConstants; @@ -109,6 +111,35 @@ else if (current.getBlock() instanceof BlockRockVariant) } } + /** + * Gets a map of generated ores for each chunk in radius. + * It takes account only loaded chunks, so if radius is too big you probably won't get an accurate data. + * + * @param world the WorldObj + * @param chunkX the center chunk's X position + * @param chunkZ the center chunk's Z position + * @param radius the radius to scan. can be 0 to scan only the central chunk + * @return a map containing all ores generated for each chunk + */ + public static Map> getChunkOres(World world, int chunkX, int chunkZ, int radius) + { + Map> map = new HashMap<>(); + for (int x = chunkX - radius; x <= chunkX + radius; x++) + { + for (int z = chunkZ - radius; z <= chunkZ + radius; z++) + { + ChunkPos chunkPos = new ChunkPos(x, z); + if (world.isBlockLoaded(chunkPos.getBlock(8, 0, 8))) + { + Chunk chunk = world.getChunk(x, z); + ChunkDataTFC chunkData = ChunkDataTFC.get(chunk); + map.put(chunkPos, chunkData.getChunkOres()); + } + } + } + return map; + } + /** * Makes an entity sit on a block * diff --git a/src/main/java/net/dries007/tfc/world/classic/chunkdata/ChunkDataTFC.java b/src/main/java/net/dries007/tfc/world/classic/chunkdata/ChunkDataTFC.java index 47cef0326b..8b910782f2 100644 --- a/src/main/java/net/dries007/tfc/world/classic/chunkdata/ChunkDataTFC.java +++ b/src/main/java/net/dries007/tfc/world/classic/chunkdata/ChunkDataTFC.java @@ -6,23 +6,27 @@ package net.dries007.tfc.world.classic.chunkdata; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import net.minecraft.nbt.NBTBase; -import net.minecraft.nbt.NBTTagByteArray; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagIntArray; +import com.google.common.collect.ImmutableSet; +import net.minecraft.nbt.*; import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.Constants; import net.minecraftforge.registries.ForgeRegistry; +import net.dries007.tfc.ConfigTFC; import net.dries007.tfc.api.registries.TFCRegistries; +import net.dries007.tfc.api.types.Ore; import net.dries007.tfc.api.types.Rock; import net.dries007.tfc.api.types.Tree; import net.dries007.tfc.util.NBTBuilder; @@ -116,6 +120,8 @@ public static Rock getRockHeight(World world, BlockPos pos) private float avgTemp; private float floraDensity; private float floraDiversity; + private Set chunkOres = new HashSet<>(); + private int chunkWorkage; /** * INTERNAL USE ONLY. @@ -136,6 +142,43 @@ public void setGenerationData(int[] rockLayer1, int[] rockLayer2, int[] rockLaye this.avgTemp = avgTemp; this.floraDensity = floraDensity; this.floraDiversity = floraDiversity; + this.chunkWorkage = 0; + } + + /** + * Adds generated ores to this chunk list of ores + * Should be used by ore vein generators to save in this chunk which ores generated here + * + * @param ore the ore added by ore vein generator + */ + public void addGeneratedOre(Ore ore) + { + chunkOres.add(ore); + } + + /** + * Returns a set of ores that generated in this chunk + * + * @return the immutable set containing all ores that generated in this chunk + */ + public Set getChunkOres() + { + return ImmutableSet.copyOf(chunkOres); + } + + public boolean canWork(int amount) + { + return ConfigTFC.GENERAL.overworkChunk || chunkWorkage <= ConfigTFC.GENERAL.maxWorkChunk + amount; + } + + public void addWork(int amount) + { + chunkWorkage += amount; + } + + public void addWork() + { + addWork(1); } public boolean isInitialized() @@ -326,6 +369,21 @@ public NBTBase writeNBT(Capability capability, ChunkDataTFC instan root.setFloat("floraDensity", instance.floraDensity); root.setFloat("floraDiversity", instance.floraDiversity); + root.setInteger("chunkWorkage", instance.chunkWorkage); + + if (instance.chunkOres.size() > 0) + { + NBTTagList oreList = new NBTTagList(); + for (Ore ore : instance.chunkOres) + { + NBTTagCompound nbtOre = new NBTTagCompound(); + //noinspection ConstantConditions + nbtOre.setString("oreRegistry", ore.getRegistryName().toString()); + oreList.appendTag(nbtOre); + } + root.setTag("chunkOres", oreList); + } + return root; } @@ -351,6 +409,21 @@ public void readNBT(Capability capability, ChunkDataTFC instance, instance.floraDensity = root.getFloat("floraDensity"); instance.floraDiversity = root.getFloat("floraDiversity"); + instance.chunkWorkage = root.getInteger("chunkWorkage"); + + instance.chunkOres = new HashSet<>(); + + if (root.hasKey("chunkOres")) + { + NBTTagList oreList = root.getTagList("chunkOres", Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < oreList.tagCount(); i++) + { + NBTTagCompound nbtOre = oreList.getCompoundTagAt(i); + Ore ore = TFCRegistries.ORES.getValue(new ResourceLocation(nbtOre.getString("oreRegistry"))); + instance.chunkOres.add(ore); + } + } + instance.initialized = true; } } diff --git a/src/main/java/net/dries007/tfc/world/classic/worldgen/WorldGenOreVeins.java b/src/main/java/net/dries007/tfc/world/classic/worldgen/WorldGenOreVeins.java index abb175e8d7..4998951232 100644 --- a/src/main/java/net/dries007/tfc/world/classic/worldgen/WorldGenOreVeins.java +++ b/src/main/java/net/dries007/tfc/world/classic/worldgen/WorldGenOreVeins.java @@ -114,6 +114,7 @@ public void generate(Random random, int chunkX, int chunkZ, World world, IChunkG if (vein.pos.getY() >= WorldTypeTFC.SEALEVEL + chunkData.getSeaLevelOffset(vein.pos)) continue; + boolean generated = false; for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) @@ -135,9 +136,14 @@ public void generate(Random random, int chunkX, int chunkZ, World world, IChunkG continue; world.setBlockState(posAt, vein.type.getOreState(blockAt.getRock(), vein.grade), 2); + generated = true; } } } + if (generated) + { + chunkData.addGeneratedOre(vein.type.ore); + } } } } \ No newline at end of file diff --git a/src/main/resources/assets b/src/main/resources/assets index f6354732b7..43f4564a8c 160000 --- a/src/main/resources/assets +++ b/src/main/resources/assets @@ -1 +1 @@ -Subproject commit f6354732b70eb537fc3a7988ac29a25e500893cb +Subproject commit 43f4564a8ceff847d32317248a8e0198a007e75b