Added test command for testing ore gen.

Started reimplementing quartz ore gen ontop of vanilla mechanics.
Fixes several sidedness issues.
Added recipe serialization for server->client sync.
This commit is contained in:
Sebastian Hartte
2020-06-20 18:04:20 +02:00
parent daaac300b8
commit 434386a7ff
44 changed files with 597 additions and 434 deletions
@@ -0,0 +1,44 @@
package appeng.worldgen;
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.Dynamic;
import com.mojang.datafixers.types.DynamicOps;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.world.gen.feature.IFeatureConfig;
import net.minecraft.world.gen.feature.ReplaceBlockConfig;
import appeng.core.AEConfig;
/**
* Extends a {@link ReplaceBlockConfig} with a chance.
*/
public class ChargedQuartzOreConfig implements IFeatureConfig {
public final BlockState target;
public final BlockState state;
public final float chance;
public ChargedQuartzOreConfig(BlockState target, BlockState state, float chance) {
this.target = target;
this.state = state;
this.chance = chance;
}
public <T> Dynamic<T> serialize(DynamicOps<T> ops) {
return new Dynamic<>(ops,
ops.createMap(
ImmutableMap.of(ops.createString("target"), BlockState.serialize(ops, this.target).getValue(),
ops.createString("state"), BlockState.serialize(ops, this.state).getValue(),
ops.createString("chance"), ops.createFloat(this.chance))));
}
public static <T> ChargedQuartzOreConfig deserialize(Dynamic<T> p_214657_0_) {
BlockState target = p_214657_0_.get("target").map(BlockState::deserialize).orElse(Blocks.AIR.getDefaultState());
BlockState state = p_214657_0_.get("state").map(BlockState::deserialize).orElse(Blocks.AIR.getDefaultState());
float chance = p_214657_0_.get("chance").asFloat(AEConfig.instance().getSpawnChargedChance());
return new ChargedQuartzOreConfig(target, state, chance);
}
}
@@ -0,0 +1,60 @@
package appeng.worldgen;
import java.util.Random;
import java.util.function.Function;
import com.mojang.datafixers.Dynamic;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.IWorld;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.GenerationSettings;
import net.minecraft.world.gen.Heightmap;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.ReplaceBlockFeature;
import appeng.core.AppEng;
/**
* Extends {@link ReplaceBlockFeature} by also allowing for a replacement
* chance. In addition, the feature will check every block in the chunk.
*/
public class ChargedQuartzOreFeature extends Feature<ChargedQuartzOreConfig> {
public static final ChargedQuartzOreFeature INSTANCE = new ChargedQuartzOreFeature(
ChargedQuartzOreConfig::deserialize);
static {
INSTANCE.setRegistryName(AppEng.MOD_ID, "charged_quartz_ore");
}
public ChargedQuartzOreFeature(Function<Dynamic<?>, ? extends ChargedQuartzOreConfig> p_i51444_1_) {
super(p_i51444_1_);
}
public boolean place(IWorld worldIn, ChunkGenerator<? extends GenerationSettings> generator, Random rand,
BlockPos pos, ChargedQuartzOreConfig config) {
ChunkPos chunkPos = new ChunkPos(pos);
BlockPos.Mutable bpos = new BlockPos.Mutable();
int height = worldIn.getHeight(Heightmap.Type.WORLD_SURFACE_WG, pos.getX(), pos.getZ());
IChunk chunk = worldIn.getChunk(pos);
for (int y = 0; y < height; y++) {
bpos.setY(y);
for (int x = chunkPos.getXStart(); x <= chunkPos.getXEnd(); x++) {
bpos.setX(x);
for (int z = chunkPos.getZStart(); z <= chunkPos.getZEnd(); z++) {
bpos.setZ(z);
if (chunk.getBlockState(bpos).getBlock() == config.target.getBlock()
&& rand.nextFloat() < config.chance) {
chunk.setBlockState(bpos, config.state, false);
}
}
}
}
return true;
}
}
@@ -1,103 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.worldgen;
import java.util.Random;
import java.util.function.Function;
import com.mojang.datafixers.Dynamic;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.GenerationSettings;
import net.minecraft.world.gen.feature.ReplaceBlockConfig;
import net.minecraft.world.gen.feature.ReplaceBlockFeature;
import appeng.api.AEApi;
import appeng.api.definitions.IBlockDefinition;
import appeng.api.definitions.IBlocks;
import appeng.api.features.IWorldGen.WorldGenType;
import appeng.core.features.registries.WorldGenRegistry;
public final class QuartzWorldGen extends ReplaceBlockFeature {
/*
* private final WorldGenMinable oreNormal; private final WorldGenMinable
* oreCharged;
*/
public QuartzWorldGen(Function<Dynamic<?>, ? extends ReplaceBlockConfig> serializer) {
super(serializer);
final IBlocks blocks = AEApi.instance().definitions().blocks();
final IBlockDefinition oreDefinition = blocks.quartzOre();
final IBlockDefinition chargedDefinition = blocks.quartzOreCharged();
/*
* this.oreNormal = oreDefinition.maybeBlock() .map( b -> new WorldGenMinable(
* b.getDefaultState(), AEConfig.instance().getQuartzOresPerCluster() ) )
* .orElse( null ); this.oreCharged = chargedDefinition.maybeBlock() .map( b ->
* new WorldGenMinable( b.getDefaultState(),
* AEConfig.instance().getQuartzOresPerCluster() ) ) .orElse( null );
*/
}
private static boolean shouldGenerate(final boolean isCharged, final World w) {
return WorldGenRegistry.INSTANCE
.isWorldGenEnabled(isCharged ? WorldGenType.CHARGED_CERTUS_QUARTZ : WorldGenType.CERTUS_QUARTZ, w);
}
@Override
public boolean place(IWorld worldIn, ChunkGenerator<? extends GenerationSettings> generator, Random r, BlockPos pos,
ReplaceBlockConfig config) {
/*
* if( this.oreNormal == null && this.oreCharged == null ) { return false; }
*
* World w = worldIn.getWorld();
*
* int seaLevel = w.getSeaLevel();
*
* ChunkPos chunkPos = new ChunkPos( pos );
*
* if( seaLevel < 20 ) { final int x = ( chunkPos.x << 4 ) + 8; final int z = (
* chunkPos.z << 4 ) + 8; seaLevel = w.getHeight( Heightmap.Type.WORLD_SURFACE,
* x, z ); }
*
* final int oreDepthMultiplier =
* AEConfig.instance().getQuartzOresClusterAmount() * seaLevel / 64; final int
* scale = (int) Math.round( r.nextGaussian() * Math.sqrt( oreDepthMultiplier )
* + oreDepthMultiplier );
*
* for( int cnt = 0; cnt < ( r.nextBoolean() ? scale * 2 : scale ) / 2; ++cnt )
* { boolean isCharged = false;
*
* if( this.oreCharged != null ) { isCharged = r.nextFloat() >
* AEConfig.instance().getSpawnChargedChance(); }
*
* final WorldGenMinable whichOre = isCharged ? this.oreCharged :
* this.oreNormal; if( whichOre != null && shouldGenerate( isCharged, w ) ) {
* final int cx = chunkPos.x * 16 + r.nextInt( 16 ); final int cy = r.nextInt(
* 40 * seaLevel / 64 ) + r.nextInt( 22 * seaLevel / 64 ) + 12 * seaLevel / 64;
* final int cz = chunkPos.z * 16 + r.nextInt( 16 ); whichOre.generate( w, r,
* new BlockPos( cx, cy, cz ) ); } }
*/
return true;
}
}