mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-18 10:12:53 +00:00
Rivers & Lakes
This commit is contained in:
parent
9be6e12a5c
commit
6d3a35517b
@ -114,7 +114,7 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator
|
||||
}
|
||||
|
||||
KList<BlockData> layers = biome.generateLayers(rx, rz, masterRandom, height, height - getFluidHeight());
|
||||
KList<BlockData> seaLayers = biome.isSea() || biome.isShore() ? biome.generateSeaLayers(rx, rz, masterRandom, fluidHeight - height) : new KList<>();
|
||||
KList<BlockData> seaLayers = biome.isAquatic() || biome.isShore() ? biome.generateSeaLayers(rx, rz, masterRandom, fluidHeight - height) : new KList<>();
|
||||
boolean caverning = false;
|
||||
KList<Integer> cavernHeights = new KList<>();
|
||||
int lastCavernHeight = -1;
|
||||
@ -510,34 +510,33 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator
|
||||
double wz = getModifiedZ(x, z);
|
||||
IrisRegion region = sampleRegion(x, z);
|
||||
double sh = region.getShoreHeight(wx, wz);
|
||||
double shMax = getFluidHeight() + (sh / 2);
|
||||
double shMin = getFluidHeight() - (sh / 2);
|
||||
IrisBiome current = sampleBiome(x, z);
|
||||
InferredType aquaticType = current.isAquatic() ? (current.isSea() ? InferredType.SEA : current.isRiver() ? InferredType.RIVER : InferredType.LAKE) : InferredType.SEA;
|
||||
boolean sea = height <= getFluidHeight();
|
||||
boolean shore = height >= shMin && height <= shMax;
|
||||
boolean land = height > getFluidHeight();
|
||||
|
||||
if(current.isShore() && height > sh)
|
||||
// Remove rivers, lakes & sea from land
|
||||
if(current.isAquatic() && land)
|
||||
{
|
||||
return glBiome.generateData(InferredType.LAND, wx, wz, x, z, region);
|
||||
current = glBiome.generateData(InferredType.LAND, wx, wz, x, z, region);
|
||||
}
|
||||
|
||||
if(current.isShore() || current.isLand() && height <= getDimension().getFluidHeight())
|
||||
// Remove land from underwater
|
||||
if(current.isLand() && sea)
|
||||
{
|
||||
return glBiome.generateData(InferredType.SEA, wx, wz, x, z, region);
|
||||
current = glBiome.generateData(aquaticType, wx, wz, x, z, region);
|
||||
}
|
||||
|
||||
if(current.isSea() && height > getDimension().getFluidHeight())
|
||||
// Add shores to land
|
||||
if(shore)
|
||||
{
|
||||
return glBiome.generateData(InferredType.LAND, wx, wz, x, z, region);
|
||||
current = glBiome.generateData(InferredType.SHORE, wx, wz, x, z, region);
|
||||
}
|
||||
|
||||
if(height <= getDimension().getFluidHeight())
|
||||
{
|
||||
return glBiome.generateData(InferredType.SEA, wx, wz, x, z, region);
|
||||
}
|
||||
|
||||
if(height <= getDimension().getFluidHeight() + sh)
|
||||
{
|
||||
return glBiome.generateData(InferredType.SHORE, wx, wz, x, z, region);
|
||||
}
|
||||
|
||||
return glBiome.generateRegionData(wx, wz, x, z, region);
|
||||
return current;
|
||||
}
|
||||
|
||||
public IrisBiome sampleCaveBiome(int x, int z)
|
||||
@ -586,22 +585,7 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator
|
||||
return focus();
|
||||
}
|
||||
|
||||
return getCache().getBiome(x, z, () ->
|
||||
{
|
||||
double wx = getModifiedX(x, z);
|
||||
double wz = getModifiedZ(x, z);
|
||||
IrisRegion region = sampleRegion(x, z);
|
||||
int height = (int) Math.round(noise);
|
||||
double sh = region.getShoreHeight(wx, wz);
|
||||
IrisBiome current = sampleTrueBiomeBase(x, z, height);
|
||||
|
||||
if(current.isSea() && height > getDimension().getFluidHeight() - sh)
|
||||
{
|
||||
return glBiome.generateData(InferredType.SHORE, wx, wz, x, z, region);
|
||||
}
|
||||
|
||||
return current;
|
||||
});
|
||||
return getCache().getBiome(x, z, () -> sampleTrueBiomeBase(x, z, (int) Math.round(noise)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -10,6 +10,7 @@ import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
|
||||
import org.bukkit.generator.ChunkGenerator.ChunkData;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.object.IrisBiome;
|
||||
import com.volmit.iris.util.B;
|
||||
import com.volmit.iris.util.HeightMap;
|
||||
@ -118,6 +119,7 @@ public class AtomicSliver
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
setSilently(h, d);
|
||||
modified = true;
|
||||
lock.lock();
|
||||
@ -134,6 +136,7 @@ public class AtomicSliver
|
||||
|
||||
if(d == null)
|
||||
{
|
||||
Iris.warn("Null set at " + h + " of " + x + " " + z);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -361,14 +364,16 @@ public class AtomicSliver
|
||||
return;
|
||||
}
|
||||
lock.lock();
|
||||
for(int i = 0; i < 256; i++)
|
||||
|
||||
for(int i : block.keySet())
|
||||
{
|
||||
if(block.get(i) != null && !block.get(i).equals(AIR))
|
||||
BlockData b = block.get(i);
|
||||
if(b != null)
|
||||
{
|
||||
BlockData b = block.get(i);
|
||||
currentData.setBlock(x, i, z, b);
|
||||
}
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
|
@ -22,20 +22,28 @@ public class GenLayerBiome extends GenLayer
|
||||
{
|
||||
private CNG regionGenerator;
|
||||
private CNG bridgeGenerator;
|
||||
private RNG lakeRandom;
|
||||
private RNG riverRandom;
|
||||
private BiomeDataProvider seaProvider;
|
||||
private BiomeDataProvider landProvider;
|
||||
private BiomeDataProvider shoreProvider;
|
||||
private BiomeDataProvider caveProvider;
|
||||
private BiomeDataProvider riverProvider;
|
||||
private BiomeDataProvider lakeProvider;
|
||||
private DimensionChunkGenerator iris;
|
||||
|
||||
public GenLayerBiome(DimensionChunkGenerator iris, RNG rng)
|
||||
{
|
||||
super(iris, rng);
|
||||
this.iris = iris;
|
||||
riverRandom = iris.getMasterRandom().nextParallelRNG(-324778);
|
||||
lakeRandom = iris.getMasterRandom().nextParallelRNG(-868778);
|
||||
seaProvider = new BiomeDataProvider(this, InferredType.SEA, rng);
|
||||
landProvider = new BiomeDataProvider(this, InferredType.LAND, rng);
|
||||
shoreProvider = new BiomeDataProvider(this, InferredType.SHORE, rng);
|
||||
caveProvider = new BiomeDataProvider(this, InferredType.CAVE, rng);
|
||||
riverProvider = new BiomeDataProvider(this, InferredType.RIVER, rng);
|
||||
lakeProvider = new BiomeDataProvider(this, InferredType.LAKE, rng);
|
||||
regionGenerator = iris.getDimension().getRegionStyle().create(rng.nextParallelRNG(1188519)).bake().scale(1D / iris.getDimension().getRegionZoom());
|
||||
bridgeGenerator = iris.getDimension().getContinentalStyle().create(rng.nextParallelRNG(1541462)).bake().scale(1D / iris.getDimension().getContinentZoom());
|
||||
}
|
||||
@ -86,6 +94,16 @@ public class GenLayerBiome extends GenLayer
|
||||
return caveProvider;
|
||||
}
|
||||
|
||||
else if(type.equals(InferredType.RIVER))
|
||||
{
|
||||
return riverProvider;
|
||||
}
|
||||
|
||||
else if(type.equals(InferredType.LAKE))
|
||||
{
|
||||
return lakeProvider;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Iris.error("Cannot find a BiomeDataProvider for type " + type.name());
|
||||
@ -99,12 +117,13 @@ public class GenLayerBiome extends GenLayer
|
||||
return generateData(getType(bx, bz, regionData), bx, bz, rawX, rawZ, regionData);
|
||||
}
|
||||
|
||||
public InferredType getType(double bx, double bz, IrisRegion regionData)
|
||||
public InferredType getType(double bx, double bz, IrisRegion region)
|
||||
{
|
||||
double x = bx;
|
||||
double z = bz;
|
||||
double c = iris.getDimension().getLandChance();
|
||||
InferredType bridge;
|
||||
|
||||
if(c >= 1)
|
||||
{
|
||||
bridge = InferredType.LAND;
|
||||
@ -117,6 +136,16 @@ public class GenLayerBiome extends GenLayer
|
||||
|
||||
bridge = bridgeGenerator.fitDouble(0, 1, x, z) < c ? InferredType.LAND : InferredType.SEA;
|
||||
|
||||
if(bridge.equals(InferredType.LAND) && region.isLake(lakeRandom, x, z))
|
||||
{
|
||||
bridge = InferredType.LAKE;
|
||||
}
|
||||
|
||||
if(bridge.equals(InferredType.LAND) && region.isRiver(riverRandom, x, z))
|
||||
{
|
||||
bridge = InferredType.RIVER;
|
||||
}
|
||||
|
||||
return bridge;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ public class PostFloatingNibDeleter extends IrisPostBlockFilter
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int ha = highestTerrainBlock(x + 1, z);
|
||||
int hb = highestTerrainBlock(x, z + 1);
|
||||
int hc = highestTerrainBlock(x - 1, z);
|
||||
|
@ -16,6 +16,12 @@ public enum InferredType
|
||||
@DontObfuscate
|
||||
CAVE,
|
||||
|
||||
@DontObfuscate
|
||||
RIVER,
|
||||
|
||||
@DontObfuscate
|
||||
LAKE,
|
||||
|
||||
@DontObfuscate
|
||||
DEFER;
|
||||
}
|
||||
|
@ -438,6 +438,29 @@ public class IrisBiome extends IrisRegistrant implements IRare
|
||||
return inferredType.equals(InferredType.SEA);
|
||||
}
|
||||
|
||||
public boolean isLake()
|
||||
{
|
||||
if(inferredType == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return inferredType.equals(InferredType.LAKE);
|
||||
}
|
||||
|
||||
public boolean isRiver()
|
||||
{
|
||||
if(inferredType == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return inferredType.equals(InferredType.RIVER);
|
||||
}
|
||||
|
||||
public boolean isAquatic()
|
||||
{
|
||||
return isSea() || isLake() || isRiver();
|
||||
}
|
||||
|
||||
public boolean isShore()
|
||||
{
|
||||
if(inferredType == null)
|
||||
|
@ -101,6 +101,14 @@ public class IrisDimension extends IrisRegistrant
|
||||
@Desc("The placement style of biomes")
|
||||
private IrisGeneratorStyle caveBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||
|
||||
@DontObfuscate
|
||||
@Desc("The placement style of biomes")
|
||||
private IrisGeneratorStyle riverBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||
|
||||
@DontObfuscate
|
||||
@Desc("The placement style of biomes")
|
||||
private IrisGeneratorStyle lakeBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||
|
||||
@DontObfuscate
|
||||
@Desc("The placement style of biomes")
|
||||
private IrisGeneratorStyle islandBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||
@ -755,6 +763,10 @@ public class IrisDimension extends IrisRegistrant
|
||||
{
|
||||
case CAVE:
|
||||
return caveBiomeStyle;
|
||||
case LAKE:
|
||||
return lakeBiomeStyle;
|
||||
case RIVER:
|
||||
return riverBiomeStyle;
|
||||
case LAND:
|
||||
return landBiomeStyle;
|
||||
case SEA:
|
||||
|
@ -15,7 +15,6 @@ import lombok.Data;
|
||||
@Data
|
||||
public class IrisGeneratorStyle
|
||||
{
|
||||
|
||||
@Required
|
||||
@DontObfuscate
|
||||
@Desc("The chance is 1 in CHANCE per interval")
|
||||
@ -53,6 +52,12 @@ public class IrisGeneratorStyle
|
||||
this.style = s;
|
||||
}
|
||||
|
||||
public IrisGeneratorStyle zoomed(double z)
|
||||
{
|
||||
this.zoom = z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CNG create(RNG rng)
|
||||
{
|
||||
return cng.aquire(() ->
|
||||
|
@ -322,7 +322,7 @@ public class IrisObject extends IrisRegistrant
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(config.isBore() && !config.getMode().equals(ObjectPlaceMode.PAINT))
|
||||
if(config.isBore())
|
||||
{
|
||||
for(int i = x - Math.floorDiv(w, 2); i <= x + Math.floorDiv(w, 2) - (w % 2 == 0 ? 1 : 0); i++)
|
||||
{
|
||||
@ -330,10 +330,7 @@ public class IrisObject extends IrisRegistrant
|
||||
{
|
||||
for(int k = z - Math.floorDiv(d, 2); k <= z + Math.floorDiv(d, 2) - (d % 2 == 0 ? 1 : 0); k++)
|
||||
{
|
||||
if(!B.isAir(placer.get(i, j, k)))
|
||||
{
|
||||
placer.set(i, j, k, AIR);
|
||||
}
|
||||
placer.set(i, j, k, AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ public class IrisRegion extends IrisRegistrant implements IRare
|
||||
@Desc("Place text on terrain")
|
||||
@ArrayType(min = 1, type = IrisTextPlacement.class)
|
||||
private KList<IrisTextPlacement> text = new KList<>();
|
||||
|
||||
|
||||
@ArrayType(min = 1, type = IrisBlockDrops.class)
|
||||
@DontObfuscate
|
||||
@Desc("Define custom block drops for this region")
|
||||
@ -87,6 +87,16 @@ public class IrisRegion extends IrisRegistrant implements IRare
|
||||
@Desc("How large shore biomes are in this region")
|
||||
private double shoreBiomeZoom = 1;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@DontObfuscate
|
||||
@Desc("How large lake biomes are in this region")
|
||||
private double lakeBiomeZoom = 1;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@DontObfuscate
|
||||
@Desc("How large river biomes are in this region")
|
||||
private double riverBiomeZoom = 1;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@DontObfuscate
|
||||
@Desc("How large sea biomes are in this region")
|
||||
@ -129,6 +139,18 @@ public class IrisRegion extends IrisRegistrant implements IRare
|
||||
@Desc("A list of root-level biomes in this region. Don't specify child biomes of other biomes here. Just the root parents.")
|
||||
private KList<String> shoreBiomes = new KList<>();
|
||||
|
||||
@RegistryListBiome
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
@DontObfuscate
|
||||
@Desc("A list of root-level biomes in this region. Don't specify child biomes of other biomes here. Just the root parents.")
|
||||
private KList<String> riverBiomes = new KList<>();
|
||||
|
||||
@RegistryListBiome
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
@DontObfuscate
|
||||
@Desc("A list of root-level biomes in this region. Don't specify child biomes of other biomes here. Just the root parents.")
|
||||
private KList<String> lakeBiomes = new KList<>();
|
||||
|
||||
@RegistryListBiome
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
@DontObfuscate
|
||||
@ -149,13 +171,99 @@ public class IrisRegion extends IrisRegistrant implements IRare
|
||||
@Desc("Define regional deposit generators that add onto the global deposit generators")
|
||||
private KList<IrisDepositGenerator> deposits = new KList<>();
|
||||
|
||||
@DontObfuscate
|
||||
@Desc("The style of rivers")
|
||||
private IrisGeneratorStyle riverStyle = NoiseStyle.VASCULAR_THIN.style().zoomed(7.77);
|
||||
|
||||
@DontObfuscate
|
||||
@Desc("The style of lakes")
|
||||
private IrisGeneratorStyle lakeStyle = NoiseStyle.CELLULAR_IRIS_THICK.style();
|
||||
|
||||
@DontObfuscate
|
||||
@Desc("The style of river chances")
|
||||
private IrisGeneratorStyle riverChanceStyle = NoiseStyle.SIMPLEX.style().zoomed(4);
|
||||
|
||||
@DontObfuscate
|
||||
@Desc("Generate lakes in this region")
|
||||
private boolean lakes = true;
|
||||
|
||||
@DontObfuscate
|
||||
@Desc("Generate rivers in this region")
|
||||
private boolean rivers = true;
|
||||
|
||||
@MinNumber(1)
|
||||
@DontObfuscate
|
||||
@Desc("Generate lakes in this region")
|
||||
private int lakeRarity = 22;
|
||||
|
||||
@MinNumber(1)
|
||||
@DontObfuscate
|
||||
@Desc("Generate rivers in this region")
|
||||
private int riverRarity = 3;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1)
|
||||
@DontObfuscate
|
||||
@Desc("Generate rivers in this region")
|
||||
private double riverThickness = 0.1;
|
||||
|
||||
private transient AtomicCache<KList<String>> cacheRidge = new AtomicCache<>();
|
||||
private transient AtomicCache<KList<String>> cacheSpot = new AtomicCache<>();
|
||||
private transient AtomicCache<CNG> shoreHeightGenerator = new AtomicCache<>();
|
||||
private transient AtomicCache<KList<IrisBiome>> realLandBiomes = new AtomicCache<>();
|
||||
private transient AtomicCache<KList<IrisBiome>> realLakeBiomes = new AtomicCache<>();
|
||||
private transient AtomicCache<KList<IrisBiome>> realRiverBiomes = new AtomicCache<>();
|
||||
private transient AtomicCache<KList<IrisBiome>> realSeaBiomes = new AtomicCache<>();
|
||||
private transient AtomicCache<KList<IrisBiome>> realShoreBiomes = new AtomicCache<>();
|
||||
private transient AtomicCache<KList<IrisBiome>> realCaveBiomes = new AtomicCache<>();
|
||||
private transient AtomicCache<CNG> lakeGen = new AtomicCache<>();
|
||||
private transient AtomicCache<CNG> riverGen = new AtomicCache<>();
|
||||
private transient AtomicCache<CNG> riverChanceGen = new AtomicCache<>();
|
||||
|
||||
public boolean isRiver(RNG rng, double x, double z)
|
||||
{
|
||||
if(!isRivers())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(getRiverBiomes().isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(getRiverChanceGen().aquire(() -> getRiverChanceStyle().create(rng)).fit(1, getRiverRarity(), x, z) != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(getRiverGen().aquire(() -> getRiverStyle().create(rng)).fitDouble(0, 1, x, z) < getRiverThickness())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isLake(RNG rng, double x, double z)
|
||||
{
|
||||
if(!isLakes())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(getLakeBiomes().isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(getLakeGen().aquire(() -> getLakeStyle().create(rng)).fit(1, getLakeRarity(), x, z) == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public double getBiomeZoom(InferredType t)
|
||||
{
|
||||
@ -163,6 +271,10 @@ public class IrisRegion extends IrisRegistrant implements IRare
|
||||
{
|
||||
case CAVE:
|
||||
return caveBiomeZoom;
|
||||
case LAKE:
|
||||
return lakeBiomeZoom;
|
||||
case RIVER:
|
||||
return riverBiomeZoom;
|
||||
case LAND:
|
||||
return landBiomeZoom;
|
||||
case SEA:
|
||||
@ -263,6 +375,16 @@ public class IrisRegion extends IrisRegistrant implements IRare
|
||||
return getRealCaveBiomes(g);
|
||||
}
|
||||
|
||||
else if(type.equals(InferredType.LAKE))
|
||||
{
|
||||
return getRealLakeBiomes(g);
|
||||
}
|
||||
|
||||
else if(type.equals(InferredType.RIVER))
|
||||
{
|
||||
return getRealRiverBiomes(g);
|
||||
}
|
||||
|
||||
return new KList<>();
|
||||
}
|
||||
|
||||
@ -281,6 +403,36 @@ public class IrisRegion extends IrisRegistrant implements IRare
|
||||
});
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getRealLakeBiomes(ContextualChunkGenerator g)
|
||||
{
|
||||
return realLakeBiomes.aquire(() ->
|
||||
{
|
||||
KList<IrisBiome> realLakeBiomes = new KList<>();
|
||||
|
||||
for(String i : getLakeBiomes())
|
||||
{
|
||||
realLakeBiomes.add((g == null ? Iris.globaldata : g.getData()).getBiomeLoader().load(i));
|
||||
}
|
||||
|
||||
return realLakeBiomes;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getRealRiverBiomes(ContextualChunkGenerator g)
|
||||
{
|
||||
return realRiverBiomes.aquire(() ->
|
||||
{
|
||||
KList<IrisBiome> realRiverBiomes = new KList<>();
|
||||
|
||||
for(String i : getRiverBiomes())
|
||||
{
|
||||
realRiverBiomes.add((g == null ? Iris.globaldata : g.getData()).getBiomeLoader().load(i));
|
||||
}
|
||||
|
||||
return realRiverBiomes;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getRealShoreBiomes(ContextualChunkGenerator g)
|
||||
{
|
||||
return realShoreBiomes.aquire(() ->
|
||||
|
@ -130,11 +130,6 @@ public class IrisStructurePlacement
|
||||
|
||||
if(t != null)
|
||||
{
|
||||
if(height >= 0)
|
||||
{
|
||||
t.getPlacement().setBore(true);
|
||||
}
|
||||
|
||||
IrisObject o = null;
|
||||
|
||||
for(IrisRareObject l : t.getTile().getRareObjects())
|
||||
|
@ -26,7 +26,7 @@ public class IrisStructureTile
|
||||
|
||||
@DontObfuscate
|
||||
@Desc("The place mode for this tile")
|
||||
private ObjectPlaceMode placeMode = ObjectPlaceMode.PAINT;
|
||||
private ObjectPlaceMode placeMode = ObjectPlaceMode.CENTER_HEIGHT;
|
||||
|
||||
@Required
|
||||
@DontObfuscate
|
||||
|
Loading…
x
Reference in New Issue
Block a user