package bloodasp.galacticgreg.api; import java.util.ArrayList; import java.util.List; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.world.chunk.IChunkProvider; //import bloodasp.galacticgreg.GalacticGreg; import bloodasp.galacticgreg.api.Enums.AirReplaceRule; import bloodasp.galacticgreg.api.Enums.DimensionType; import bloodasp.galacticgreg.api.Enums.ReplaceState; import bloodasp.galacticgreg.api.Enums.SpaceObjectType; /** * Class to define a Dimension. Supposed to be added to a ModContainer */ public class ModDimensionDef { private static final String STR_NOTDEFINED = "iiznotdefined"; private String _mDimensionName; private String _mInternalDimIdentifier; private String _mChunkProvider; private AirReplaceRule _mDimAirSetting; private ArrayList _mReplaceableBlocks; private DimensionType _mDimensionType; private List _mSpaceObjectsGenerators; private List _mSpaceStructureGenerators; // Special Planets config settings private int _mGroundOreMaxY = 64; private int _mFloatingAsteroidsMinY = 128; // ------ // Override for stonetype private GTOreTypes _mStoneType; // Asteroid stuff private List _mValidAsteroidMaterials; private List _mSpecialBlocksForAsteroids; private Random _mRandom = new Random(System.currentTimeMillis()); /** Internal function * @return A list of possible asteroid-mixes that shall be generated */ public List getValidAsteroidMaterials() { return _mValidAsteroidMaterials; } // ================================================= /** Internal function * The only purpose of this functions is to get a default config value for this dim, that can be altered by * the mod author which adds the dimension definition to his mod, but also provide the modpack-author/serveradmin * to change these values aswell */ public int getPreConfiguratedGroundOreMaxY() { return _mGroundOreMaxY; } /** Internal function * The only purpose of this functions is to get a default config value for this dim, that can be altered by * the mod author which adds the dimension definition to his mod, but also provide the modpack-author/serveradmin * to change these values aswell */ public int getPreConfiguratedFloatingAsteroidMinY() { return _mFloatingAsteroidsMinY; } /**Register new generator for objects in space. You can register as many as you want. * If you don't register anything, no structures will generate and the default Asteroid-Generator will be used * @param pSpaceObjectGenerator An instance of your own object generator */ public void registerSpaceObjectGenerator(ISpaceObjectGenerator pSpaceObjectGenerator) { SpaceObjectType tType = pSpaceObjectGenerator.getType(); switch(tType) { case NonOreSchematic: _mSpaceStructureGenerators.add(pSpaceObjectGenerator); break; case OreAsteroid: _mSpaceObjectsGenerators.add(pSpaceObjectGenerator); break; default: //GalacticGreg.Logger.error("registerSpaceObjectGenerator() found unhandled generator type %s. Please report asap, the author was lazy!", tType.toString()); break; } } /**Internal function * Return a random generator for space objects */ public ISpaceObjectGenerator getRandomSOGenerator(SpaceObjectType pTargetType) { ISpaceObjectGenerator tGen = null; List tLst = null; try { switch (pTargetType) { case NonOreSchematic: tLst = _mSpaceStructureGenerators; break; case OreAsteroid: tLst = _mSpaceObjectsGenerators; break; default: break; } if (tLst != null) { if (tLst.size() == 1) tGen = tLst.get(0); else if (tLst.size() > 1) tGen = tLst.get(_mRandom.nextInt(tLst.size())); } } catch(Exception e) { e.printStackTrace(); } return tGen; } /** * Define the default values for the floating asteroids and the oregen here. * As both generators run in the same dimension, and you probably don't want to * have asteroids stuck in the ground, both generators are separated from each other. * Basically, you can go with the default values. If you want to change them, make sure * that pOregenMaxY is lower than pAsteroidMinY * @param pOregenMaxY The maximum Y-height where ores will be allowed to spawn. Default: 64 * @param pAsteroidMinY The minimum Y-height that has to be reached before asteroids will spawn. Default: 128 * @throws IllegalArgumentException if the limits are invalid * */ public void setAsteroidAndPlanetLimits(int pOregenMaxY, int pAsteroidMinY) { if (pOregenMaxY >= pAsteroidMinY) throw new IllegalArgumentException("pOregenMaxY must be LOWER than pAsteroidMinY!"); _mFloatingAsteroidsMinY = pAsteroidMinY; _mGroundOreMaxY = pOregenMaxY; } // ================================================= /**Internal function * * @return A list of all special blocks that shall be used to generate the asteroids. */ public List getSpecialBlocksForAsteroids() { return _mSpecialBlocksForAsteroids; } public List getSpaceObjectGenerators() { return _mSpaceObjectsGenerators; } /**Internal function * * @return The type for this dimension */ public DimensionType getDimensionType() { return _mDimensionType; } /** * Set whether this DimensionDefinition defines an void-dimension that shall spawn asteroids instead of ores in stone * @param pType The dimensiontype to be used */ public void setDimensionType(DimensionType pType) { _mDimensionType = pType; } /**Internal function * * @return The configuration for AirBlocks */ public AirReplaceRule getAirSetting() { return _mDimAirSetting; } /** * Define how the oregen shall handle air-blocks. * These settings should be pretty self-explandatory, but anyways: * NeverReplaceAir: No matter what, if there is an Air-Block found, it will not replace it. * AllowReplaceAir: This will generate Ores in Stones (defined by addBlockDefinition()) and air if found * OnlyReplaceAir : This will not generate Ores in solid blocks, but only in air * * Note that "OnlyReplaceAir" is a special setting if you have a dimension that is not defined as "Asteroids" * but you still need/want to generate ores in midair. * @param pSetting */ public void setAirSetting(AirReplaceRule pSetting) { _mDimAirSetting = pSetting; } /**Internal function * * @return The dimension identifier that is used internally to identify the dimension */ public String getDimIdentifier() { return _mInternalDimIdentifier; } /** * Set a manual override for ores that shall be generated. * This setting is ignored if getIsAsteroidDimension() returns true * * For example, on GalactiCraft Mars, this value is set to GTOreTypes.RedGranite, because it matches the * color better. If you don't set anything here, it will generate regular stone-ores. * @param pOffset */ public void setStoneType(GTOreTypes pStoneType) { _mStoneType = pStoneType; } /** Internal function * * @return The stone override for gregtech ores */ public GTOreTypes getStoneType() { return _mStoneType; } /** Internal function * * @return The attached chunk-provider for this dimension */ public String getChunkProviderName() { return _mChunkProvider; } /** * Adds a new blockdefinition to this dimension. This block will then later be replaced by ores. * You can add as many blocks as you want. Just don't add Blocks.Air, as there is another setting for allowing Air-Replacement * @param pBlockDef * @return */ public boolean addBlockDefinition(ModDBMDef pBlockDef) { if (_mReplaceableBlocks.contains(pBlockDef)) { //GalacticGreg.Logger.error("Cannot add Block %s:%d, as it is already existing!", pBlockDef.getBlockName(), pBlockDef.getMeta()); return false; } else { _mReplaceableBlocks.add(pBlockDef); return true; } } /**Internal function * * @return The DimensionName in a Human-readable format */ public String getDimensionName() { return _mDimensionName; } /**Internal function * * @return A list of all defined Blocks that can be replaced while generating ores */ public ArrayList getReplaceableBlocks() { return _mReplaceableBlocks; } /** Define a new dimension * @param pDimensionName The human-readable. Spaces will be removed * @param pChunkProvider The chunkprovider class that shall be observed for the oregen */ public ModDimensionDef(String pDimensionName, Class pChunkProvider, DimensionType pDimType) { this(pDimensionName, pChunkProvider.toString().substring(6), pDimType, null); } /** Define a new dimension * @param pDimensionName The human-readable. Spaces will be removed * @param pChunkProvider The chunkprovider class that shall be observed for the oregen * @param pBlockDefinitions The list of predefined blocks to be replaced by ores */ public ModDimensionDef(String pDimensionName, Class pChunkProvider, DimensionType pDimType, List pBlockDefinitions) { this(pDimensionName, pChunkProvider.toString().substring(6), pDimType, pBlockDefinitions); } /** Define a new dimension * @param pDimensionName The human-readable DimensionName. Spaces will be removed * @param pChunkProviderName The human-readable, full-qualified classname for the chunkprovider */ public ModDimensionDef(String pDimensionName, String pChunkProviderName, DimensionType pDimType) { this(pDimensionName, pChunkProviderName, pDimType, null); } /** Define a new dimension * @param pDimensionName The human-readable DimensionName. Spaces will be removed * @param pChunkProviderName The human-readable, full-qualified classname for the chunkprovider * @param pBlockDefinitions The list of predefined blocks to be replaced by ores */ public ModDimensionDef(String pDimensionName, String pChunkProviderName, DimensionType pDimType, List pBlockDefinitions) { _mInternalDimIdentifier = STR_NOTDEFINED; _mDimensionName = pDimensionName; _mChunkProvider = pChunkProviderName; _mDimensionType = pDimType; _mReplaceableBlocks = new ArrayList(); if (pBlockDefinitions != null) _mReplaceableBlocks.addAll(pBlockDefinitions); _mValidAsteroidMaterials = new ArrayList(); _mSpecialBlocksForAsteroids = new ArrayList(); _mSpaceObjectsGenerators = new ArrayList(); _mSpaceStructureGenerators = new ArrayList(); } /**Internal function * * Do not call this function by yourself. Ever. It will cause explosions, water to blood, death of firstborn,... * Seriously, don't do it. */ protected void setParentModName(String pModName) { if (!_mInternalDimIdentifier.equals(STR_NOTDEFINED)) return; // Don't update, we're already set else { _mInternalDimIdentifier = String.format("%s_%s", pModName, _mDimensionName); //GalacticGreg.Logger.debug("Set Internal Identifier for Dimension %s to %s", _mDimensionName, _mInternalDimIdentifier); } } /**Internal function * * Check if pBlock can be replaced by an ore * @param pBlock * @param pMeta * @return */ public ReplaceState getReplaceStateForBlock(Block pBlock, int pMeta) { ReplaceState tFlag = ReplaceState.Unknown; for (ModDBMDef pDef : _mReplaceableBlocks) { ReplaceState tResult = pDef.blockEquals(pBlock, pMeta); if (tResult == ReplaceState.Unknown) continue; if (tResult == ReplaceState.CanReplace) { //GalacticGreg.Logger.trace("Targetblock found and metadata match. Replacement allowed"); tFlag = ReplaceState.CanReplace; } else if (tResult == ReplaceState.CannotReplace) { //GalacticGreg.Logger.trace("Targetblock found but metadata mismatch. Replacement denied"); tFlag = ReplaceState.CannotReplace; } break; } return tFlag; } /**Internal function * * Randomly select one material out of all defined materials * @return */ public AsteroidBlockComb getRandomAsteroidMaterial() { if (_mValidAsteroidMaterials.size() == 0) return null; if (_mValidAsteroidMaterials.size() == 1) return _mValidAsteroidMaterials.get(0); else { return _mValidAsteroidMaterials.get(_mRandom.nextInt(_mValidAsteroidMaterials.size())); } } /**Internal function * * Randomly select one special block to be placed in the asteroids * @return */ public SpecialBlockComb getRandomSpecialAsteroidBlock() { if (_mSpecialBlocksForAsteroids.size() == 0) return null; if (_mSpecialBlocksForAsteroids.size() == 1) return _mSpecialBlocksForAsteroids.get(0); else { return _mSpecialBlocksForAsteroids.get(_mRandom.nextInt(_mSpecialBlocksForAsteroids.size())); } } /** * Define the material the asteroid shall be made of. Limited to GT-Based Ores and their stones * @param pMaterial */ public void addAsteroidMaterial(GTOreTypes pMaterial) { addAsteroidMaterial(new AsteroidBlockComb(pMaterial)); } /** * Define the material the asteroid shall be made of, more advanced option to specify your own blocks * @param pMaterial */ public void addAsteroidMaterial(AsteroidBlockComb pBlockComb) { if (_mValidAsteroidMaterials.contains(pBlockComb)) return; else _mValidAsteroidMaterials.add(pBlockComb); } /** * Adds a new material for asteroid generation. These will spawn randomly in asteroids if enabled. * You can basically add every block you can imagine. * Be warned though, if you use Liquids (Water / Lava / ..), it can affect performance if the liquid * is flowing down to the void. So make sure you define "AsteroidCore" as position * @param pBlock Block-Meta Combination that shall be used */ public void addSpecialAsteroidBlock(SpecialBlockComb pBlock) { if (_mSpecialBlocksForAsteroids.contains(pBlock)) return; else _mSpecialBlocksForAsteroids.add(pBlock); } /**Internal function * Called when GalacticGreg will finalize all its internal structures. You should never call this yourself */ public void finalizeReplaceableBlocks(String pParentModName) { for (ModDBMDef rpb : _mReplaceableBlocks) { try { rpb.updateBlockName(pParentModName); if (_mStoneType == null) _mStoneType = GTOreTypes.NormalOres; } catch(Exception e) { //GalacticGreg.Logger.error("Unable to finalize replaceable block with modname for block %s. Dimension %s will probably have problems generating ores", rpb.getBlockName(), _mDimensionName); continue; } } } }