mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-04-08 08:46:21 +00:00
Restructure Packages (read commit description)
There are now three root packages - Engine: Generator & JSON Scaffolding - Core: Managers, Commands, NMS - Util: Random utility packages
This commit is contained in:
46
src/main/java/com/volmit/iris/engine/object/CarvingMode.java
Normal file
46
src/main/java/com/volmit/iris/engine/object/CarvingMode.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
|
||||
@Desc("Defines if an object is allowed to place in carvings, surfaces or both.")
|
||||
public enum CarvingMode {
|
||||
@Desc("Only place this object on surfaces (NOT under carvings)")
|
||||
|
||||
SURFACE_ONLY,
|
||||
|
||||
@Desc("Only place this object under carvings (NOT on the surface)")
|
||||
|
||||
CARVING_ONLY,
|
||||
|
||||
@Desc("This object can place anywhere")
|
||||
|
||||
ANYWHERE;
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean supportsCarving() {
|
||||
return this.equals(ANYWHERE) || this.equals(CARVING_ONLY);
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean supportsSurface() {
|
||||
return this.equals(ANYWHERE) || this.equals(SURFACE_ONLY);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
|
||||
@Desc("Represents a location where decorations should go")
|
||||
public enum DecorationPart {
|
||||
@Desc("The default, decorate anywhere")
|
||||
|
||||
NONE,
|
||||
|
||||
@Desc("Targets shore lines (typically for sugar cane)")
|
||||
|
||||
SHORE_LINE,
|
||||
|
||||
@Desc("Target sea surfaces (typically for lilypads)")
|
||||
|
||||
SEA_SURFACE,
|
||||
|
||||
@Desc("Targets the sea floor (entire placement must be bellow sea level)")
|
||||
|
||||
SEA_FLOOR,
|
||||
|
||||
@Desc("Decorates on cave & carving ceilings or underside of overhangs")
|
||||
|
||||
CEILING,
|
||||
}
|
||||
36
src/main/java/com/volmit/iris/engine/object/FontStyle.java
Normal file
36
src/main/java/com/volmit/iris/engine/object/FontStyle.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
|
||||
@Desc("Represents a basic font style to apply to a font family")
|
||||
public enum FontStyle {
|
||||
@Desc("Plain old text")
|
||||
|
||||
PLAIN,
|
||||
|
||||
@Desc("Italicized Text")
|
||||
|
||||
ITALIC,
|
||||
|
||||
@Desc("Bold Text")
|
||||
|
||||
BOLD,
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
|
||||
@Desc("Represents a biome type")
|
||||
public enum InferredType {
|
||||
@Desc("Represents any shore biome type")
|
||||
|
||||
SHORE,
|
||||
|
||||
@Desc("Represents any land biome type")
|
||||
|
||||
LAND,
|
||||
|
||||
@Desc("Represents any sea biome type")
|
||||
|
||||
SEA,
|
||||
|
||||
@Desc("Represents any cave biome type")
|
||||
|
||||
CAVE,
|
||||
|
||||
@Desc("Represents any river biome type")
|
||||
|
||||
RIVER,
|
||||
|
||||
@Desc("Represents any lake biome type")
|
||||
|
||||
LAKE,
|
||||
|
||||
@Desc("Defers the type to whatever another biome type that already exists is.")
|
||||
|
||||
DEFER
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
|
||||
@Desc("An interpolation method (or function) is simply a method of smoothing a position based on surrounding points on a grid. Bicubic for example is smoother, but has 4 times the checks than Bilinear for example. Try using BILINEAR_STARCAST_9 for beautiful results.")
|
||||
public enum InterpolationMethod {
|
||||
@Desc("No interpolation. Nearest Neighbor (bad for terrain, great for performance).")
|
||||
|
||||
NONE,
|
||||
|
||||
@Desc("Uses 4 nearby points in a square to calculate a 2d slope. Very fast but creates square artifacts. See: https://en.wikipedia.org/wiki/Bilinear_interpolation")
|
||||
|
||||
BILINEAR,
|
||||
|
||||
@Desc("Starcast is Iris's own creation. It uses raytrace checks to find a horizontal boundary nearby. 3 Checks in a circle. Typically starcast is used with another interpolation method. See BILINEAR_STARCAST_9 For example. Starcast is meant to 'break up' large, abrupt cliffs to make cheap interpolation smoother.")
|
||||
|
||||
STARCAST_3,
|
||||
|
||||
@Desc("Starcast is Iris's own creation. It uses raytrace checks to find a horizontal boundary nearby. 6 Checks in a circle. Typically starcast is used with another interpolation method. See BILINEAR_STARCAST_9 For example. Starcast is meant to 'break up' large, abrupt cliffs to make cheap interpolation smoother.")
|
||||
|
||||
STARCAST_6,
|
||||
|
||||
@Desc("Starcast is Iris's own creation. It uses raytrace checks to find a horizontal boundary nearby. 9 Checks in a circle. Typically starcast is used with another interpolation method. See BILINEAR_STARCAST_9 For example. Starcast is meant to 'break up' large, abrupt cliffs to make cheap interpolation smoother.")
|
||||
|
||||
STARCAST_9,
|
||||
|
||||
@Desc("Starcast is Iris's own creation. It uses raytrace checks to find a horizontal boundary nearby. 12 Checks in a circle. Typically starcast is used with another interpolation method. See BILINEAR_STARCAST_9 For example. Starcast is meant to 'break up' large, abrupt cliffs to make cheap interpolation smoother.")
|
||||
|
||||
STARCAST_12,
|
||||
|
||||
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with bilinear.")
|
||||
|
||||
BILINEAR_STARCAST_3,
|
||||
|
||||
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with bilinear.")
|
||||
|
||||
BILINEAR_STARCAST_6,
|
||||
|
||||
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with bilinear.")
|
||||
|
||||
BILINEAR_STARCAST_9,
|
||||
|
||||
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with bilinear.")
|
||||
|
||||
BILINEAR_STARCAST_12,
|
||||
|
||||
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with hermite.")
|
||||
|
||||
HERMITE_STARCAST_3,
|
||||
|
||||
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with hermite.")
|
||||
|
||||
HERMITE_STARCAST_6,
|
||||
|
||||
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with hermite.")
|
||||
|
||||
HERMITE_STARCAST_9,
|
||||
|
||||
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with hermite.")
|
||||
|
||||
HERMITE_STARCAST_12,
|
||||
|
||||
@Desc("Uses bilinear but on a bezier curve. See: https://en.wikipedia.org/wiki/Bezier_curve")
|
||||
|
||||
BILINEAR_BEZIER,
|
||||
|
||||
@Desc("Uses Bilinear but with parametric curves alpha 2.")
|
||||
|
||||
BILINEAR_PARAMETRIC_2,
|
||||
|
||||
@Desc("Uses Bilinear but with parametric curves alpha 4.")
|
||||
|
||||
BILINEAR_PARAMETRIC_4,
|
||||
|
||||
@Desc("Uses Bilinear but with parametric curves alpha 1.5.")
|
||||
|
||||
BILINEAR_PARAMETRIC_1_5,
|
||||
|
||||
@Desc("Bicubic noise creates 4, 4-point splines for a total of 16 checks. Bcubic can go higher than expected and lower than expected right before a large change in slope.")
|
||||
|
||||
BICUBIC,
|
||||
|
||||
@Desc("Hermite is similar to bicubic, but faster and it can be tuned a little bit")
|
||||
|
||||
HERMITE,
|
||||
|
||||
@Desc("Essentially bicubic with zero tension")
|
||||
|
||||
CATMULL_ROM_SPLINE,
|
||||
|
||||
@Desc("Essentially bicubic with max tension")
|
||||
|
||||
HERMITE_TENSE,
|
||||
|
||||
@Desc("Hermite is similar to bicubic, this variant reduces the dimple artifacts of bicubic")
|
||||
|
||||
HERMITE_LOOSE,
|
||||
|
||||
@Desc("Hermite is similar to bicubic, this variant reduces the dimple artifacts of bicubic")
|
||||
|
||||
HERMITE_LOOSE_HALF_POSITIVE_BIAS,
|
||||
|
||||
@Desc("Hermite is similar to bicubic, this variant reduces the dimple artifacts of bicubic")
|
||||
|
||||
HERMITE_LOOSE_HALF_NEGATIVE_BIAS,
|
||||
|
||||
@Desc("Hermite is similar to bicubic, this variant reduces the dimple artifacts of bicubic")
|
||||
|
||||
HERMITE_LOOSE_FULL_POSITIVE_BIAS,
|
||||
|
||||
@Desc("Hermite is similar to bicubic, this variant reduces the dimple artifacts of bicubic")
|
||||
|
||||
HERMITE_LOOSE_FULL_NEGATIVE_BIAS,
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
|
||||
@Desc("An inventory slot type is used to represent a type of slot for items to fit into in any given inventory.")
|
||||
public enum InventorySlotType {
|
||||
@Desc("Typically the one you want to go with. Storage represnents most slots in inventories.")
|
||||
|
||||
STORAGE,
|
||||
|
||||
@Desc("Used for the fuel slot in Furnaces, Blast furnaces, smokers etc.")
|
||||
|
||||
FUEL,
|
||||
|
||||
@Desc("Used for the cook slot in furnaces")
|
||||
|
||||
FURNACE,
|
||||
|
||||
@Desc("Used for the cook slot in blast furnaces")
|
||||
|
||||
BLAST_FURNACE,
|
||||
|
||||
@Desc("Used for the cook slot in smokers")
|
||||
|
||||
SMOKER,
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.attribute.Attributable;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeModifier;
|
||||
import org.bukkit.attribute.AttributeModifier.Operation;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Desc("Represents an attribute modifier for an item or an entity. This allows you to create modifications to basic game attributes such as MAX_HEALTH or ARMOR_VALUE.")
|
||||
@Data
|
||||
public class IrisAttributeModifier {
|
||||
@Required
|
||||
|
||||
@Desc("The Attribute type. This type is pulled from the game attributes. Zombie & Horse attributes will not work on non-zombie/horse entities.\nUsing an attribute on an item will have affects when held, or worn. There is no way to specify further granularity as the game picks this depending on the item type.")
|
||||
private Attribute attribute = null;
|
||||
|
||||
@MinNumber(2)
|
||||
@Required
|
||||
|
||||
|
||||
@Desc("The Attribute Name is used internally only for the game. This value should be unique to all other attributes applied to this item/entity. It is not shown in game.")
|
||||
private String name = "";
|
||||
|
||||
@Desc("The application operation (add number is default). Add Number adds to the default value. \nAdd scalar_1 will multiply by 1 for example if the health is 20 and you multiply_scalar_1 by 0.5, the health will result in 30, not 10. Use negative values to achieve that.")
|
||||
private Operation operation = Operation.ADD_NUMBER;
|
||||
|
||||
@Desc("Minimum amount for this modifier. Iris randomly chooses an amount, this is the minimum it can choose randomly for this attribute.")
|
||||
private double minAmount = 1;
|
||||
|
||||
@Desc("Maximum amount for this modifier Iris randomly chooses an amount, this is the maximum it can choose randomly for this attribute.")
|
||||
private double maxAmount = 1;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1)
|
||||
@Desc("The chance that this attribute is applied (0 to 1). If the chance is 0.5 (50%), then Iris will only apply this attribute 50% of the time.")
|
||||
private double chance = 1;
|
||||
|
||||
public void apply(RNG rng, ItemMeta meta) {
|
||||
if (rng.nextDouble() < getChance()) {
|
||||
meta.addAttributeModifier(getAttribute(), new AttributeModifier(getName(), getAmount(rng), getOperation()));
|
||||
}
|
||||
}
|
||||
|
||||
public void apply(RNG rng, Attributable meta) {
|
||||
if (rng.nextDouble() < getChance()) {
|
||||
meta.getAttribute(getAttribute()).addModifier(new AttributeModifier(getName(), getAmount(rng), getOperation()));
|
||||
}
|
||||
}
|
||||
|
||||
public double getAmount(RNG rng) {
|
||||
return rng.d(getMinAmount(), getMaxAmount());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Desc("Represents a rotation axis with intervals and maxes. The x and z axis values are defaulted to disabled. The Y axis defaults to on, rotating by 90 degree increments.")
|
||||
@Data
|
||||
public class IrisAxisRotationClamp {
|
||||
|
||||
@Desc("Should this axis be rotated at all?")
|
||||
private boolean enabled = false;
|
||||
private transient boolean forceLock = false;
|
||||
|
||||
@Required
|
||||
@DependsOn({"max"})
|
||||
@MinNumber(-360)
|
||||
@MaxNumber(360)
|
||||
@Desc("The minimum angle (from) or set this and max to zero for any angle degrees. Set both to the same non-zero value to force it to that angle only")
|
||||
private double min = 0;
|
||||
|
||||
@Required
|
||||
@DependsOn({"min"})
|
||||
@MinNumber(-360)
|
||||
@MaxNumber(360)
|
||||
@Desc("The maximum angle (to) or set this and min to zero for any angle degrees. Set both to the same non-zero value to force it to that angle only")
|
||||
private double max = 0;
|
||||
|
||||
@Required
|
||||
@DependsOn({"min", "max"})
|
||||
@MinNumber(0)
|
||||
@MaxNumber(360)
|
||||
@Desc("Iris spins the axis but not freely. For example an interval of 90 would mean 4 possible angles (right angles) degrees. \nSetting this to 0 means totally free rotation.\n\nNote that a lot of structures can have issues with non 90 degree intervals because the minecraft block resolution is so low.")
|
||||
private double interval = 0;
|
||||
|
||||
public void minMax(double fd) {
|
||||
min = fd;
|
||||
max = fd;
|
||||
forceLock = true;
|
||||
}
|
||||
|
||||
public boolean isUnlimited() {
|
||||
return min == max && min == 0;
|
||||
}
|
||||
|
||||
public boolean isLocked() {
|
||||
return min == max && !isUnlimited();
|
||||
}
|
||||
|
||||
public double getRadians(int rng) {
|
||||
if (forceLock) {
|
||||
return Math.toRadians(max);
|
||||
}
|
||||
|
||||
if (isUnlimited()) {
|
||||
if (interval < 1) {
|
||||
interval = 1;
|
||||
}
|
||||
|
||||
return Math.toRadians((interval * (Math.ceil(Math.abs((rng % 360D) / interval)))) % 360D);
|
||||
}
|
||||
|
||||
if (min == max && min != 0) {
|
||||
return Math.toRadians(max);
|
||||
}
|
||||
|
||||
return Math.toRadians(M.clip((interval * (Math.ceil(Math.abs((rng % 360D) / interval)))) % 360D, Math.min(min, max), Math.max(min, max)));
|
||||
}
|
||||
}
|
||||
665
src/main/java/com/volmit/iris/engine/object/IrisBiome.java
Normal file
665
src/main/java/com/volmit/iris/engine/object/IrisBiome.java
Normal file
@@ -0,0 +1,665 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.IrisComplex;
|
||||
import com.volmit.iris.engine.noise.CNG;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.core.gui.RenderType;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.data.DataProvider;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@SuppressWarnings("DefaultAnnotationParam")
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
|
||||
@Desc("Represents a biome in iris. Biomes are placed inside of regions and hold objects.\nA biome consists of layers (block palletes), decorations, objects & generators.")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisBiome extends IrisRegistrant implements IRare {
|
||||
@MinNumber(2)
|
||||
@Required
|
||||
|
||||
@Desc("This is the human readable name for this biome. This can and should be different than the file name. This is not used for loading biomes in other objects.")
|
||||
private String name = "A Biome";
|
||||
|
||||
|
||||
@ArrayType(min = 1, type = IrisBiomeCustom.class)
|
||||
@Desc("If the biome type custom is defined, specify this")
|
||||
private KList<IrisBiomeCustom> customDerivitives;
|
||||
|
||||
|
||||
@Desc("Entity spawns to override or add to this biome. Anytime an entity spawns, it has a chance to be replaced as one of these overrides.")
|
||||
@ArrayType(min = 1, type = IrisEntitySpawnOverride.class)
|
||||
private KList<IrisEntitySpawnOverride> entitySpawnOverrides = new KList<>();
|
||||
|
||||
|
||||
@Desc("Add random chances for terrain features")
|
||||
@ArrayType(min = 1, type = IrisFeaturePotential.class)
|
||||
private KList<IrisFeaturePotential> features = new KList<>();
|
||||
|
||||
|
||||
@Desc("Entity spawns during generation")
|
||||
@ArrayType(min = 1, type = IrisEntityInitialSpawn.class)
|
||||
private KList<IrisEntityInitialSpawn> entityInitialSpawns = new KList<>();
|
||||
|
||||
@ArrayType(min = 1, type = IrisEffect.class)
|
||||
@Desc("Effects are ambient effects such as potion effects, random sounds, or even particles around each player. All of these effects are played via packets so two players won't see/hear each others effects.\nDue to performance reasons, effects will play arround the player even if where the effect was played is no longer in the biome the player is in.")
|
||||
private KList<IrisEffect> effects = new KList<>();
|
||||
|
||||
|
||||
@DependsOn({"biomeStyle", "biomeZoom", "biomeScatter"})
|
||||
@Desc("This changes the dispersion of the biome colors if multiple derivatives are chosen.")
|
||||
private IrisGeneratorStyle biomeStyle = NoiseStyle.SIMPLEX.style();
|
||||
|
||||
@ArrayType(min = 1, type = IrisBlockDrops.class)
|
||||
@Desc("Define custom block drops for this biome")
|
||||
private KList<IrisBlockDrops> blockDrops = new KList<>();
|
||||
|
||||
|
||||
@Desc("Reference loot tables in this area")
|
||||
private IrisLootReference loot = new IrisLootReference();
|
||||
|
||||
@MinNumber(0.0001)
|
||||
|
||||
@DependsOn({"biomeStyle", "biomeZoom", "biomeScatter"})
|
||||
@Desc("This zooms in the biome colors if multiple derivatives are chosen")
|
||||
private double biomeZoom = 1;
|
||||
|
||||
|
||||
@Desc("Layers no longer descend from the surface block, they descend from the max possible height the biome can produce (constant) creating mesa like layers.")
|
||||
private boolean lockLayers = false;
|
||||
|
||||
|
||||
@Desc("The max layers to iterate below the surface for locked layer biomes (mesa).")
|
||||
private int lockLayersMax = 7;
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(512)
|
||||
@Desc("The rarity of this biome (integer)")
|
||||
private int rarity = 1;
|
||||
|
||||
|
||||
@Desc("A color for visualizing this biome with a color. I.e. #F13AF5. This will show up on the map.")
|
||||
private String color = null;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The raw derivative of this biome. This is required or the terrain will not properly generate. Use any vanilla biome type. Look in examples/biome-list.txt")
|
||||
private Biome derivative = Biome.THE_VOID;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("Override the derivative when vanilla places structures to this derivative. This is useful for example if you have an ocean biome, but you have set the derivative to desert to get a brown-ish color. To prevent desert structures from spawning on top of your ocean, you can set your vanillaDerivative to ocean, to allow for vanilla structures. Not defining this value will simply select the derivative.")
|
||||
private Biome vanillaDerivative = null;
|
||||
|
||||
@ArrayType(min = 1, type = Biome.class)
|
||||
@Desc("You can instead specify multiple biome derivatives to randomly scatter colors in this biome")
|
||||
private KList<Biome> biomeScatter = new KList<>();
|
||||
|
||||
@ArrayType(min = 1, type = Biome.class)
|
||||
@Desc("Since 1.13 supports 3D biomes, you can add different derivative colors for anything above the terrain. (Think swampy tree leaves with a desert looking grass surface)")
|
||||
private KList<Biome> biomeSkyScatter = new KList<>();
|
||||
|
||||
|
||||
@DependsOn({"children"})
|
||||
@Desc("If this biome has children biomes, and the gen layer chooses one of this biomes children, how much smaller will it be (inside of this biome). Higher values means a smaller biome relative to this biome's size. Set higher than 1.0 and below 3.0 for best results.")
|
||||
private double childShrinkFactor = 1.5;
|
||||
|
||||
|
||||
@DependsOn({"children"})
|
||||
@Desc("If this biome has children biomes, and the gen layer chooses one of this biomes children, How will it be shaped?")
|
||||
private IrisGeneratorStyle childStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||
|
||||
@RegistryListBiome
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
@Desc("List any biome names (file names without.json) here as children. Portions of this biome can sometimes morph into their children. Iris supports cyclic relationships such as A > B > A > B. Iris will stop checking 9 biomes down the tree.")
|
||||
private KList<String> children = new KList<>();
|
||||
|
||||
@ArrayType(min = 1, type = IrisJigsawStructurePlacement.class)
|
||||
@Desc("Jigsaw structures")
|
||||
private KList<IrisJigsawStructurePlacement> jigsawStructures = new KList<>();
|
||||
|
||||
@RegistryListBiome
|
||||
|
||||
@Desc("The carving biome. If specified the biome will be used when under a carving instead of this current biome.")
|
||||
private String carvingBiome = "";
|
||||
|
||||
|
||||
@Desc("The default slab if iris decides to place a slab in this biome. Default is no slab.")
|
||||
private IrisBiomePaletteLayer slab = new IrisBiomePaletteLayer().zero();
|
||||
|
||||
|
||||
@Desc("The default wall if iris decides to place a wall higher than 2 blocks (steep hills or possibly cliffs)")
|
||||
private IrisBiomePaletteLayer wall = new IrisBiomePaletteLayer().zero();
|
||||
|
||||
@Required
|
||||
@ArrayType(min = 1, type = IrisBiomePaletteLayer.class)
|
||||
@Desc("This defines the layers of materials in this biome. Each layer has a palette and min/max height and some other properties. Usually a grassy/sandy layer then a dirt layer then a stone layer. Iris will fill in the remaining blocks below your layers with stone.")
|
||||
private KList<IrisBiomePaletteLayer> layers = new KList<IrisBiomePaletteLayer>().qadd(new IrisBiomePaletteLayer());
|
||||
|
||||
@ArrayType(min = 1, type = IrisBiomePaletteLayer.class)
|
||||
@Desc("This defines the layers of materials in this biome. Each layer has a palette and min/max height and some other properties. Usually a grassy/sandy layer then a dirt layer then a stone layer. Iris will fill in the remaining blocks below your layers with stone.")
|
||||
private KList<IrisBiomePaletteLayer> seaLayers = new KList<>();
|
||||
|
||||
@ArrayType(min = 1, type = IrisDecorator.class)
|
||||
@Desc("Decorators are used for things like tall grass, bisected flowers, and even kelp or cactus (random heights)")
|
||||
private KList<IrisDecorator> decorators = new KList<>();
|
||||
|
||||
@ArrayType(min = 1, type = IrisObjectPlacement.class)
|
||||
@Desc("Objects define what schematics (iob files) iris will place in this biome")
|
||||
private KList<IrisObjectPlacement> objects = new KList<>();
|
||||
|
||||
@Required
|
||||
@ArrayType(min = 1, type = IrisBiomeGeneratorLink.class)
|
||||
@Desc("Generators for this biome. Multiple generators with different interpolation sizes will mix with other biomes how you would expect. This defines your biome height relative to the fluid height. Use negative for oceans.")
|
||||
private KList<IrisBiomeGeneratorLink> generators = new KList<IrisBiomeGeneratorLink>().qadd(new IrisBiomeGeneratorLink());
|
||||
|
||||
@ArrayType(min = 1, type = IrisDepositGenerator.class)
|
||||
@Desc("Define biome deposit generators that add onto the existing regional and global deposit generators")
|
||||
private KList<IrisDepositGenerator> deposits = new KList<>();
|
||||
|
||||
private transient InferredType inferredType;
|
||||
|
||||
private final transient AtomicCache<KMap<String, IrisBiomeGeneratorLink>> genCache = new AtomicCache<>();
|
||||
private final transient AtomicCache<KMap<String, Integer>> genCacheMax = new AtomicCache<>();
|
||||
private final transient AtomicCache<KMap<String, Integer>> genCacheMin = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<IrisObjectPlacement>> surfaceObjectsCache = new AtomicCache<>(false);
|
||||
private final transient AtomicCache<KList<IrisObjectPlacement>> carveObjectsCache = new AtomicCache<>(false);
|
||||
private final transient AtomicCache<Color> cacheColor = new AtomicCache<>();
|
||||
private final transient AtomicCache<Color> cacheColorObjectDensity = new AtomicCache<>();
|
||||
private final transient AtomicCache<Color> cacheColorDecoratorLoad = new AtomicCache<>();
|
||||
private final transient AtomicCache<Color> cacheColorLayerLoad = new AtomicCache<>();
|
||||
private final transient AtomicCache<Color> cacheColorDepositLoad = new AtomicCache<>();
|
||||
private final transient AtomicCache<CNG> childrenCell = new AtomicCache<>();
|
||||
private final transient AtomicCache<CNG> biomeGenerator = new AtomicCache<>();
|
||||
private final transient AtomicCache<Integer> maxHeight = new AtomicCache<>();
|
||||
private final transient AtomicCache<IrisBiome> realCarveBiome = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<IrisBiome>> realChildren = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<CNG>> layerHeightGenerators = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<CNG>> layerSeaHeightGenerators = new AtomicCache<>();
|
||||
|
||||
public Biome getVanillaDerivative() {
|
||||
return vanillaDerivative == null ? derivative : vanillaDerivative;
|
||||
}
|
||||
|
||||
public boolean isCustom() {
|
||||
return getCustomDerivitives() != null && getCustomDerivitives().isNotEmpty();
|
||||
}
|
||||
|
||||
public double getGenLinkMax(String loadKey) {
|
||||
Integer v = genCacheMax.aquire(() ->
|
||||
{
|
||||
KMap<String, Integer> l = new KMap<>();
|
||||
|
||||
for (IrisBiomeGeneratorLink i : getGenerators()) {
|
||||
l.put(i.getGenerator(), i.getMax());
|
||||
}
|
||||
|
||||
return l;
|
||||
}).get(loadKey);
|
||||
|
||||
return v == null ? 0 : v;
|
||||
}
|
||||
|
||||
public double getGenLinkMin(String loadKey) {
|
||||
Integer v = genCacheMin.aquire(() ->
|
||||
{
|
||||
KMap<String, Integer> l = new KMap<>();
|
||||
|
||||
for (IrisBiomeGeneratorLink i : getGenerators()) {
|
||||
l.put(i.getGenerator(), i.getMin());
|
||||
}
|
||||
|
||||
return l;
|
||||
}).get(loadKey);
|
||||
|
||||
return v == null ? 0 : v;
|
||||
}
|
||||
|
||||
public IrisBiomeGeneratorLink getGenLink(String loadKey) {
|
||||
return genCache.aquire(() ->
|
||||
{
|
||||
KMap<String, IrisBiomeGeneratorLink> l = new KMap<>();
|
||||
|
||||
for (IrisBiomeGeneratorLink i : getGenerators()) {
|
||||
l.put(i.getGenerator(), i);
|
||||
}
|
||||
|
||||
return l;
|
||||
}).get(loadKey);
|
||||
}
|
||||
|
||||
public IrisBiome getRealCarvingBiome(IrisDataManager data) {
|
||||
return realCarveBiome.aquire(() ->
|
||||
{
|
||||
IrisBiome biome = data.getBiomeLoader().load(getCarvingBiome());
|
||||
|
||||
if (biome == null) {
|
||||
biome = this;
|
||||
}
|
||||
|
||||
return biome;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<IrisObjectPlacement> getSurfaceObjects() {
|
||||
return getSurfaceObjectsCache().aquire(() ->
|
||||
{
|
||||
KList<IrisObjectPlacement> o = getObjects().copy();
|
||||
|
||||
for (IrisObjectPlacement i : o.copy()) {
|
||||
if (!i.getCarvingSupport().supportsSurface()) {
|
||||
o.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
return o;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<IrisObjectPlacement> getCarvingObjects() {
|
||||
return getCarveObjectsCache().aquire(() ->
|
||||
{
|
||||
KList<IrisObjectPlacement> o = getObjects().copy();
|
||||
|
||||
for (IrisObjectPlacement i : o.copy()) {
|
||||
if (!i.getCarvingSupport().supportsCarving()) {
|
||||
o.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
return o;
|
||||
});
|
||||
}
|
||||
|
||||
public double getHeight(IrisAccess xg, double x, double z, long seed) {
|
||||
double height = 0;
|
||||
|
||||
for (IrisBiomeGeneratorLink i : generators) {
|
||||
height += i.getHeight(xg, x, z, seed);
|
||||
}
|
||||
|
||||
return Math.max(0, Math.min(height, 255));
|
||||
}
|
||||
|
||||
public CNG getBiomeGenerator(RNG random) {
|
||||
return biomeGenerator.aquire(() ->
|
||||
biomeStyle.create(random.nextParallelRNG(213949 + 228888 + getRarity() + getName().length())));
|
||||
}
|
||||
|
||||
public CNG getChildrenGenerator(RNG random, int sig, double scale) {
|
||||
return childrenCell.aquire(() -> getChildStyle().create(random.nextParallelRNG(sig * 2137)).bake().scale(scale).bake());
|
||||
}
|
||||
|
||||
public KList<BlockData> generateLayers(double wx, double wz, RNG random, int maxDepth, int height, IrisDataManager rdata, IrisComplex complex) {
|
||||
if (isLockLayers()) {
|
||||
return generateLockedLayers(wx, wz, random, maxDepth, height, rdata, complex);
|
||||
}
|
||||
|
||||
KList<BlockData> data = new KList<>();
|
||||
|
||||
if (maxDepth <= 0) {
|
||||
return data;
|
||||
}
|
||||
|
||||
for (int i = 0; i < layers.size(); i++) {
|
||||
CNG hgen = getLayerHeightGenerators(random, rdata).get(i);
|
||||
double d = hgen.fit(layers.get(i).getMinHeight(), layers.get(i).getMaxHeight(), wx / layers.get(i).getZoom(), wz / layers.get(i).getZoom());
|
||||
|
||||
IrisSlopeClip sc = getLayers().get(i).getSlopeCondition();
|
||||
|
||||
if (!sc.isDefault()) {
|
||||
if (!sc.isValid(complex.getSlopeStream().get(wx, wz))) {
|
||||
d = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (d <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < d; j++) {
|
||||
if (data.size() >= maxDepth) {
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
data.add(getLayers().get(i).get(random.nextParallelRNG(i + j), (wx + j) / layers.get(i).getZoom(), j, (wz - j) / layers.get(i).getZoom(), rdata));
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (data.size() >= maxDepth) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public KList<BlockData> generateLockedLayers(double wx, double wz, RNG random, int maxDepthf, int height, IrisDataManager rdata, IrisComplex complex) {
|
||||
KList<BlockData> data = new KList<>();
|
||||
KList<BlockData> real = new KList<>();
|
||||
int maxDepth = Math.min(maxDepthf, getLockLayersMax());
|
||||
if (maxDepth <= 0) {
|
||||
return data;
|
||||
}
|
||||
|
||||
for (int i = 0; i < layers.size(); i++) {
|
||||
CNG hgen = getLayerHeightGenerators(random, rdata).get(i);
|
||||
double d = hgen.fit(layers.get(i).getMinHeight(), layers.get(i).getMaxHeight(), wx / layers.get(i).getZoom(), wz / layers.get(i).getZoom());
|
||||
|
||||
IrisSlopeClip sc = getLayers().get(i).getSlopeCondition();
|
||||
|
||||
if (!sc.isDefault()) {
|
||||
if (!sc.isValid(complex.getSlopeStream().get(wx, wz))) {
|
||||
d = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (d <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < d; j++) {
|
||||
try {
|
||||
data.add(getLayers().get(i).get(random.nextParallelRNG(i + j), (wx + j) / layers.get(i).getZoom(), j, (wz - j) / layers.get(i).getZoom(), rdata));
|
||||
} catch (Throwable e) {Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data.isEmpty()) {
|
||||
return real;
|
||||
}
|
||||
|
||||
for (int i = 0; i < maxDepth; i++) {
|
||||
int offset = (255 - height) - i;
|
||||
int index = offset % data.size();
|
||||
real.add(data.get(Math.max(index, 0)));
|
||||
}
|
||||
|
||||
return real;
|
||||
}
|
||||
|
||||
private int getMaxHeight() {
|
||||
return maxHeight.aquire(() ->
|
||||
{
|
||||
int maxHeight = 0;
|
||||
|
||||
for (IrisBiomeGeneratorLink i : getGenerators()) {
|
||||
maxHeight += i.getMax();
|
||||
}
|
||||
|
||||
return maxHeight;
|
||||
});
|
||||
}
|
||||
|
||||
public IrisBiome infer(InferredType t, InferredType type) {
|
||||
setInferredType(t.equals(InferredType.DEFER) ? type : t);
|
||||
return this;
|
||||
}
|
||||
|
||||
public KList<BlockData> generateSeaLayers(double wx, double wz, RNG random, int maxDepth, IrisDataManager rdata) {
|
||||
KList<BlockData> data = new KList<>();
|
||||
|
||||
for (int i = 0; i < seaLayers.size(); i++) {
|
||||
CNG hgen = getLayerSeaHeightGenerators(random, rdata).get(i);
|
||||
int d = hgen.fit(seaLayers.get(i).getMinHeight(), seaLayers.get(i).getMaxHeight(), wx / seaLayers.get(i).getZoom(), wz / seaLayers.get(i).getZoom());
|
||||
|
||||
if (d < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < d; j++) {
|
||||
if (data.size() >= maxDepth) {
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
data.add(getSeaLayers().get(i).get(random.nextParallelRNG(i + j), (wx + j) / seaLayers.get(i).getZoom(), j, (wz - j) / seaLayers.get(i).getZoom(), rdata));
|
||||
} catch (Throwable e) {Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (data.size() >= maxDepth) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public KList<CNG> getLayerHeightGenerators(RNG rng, IrisDataManager rdata) {
|
||||
return layerHeightGenerators.aquire(() ->
|
||||
{
|
||||
KList<CNG> layerHeightGenerators = new KList<>();
|
||||
|
||||
int m = 7235;
|
||||
|
||||
for (IrisBiomePaletteLayer i : getLayers()) {
|
||||
layerHeightGenerators.add(i.getHeightGenerator(rng.nextParallelRNG((m++) * m * m * m), rdata));
|
||||
}
|
||||
|
||||
return layerHeightGenerators;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<CNG> getLayerSeaHeightGenerators(RNG rng, IrisDataManager data) {
|
||||
return layerSeaHeightGenerators.aquire(() ->
|
||||
{
|
||||
KList<CNG> layerSeaHeightGenerators = new KList<>();
|
||||
|
||||
int m = 7735;
|
||||
|
||||
for (IrisBiomePaletteLayer i : getSeaLayers()) {
|
||||
layerSeaHeightGenerators.add(i.getHeightGenerator(rng.nextParallelRNG((m++) * m * m * m), data));
|
||||
}
|
||||
|
||||
return layerSeaHeightGenerators;
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isLand() {
|
||||
if (inferredType == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return inferredType.equals(InferredType.LAND);
|
||||
}
|
||||
|
||||
public boolean isSea() {
|
||||
if (inferredType == null) {
|
||||
return false;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean isShore() {
|
||||
if (inferredType == null) {
|
||||
return false;
|
||||
}
|
||||
return inferredType.equals(InferredType.SHORE);
|
||||
}
|
||||
|
||||
public Biome getSkyBiome(RNG rng, double x, double y, double z) {
|
||||
if (biomeSkyScatter.size() == 1) {
|
||||
return biomeSkyScatter.get(0);
|
||||
}
|
||||
|
||||
if (biomeSkyScatter.isEmpty()) {
|
||||
return getGroundBiome(rng, x, y, z);
|
||||
}
|
||||
|
||||
return biomeSkyScatter.get(getBiomeGenerator(rng).fit(0, biomeSkyScatter.size() - 1, x, y, z));
|
||||
}
|
||||
|
||||
public IrisBiomeCustom getCustomBiome(RNG rng, double x, double y, double z) {
|
||||
if (customDerivitives.size() == 1) {
|
||||
return customDerivitives.get(0);
|
||||
}
|
||||
|
||||
return customDerivitives.get(getBiomeGenerator(rng).fit(0, customDerivitives.size() - 1, x, y, z));
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getRealChildren(DataProvider g) {
|
||||
return realChildren.aquire(() ->
|
||||
{
|
||||
KList<IrisBiome> realChildren = new KList<>();
|
||||
|
||||
for (String i : getChildren()) {
|
||||
realChildren.add(g.getData().getBiomeLoader().load(i));
|
||||
}
|
||||
|
||||
return realChildren;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<String> getAllChildren(DataProvider g, int limit) {
|
||||
KSet<String> m = new KSet<>();
|
||||
m.addAll(getChildren());
|
||||
limit--;
|
||||
|
||||
if (limit > 0) {
|
||||
for (String i : getChildren()) {
|
||||
IrisBiome b = g.getData().getBiomeLoader().load(i);
|
||||
m.addAll(b.getAllChildren(g, limit));
|
||||
}
|
||||
}
|
||||
|
||||
return new KList<>(m);
|
||||
}
|
||||
|
||||
//TODO: Test
|
||||
public Biome getGroundBiome(RNG rng, double x, double y, double z) {
|
||||
if (biomeScatter.isEmpty()) {
|
||||
return getDerivative();
|
||||
}
|
||||
|
||||
if (biomeScatter.size() == 1) {
|
||||
return biomeScatter.get(0);
|
||||
}
|
||||
|
||||
return getBiomeGenerator(rng).fit(biomeScatter, x, y, z);
|
||||
}
|
||||
|
||||
public BlockData getSurfaceBlock(int x, int z, RNG rng, IrisDataManager idm) {
|
||||
if (getLayers().isEmpty()) {
|
||||
return B.get("AIR");
|
||||
}
|
||||
|
||||
return getLayers().get(0).get(rng, x, 0, z, idm);
|
||||
}
|
||||
|
||||
public Color getColor(Engine engine, RenderType type) {
|
||||
switch (type) {
|
||||
case BIOME, HEIGHT, CAVE_LAND, REGION, BIOME_SEA, BIOME_LAND -> {
|
||||
return this.cacheColor.aquire(() -> {
|
||||
if (this.color == null) {
|
||||
RandomColor randomColor = new RandomColor(getName().hashCode());
|
||||
if (this.getVanillaDerivative() == null) {
|
||||
Iris.warn("No vanilla biome found for " + getName());
|
||||
return new Color(randomColor.randomColor());
|
||||
}
|
||||
RandomColor.Color col = VanillaBiomeMap.getColorType(this.getVanillaDerivative());
|
||||
RandomColor.Luminosity lum = VanillaBiomeMap.getColorLuminosity(this.getVanillaDerivative());
|
||||
RandomColor.SaturationType sat = VanillaBiomeMap.getColorSaturatiom(this.getVanillaDerivative());
|
||||
int newColorI = randomColor.randomColor(col, col == RandomColor.Color.MONOCHROME ? RandomColor.SaturationType.MONOCHROME : sat, lum);
|
||||
|
||||
return new Color(newColorI);
|
||||
}
|
||||
|
||||
try {
|
||||
return Color.decode(this.color);
|
||||
} catch (NumberFormatException e) {
|
||||
Iris.warn("Could not parse color \"" + this.color + "\" for biome " + getName());
|
||||
return new Color(new RandomColor(getName().hashCode()).randomColor());
|
||||
}
|
||||
});
|
||||
}
|
||||
case OBJECT_LOAD -> {
|
||||
return cacheColorObjectDensity.aquire(() -> {
|
||||
double density = 0;
|
||||
|
||||
for(IrisObjectPlacement i : getObjects())
|
||||
{
|
||||
density += i.getDensity() * i.getChance();
|
||||
}
|
||||
|
||||
return Color.getHSBColor(0.225f, (float) (density / engine.getMaxBiomeObjectDensity()), 1f);
|
||||
});
|
||||
}
|
||||
case DECORATOR_LOAD -> {
|
||||
return cacheColorDecoratorLoad.aquire(() -> {
|
||||
double density = 0;
|
||||
|
||||
for(IrisDecorator i : getDecorators())
|
||||
{
|
||||
density += i.getChance() * Math.min(1, i.getStackMax()) * 256;
|
||||
}
|
||||
|
||||
return Color.getHSBColor(0.41f, (float) (density / engine.getMaxBiomeDecoratorDensity()), 1f);
|
||||
});
|
||||
}
|
||||
case LAYER_LOAD -> {
|
||||
return cacheColorLayerLoad.aquire(() -> Color.getHSBColor(0.625f, (float) (getLayers().size() / engine.getMaxBiomeLayerDensity()), 1f));
|
||||
}
|
||||
}
|
||||
|
||||
return Color.black;
|
||||
}
|
||||
}
|
||||
169
src/main/java/com/volmit/iris/engine/object/IrisBiomeCustom.java
Normal file
169
src/main/java/com/volmit/iris/engine/object/IrisBiomeCustom.java
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Locale;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("A custom biome, generated through a datapack")
|
||||
@Data
|
||||
public class IrisBiomeCustom {
|
||||
@Required
|
||||
@Desc("The resource key of this biome. Just a simple id such as 'plains' or something.")
|
||||
private String id = "";
|
||||
|
||||
@MinNumber(-3)
|
||||
@MaxNumber(3)
|
||||
@Desc("The biome's temperature")
|
||||
private double temperature = 0.8;
|
||||
|
||||
@MinNumber(-3)
|
||||
@MaxNumber(3)
|
||||
@Desc("The biome's downfall amount (snow / rain), see preci")
|
||||
private double humidity = 0.4;
|
||||
|
||||
@DependsOn("spawnRarity")
|
||||
@ArrayType(min = 1, type = IrisBiomeCustomSpawn.class)
|
||||
@Desc("The biome's mob spawns")
|
||||
private KList<IrisBiomeCustomSpawn> spawns = new KList<>();
|
||||
|
||||
@Desc("The biome's downfall type")
|
||||
private IrisBiomeCustomPrecipType downfallType = IrisBiomeCustomPrecipType.rain;
|
||||
|
||||
@Desc("Define an ambient particle to be rendered clientside (no server cost!)")
|
||||
private IrisBiomeCustomParticle ambientParticle = null;
|
||||
|
||||
@Desc("The biome's category type")
|
||||
private IrisBiomeCustomCategory category = IrisBiomeCustomCategory.plains;
|
||||
|
||||
@Desc("The spawn rarity of any defined spawners")
|
||||
private int spawnRarity = -1;
|
||||
|
||||
@Desc("The color of the sky, top half of sky. (hex format)")
|
||||
private String skyColor = "#79a8e1";
|
||||
|
||||
@Desc("The color of the fog, bottom half of sky. (hex format)")
|
||||
private String fogColor = "#c0d8e1";
|
||||
|
||||
@Desc("The color of the water (hex format). Leave blank / don't define to not change")
|
||||
private String waterColor = "#3f76e4";
|
||||
|
||||
@Desc("The color of water fog (hex format). Leave blank / don't define to not change")
|
||||
private String waterFogColor = "#050533";
|
||||
|
||||
@Desc("The color of the grass (hex format). Leave blank / don't define to not change")
|
||||
private String grassColor = "";
|
||||
|
||||
@Desc("The color of foliage (hex format). Leave blank / don't define to not change")
|
||||
private String foliageColor = "";
|
||||
|
||||
public String generateJson() {
|
||||
JSONObject effects = new JSONObject();
|
||||
effects.put("sky_color", parseColor(getSkyColor()));
|
||||
effects.put("fog_color", parseColor(getFogColor()));
|
||||
effects.put("water_color", parseColor(getWaterColor()));
|
||||
effects.put("water_fog_color", parseColor(getWaterFogColor()));
|
||||
|
||||
if(ambientParticle != null)
|
||||
{
|
||||
JSONObject particle = new JSONObject();
|
||||
JSONObject po = new JSONObject();
|
||||
po.put("type", ambientParticle.getParticle().name().toLowerCase());
|
||||
particle.put("options", po);
|
||||
particle.put("probability", ambientParticle.getRarity());
|
||||
effects.put("particle", particle);
|
||||
}
|
||||
|
||||
if (!getGrassColor().isEmpty()) {
|
||||
effects.put("grass_color", parseColor(getGrassColor()));
|
||||
}
|
||||
|
||||
if (!getFoliageColor().isEmpty()) {
|
||||
effects.put("foliage_color", parseColor(getFoliageColor()));
|
||||
}
|
||||
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("surface_builder", "minecraft:grass");
|
||||
j.put("depth", 0.125);
|
||||
j.put("scale", 0.05);
|
||||
j.put("temperature", getTemperature());
|
||||
j.put("downfall", getHumidity());
|
||||
j.put("creature_spawn_probability", getSpawnRarity());
|
||||
j.put("precipitation", getDownfallType().toString().toLowerCase());
|
||||
j.put("category", getCategory().toString().toLowerCase());
|
||||
j.put("effects", effects);
|
||||
j.put("starts", new JSONArray());
|
||||
j.put("spawners", new JSONObject());
|
||||
j.put("spawn_costs", new JSONObject());
|
||||
j.put("carvers", new JSONObject());
|
||||
j.put("features", new JSONArray());
|
||||
|
||||
if(spawnRarity > 0)
|
||||
{
|
||||
j.put("creature_spawn_probability", spawnRarity);
|
||||
}
|
||||
|
||||
if(getSpawns() != null && getSpawns().isNotEmpty())
|
||||
{
|
||||
JSONObject spawners = new JSONObject();
|
||||
KMap<IrisBiomeCustomSpawnType, JSONArray> groups = new KMap<>();
|
||||
|
||||
for(IrisBiomeCustomSpawn i : getSpawns())
|
||||
{
|
||||
JSONArray g = groups.compute(i.getGroup(), (k, v) -> v != null ? v : new JSONArray());
|
||||
JSONObject o = new JSONObject();
|
||||
o.put("type", "minecraft:" + i.getType().name().toLowerCase());
|
||||
o.put("weight", i.getWeight());
|
||||
o.put("minCount", i.getMinCount());
|
||||
o.put("maxCount", i.getMaxCount());
|
||||
g.put(o);
|
||||
}
|
||||
|
||||
for(IrisBiomeCustomSpawnType i : groups.k())
|
||||
{
|
||||
spawners.put(i.name().toLowerCase(Locale.ROOT), groups.get(i));
|
||||
}
|
||||
|
||||
j.put("spawners", spawners);
|
||||
}
|
||||
|
||||
return j.toString(4);
|
||||
}
|
||||
|
||||
private int parseColor(String c) {
|
||||
String v = (c.startsWith("#") ? c : "#" + c).trim();
|
||||
try {
|
||||
return Color.decode(v).getRGB();
|
||||
} catch (Throwable e) {Iris.reportError(e);
|
||||
Iris.error("Error Parsing '''color''', (" + c + ")");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
|
||||
@Desc("The custom biome category. Vanilla asks for this, basically what represents your biome closest?")
|
||||
public enum IrisBiomeCustomCategory {
|
||||
beach,
|
||||
desert,
|
||||
extreme_hills,
|
||||
forest,
|
||||
icy,
|
||||
jungle,
|
||||
mesa,
|
||||
mushroom,
|
||||
nether,
|
||||
none,
|
||||
ocean,
|
||||
plains,
|
||||
river,
|
||||
savanna,
|
||||
swamp,
|
||||
taiga,
|
||||
the_end
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.Particle;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("A custom biome ambient particle")
|
||||
@Data
|
||||
public class IrisBiomeCustomParticle {
|
||||
@Required
|
||||
@Desc("The biome's particle type")
|
||||
private Particle particle = Particle.FLASH;
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(10000)
|
||||
@Desc("The rarity")
|
||||
private int rarity = 35;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
|
||||
@Desc("Snow, rain, or nothing")
|
||||
public enum IrisBiomeCustomPrecipType {
|
||||
@Desc("No downfall")
|
||||
|
||||
none,
|
||||
|
||||
@Desc("Rain downfall")
|
||||
|
||||
rain,
|
||||
|
||||
@Desc("Snow downfall")
|
||||
|
||||
snow
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.MaxNumber;
|
||||
import com.volmit.iris.util.MinNumber;
|
||||
import com.volmit.iris.util.Required;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("A custom biome spawn")
|
||||
@Data
|
||||
public class IrisBiomeCustomSpawn {
|
||||
@Required
|
||||
@Desc("The biome's particle type")
|
||||
private EntityType type = EntityType.COW;
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(20)
|
||||
@Desc("The min to spawn")
|
||||
private int minCount = 2;
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(20)
|
||||
@Desc("The max to spawn")
|
||||
private int maxCount = 5;
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(1000)
|
||||
@Desc("The weight in this group. Higher weight, the more common this type is spawned")
|
||||
private int weight = 1;
|
||||
|
||||
@Desc("The rarity")
|
||||
private IrisBiomeCustomSpawnType group = IrisBiomeCustomSpawnType.MISC;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
|
||||
@Desc("The mob spawn group")
|
||||
public enum IrisBiomeCustomSpawnType {
|
||||
MONSTER,
|
||||
CREATURE,
|
||||
AMBIENT,
|
||||
UNDERGROUND_WATER_CREATURE,
|
||||
WATER_CREATURE,
|
||||
WATER_AMBIENT,
|
||||
MISC
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.data.DataProvider;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("This represents a link to a generator for a biome")
|
||||
@Data
|
||||
public class IrisBiomeGeneratorLink {
|
||||
|
||||
@RegistryListGenerator
|
||||
|
||||
@Desc("The generator id")
|
||||
private String generator = "default";
|
||||
|
||||
@DependsOn({"min", "max"})
|
||||
@Required
|
||||
@MinNumber(-256) // TODO: WARNING HEIGHT
|
||||
@MaxNumber(256) // TODO: WARNING HEIGHT
|
||||
|
||||
@Desc("The min block value (value + fluidHeight)")
|
||||
private int min = 0;
|
||||
|
||||
@DependsOn({"min", "max"})
|
||||
@Required
|
||||
@MinNumber(-256) // TODO: WARNING HEIGHT
|
||||
@MaxNumber(256) // TODO: WARNING HEIGHT
|
||||
|
||||
@Desc("The max block value (value + fluidHeight)")
|
||||
private int max = 0;
|
||||
|
||||
private final transient AtomicCache<IrisGenerator> gen = new AtomicCache<>();
|
||||
|
||||
public IrisGenerator getCachedGenerator(DataProvider g) {
|
||||
return gen.aquire(() ->
|
||||
{
|
||||
IrisGenerator gen = g.getData().getGeneratorLoader().load(getGenerator());
|
||||
|
||||
if (gen == null) {
|
||||
gen = new IrisGenerator();
|
||||
}
|
||||
|
||||
return gen;
|
||||
});
|
||||
}
|
||||
|
||||
public double getHeight(DataProvider xg, double x, double z, long seed) {
|
||||
double g = getCachedGenerator(xg).getHeight(x, z, seed);
|
||||
g = g < 0 ? 0 : g;
|
||||
g = g > 1 ? 1 : g;
|
||||
|
||||
return IrisInterpolation.lerp(min, max, g);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.data.DataProvider;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("A biome mutation if a condition is met")
|
||||
@Data
|
||||
public class IrisBiomeMutation {
|
||||
|
||||
@RegistryListBiome
|
||||
@Required
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
@Desc("One of The following biomes or regions must show up")
|
||||
private KList<String> sideA = new KList<>();
|
||||
|
||||
@RegistryListBiome
|
||||
@Required
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
@Desc("One of The following biomes or regions must show up")
|
||||
private KList<String> sideB = new KList<>();
|
||||
|
||||
@Required
|
||||
@MinNumber(1)
|
||||
@MaxNumber(1024)
|
||||
@Desc("The scan radius for placing this mutator")
|
||||
private int radius = 16;
|
||||
|
||||
@Required
|
||||
@MinNumber(1)
|
||||
@MaxNumber(32)
|
||||
@Desc("How many tries per chunk to check for this mutation")
|
||||
private int checks = 2;
|
||||
|
||||
@RegistryListObject
|
||||
@ArrayType(min = 1, type = IrisObjectPlacement.class)
|
||||
@Desc("Objects define what schematics (iob files) iris will place in this biome mutation")
|
||||
private KList<IrisObjectPlacement> objects = new KList<>();
|
||||
|
||||
private final transient AtomicCache<KList<String>> sideACache = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<String>> sideBCache = new AtomicCache<>();
|
||||
|
||||
public KList<String> getRealSideA(DataProvider xg) {
|
||||
return sideACache.aquire(() -> processList(xg, getSideA()));
|
||||
}
|
||||
|
||||
public KList<String> getRealSideB(DataProvider xg) {
|
||||
return sideBCache.aquire(() -> processList(xg, getSideB()));
|
||||
}
|
||||
|
||||
public KList<String> processList(DataProvider xg, KList<String> s) {
|
||||
KSet<String> r = new KSet<>();
|
||||
|
||||
for (String i : s) {
|
||||
|
||||
if (i.startsWith("^")) {
|
||||
r.addAll(xg.getData().getRegionLoader().load(i.substring(1)).getLandBiomes());
|
||||
} else if (i.startsWith("*")) {
|
||||
String name = i.substring(1);
|
||||
r.addAll(xg.getData().getBiomeLoader().load(name).getAllChildren(xg, 7));
|
||||
} else if (i.startsWith("!")) {
|
||||
r.remove(i.substring(1));
|
||||
} else if (i.startsWith("!*")) {
|
||||
String name = i.substring(2);
|
||||
|
||||
for(String g : xg.getData().getBiomeLoader().load(name).getAllChildren(xg, 7))
|
||||
{
|
||||
r.remove(g);
|
||||
}
|
||||
} else {
|
||||
r.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
return new KList<>(r);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.noise.CNG;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("A layer of surface / subsurface material in biomes")
|
||||
@Data
|
||||
public class IrisBiomePaletteLayer {
|
||||
|
||||
@Desc("The style of noise")
|
||||
private IrisGeneratorStyle style = NoiseStyle.STATIC.style();
|
||||
|
||||
@DependsOn({"minHeight", "maxHeight"})
|
||||
@MinNumber(0)
|
||||
@MaxNumber(256) // TODO: WARNING HEIGHT
|
||||
|
||||
@Desc("The min thickness of this layer")
|
||||
private int minHeight = 1;
|
||||
|
||||
@DependsOn({"minHeight", "maxHeight"})
|
||||
@MinNumber(1)
|
||||
@MaxNumber(256) // TODO: WARNING HEIGHT
|
||||
|
||||
@Desc("The max thickness of this layer")
|
||||
private int maxHeight = 1;
|
||||
|
||||
|
||||
@Desc("If set, this layer will change size depending on the slope. If in bounds, the layer will get larger (taller) the closer to the center of this slope clip it is. If outside of the slipe's bounds, this layer will not show.")
|
||||
private IrisSlopeClip slopeCondition = new IrisSlopeClip();
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@Desc("The terrain zoom mostly for zooming in on a wispy palette")
|
||||
private double zoom = 5;
|
||||
|
||||
@Required
|
||||
@ArrayType(min = 1, type = IrisBlockData.class)
|
||||
@Desc("The palette of blocks to be used in this layer")
|
||||
private KList<IrisBlockData> palette = new KList<IrisBlockData>().qadd(new IrisBlockData("GRASS_BLOCK"));
|
||||
|
||||
private final transient AtomicCache<KList<BlockData>> blockData = new AtomicCache<>();
|
||||
private final transient AtomicCache<CNG> layerGenerator = new AtomicCache<>();
|
||||
private final transient AtomicCache<CNG> heightGenerator = new AtomicCache<>();
|
||||
|
||||
public CNG getHeightGenerator(RNG rng, IrisDataManager data) {
|
||||
return heightGenerator.aquire(() -> CNG.signature(rng.nextParallelRNG(minHeight * maxHeight + getBlockData(data).size())));
|
||||
}
|
||||
|
||||
public BlockData get(RNG rng, double x, double y, double z, IrisDataManager data) {
|
||||
if (getBlockData(data).isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (getBlockData(data).size() == 1) {
|
||||
return getBlockData(data).get(0);
|
||||
}
|
||||
|
||||
return getLayerGenerator(rng, data).fit(getBlockData(data), x / zoom, y / zoom, z / zoom);
|
||||
}
|
||||
|
||||
public CNG getLayerGenerator(RNG rng, IrisDataManager data) {
|
||||
return layerGenerator.aquire(() ->
|
||||
{
|
||||
RNG rngx = rng.nextParallelRNG(minHeight + maxHeight + getBlockData(data).size());
|
||||
return style.create(rngx);
|
||||
});
|
||||
}
|
||||
|
||||
public KList<IrisBlockData> add(String b) {
|
||||
palette.add(new IrisBlockData(b));
|
||||
|
||||
return palette;
|
||||
}
|
||||
|
||||
public KList<BlockData> getBlockData(IrisDataManager data) {
|
||||
return blockData.aquire(() ->
|
||||
{
|
||||
KList<BlockData> blockData = new KList<>();
|
||||
for (IrisBlockData ix : palette) {
|
||||
BlockData bx = ix.getBlockData(data);
|
||||
if (bx != null) {
|
||||
for (int i = 0; i < ix.getWeight(); i++) {
|
||||
blockData.add(bx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blockData;
|
||||
});
|
||||
}
|
||||
|
||||
public IrisBiomePaletteLayer zero() {
|
||||
palette.clear();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
212
src/main/java/com/volmit/iris/engine/object/IrisBlockData.java
Normal file
212
src/main/java/com/volmit/iris/engine/object/IrisBlockData.java
Normal file
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings("DefaultAnnotationParam")
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents Block Data")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisBlockData extends IrisRegistrant {
|
||||
@RegistryListBlockType
|
||||
@Required
|
||||
|
||||
@Desc("The block to use")
|
||||
private String block = "air";
|
||||
|
||||
@Desc("Debug this block by printing it to the console when it's used")
|
||||
|
||||
private boolean debug = false;
|
||||
|
||||
|
||||
@Desc("The resource key. Typically Minecraft")
|
||||
private String key = "minecraft";
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(1000)
|
||||
@Desc("The weight is used when this block data is inside of a list of blockdata. A weight of two is just as if you placed two of the same block data values in the same list making it more common when randomly picked.")
|
||||
private int weight = 1;
|
||||
|
||||
|
||||
@Desc("If the block cannot be created on this version, Iris will attempt to use this backup block data instead.")
|
||||
private IrisBlockData backup = null;
|
||||
|
||||
|
||||
@Desc("Optional properties for this block data such as 'waterlogged': true")
|
||||
private KMap<String, Object> data = new KMap<>();
|
||||
|
||||
private final transient AtomicCache<BlockData> blockdata = new AtomicCache<>();
|
||||
private final transient AtomicCache<String> realProperties = new AtomicCache<>();
|
||||
|
||||
public IrisBlockData(String b) {
|
||||
this.block = b;
|
||||
}
|
||||
|
||||
public String computeProperties(KMap<String, Object> data) {
|
||||
if (data.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
KList<String> r = new KList<>();
|
||||
|
||||
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
||||
r.add(entry.getKey() + "=" + filter(entry.getValue().toString()));
|
||||
}
|
||||
|
||||
return "[" + r.toString(",") + "]";
|
||||
}
|
||||
|
||||
public String computeProperties() {
|
||||
return computeProperties(getData());
|
||||
}
|
||||
|
||||
public BlockData getBlockData(IrisDataManager data) {
|
||||
return blockdata.aquire(() ->
|
||||
{
|
||||
BlockData b = null;
|
||||
|
||||
IrisBlockData customData = data.getBlockLoader().load(getBlock(), false);
|
||||
|
||||
if (customData != null) {
|
||||
b = customData.getBlockData(data);
|
||||
|
||||
if (b != null) {
|
||||
b = b.clone();
|
||||
|
||||
String st = b.getAsString(true);
|
||||
|
||||
if (st.contains("[")) {
|
||||
st = st.split("\\Q[\\E")[0];
|
||||
}
|
||||
|
||||
KMap<String, Object> cdata = customData.getData().copy();
|
||||
|
||||
for (String i : getData().keySet()) {
|
||||
cdata.put(i, getData().get(i));
|
||||
}
|
||||
|
||||
String sx = getKey() + ":" + st.split("\\Q:\\E")[1] + computeProperties(cdata);
|
||||
|
||||
if (debug) {
|
||||
Iris.warn("Debug block data " + sx + " (CUSTOM)");
|
||||
}
|
||||
|
||||
BlockData bx = B.get(sx);
|
||||
|
||||
if (bx != null) {
|
||||
return bx;
|
||||
}
|
||||
|
||||
if (b != null) {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String ss = getKey() + ":" + getBlock() + computeProperties();
|
||||
b = B.get(ss);
|
||||
|
||||
if (debug) {
|
||||
Iris.warn("Debug block data " + ss);
|
||||
}
|
||||
|
||||
if (b != null) {
|
||||
return b;
|
||||
}
|
||||
|
||||
if (backup != null) {
|
||||
return backup.getBlockData(data);
|
||||
}
|
||||
|
||||
return B.get("AIR");
|
||||
});
|
||||
}
|
||||
|
||||
public static IrisBlockData from(String j) {
|
||||
IrisBlockData b = new IrisBlockData();
|
||||
String m = j.toLowerCase().trim();
|
||||
|
||||
if (m.contains(":")) {
|
||||
b.setKey(m.split("\\Q:\\E")[0]);
|
||||
String v = m.split("\\Q:\\E")[1];
|
||||
|
||||
if (v.contains("[")) {
|
||||
KList<String> props = new KList<>();
|
||||
String rp = v.split("\\Q[\\E")[1].replaceAll("\\Q]\\E", "");
|
||||
b.setBlock(v.split("\\Q[\\E")[0]);
|
||||
|
||||
if (rp.contains(",")) {
|
||||
props.add(rp.split("\\Q,\\E"));
|
||||
} else {
|
||||
props.add(rp);
|
||||
}
|
||||
|
||||
for (String i : props) {
|
||||
Object kg = filter(i.split("\\Q=\\E")[1]);
|
||||
b.data.put(i.split("\\Q=\\E")[0], kg);
|
||||
}
|
||||
} else {
|
||||
b.setBlock(v);
|
||||
}
|
||||
} else {
|
||||
b.setBlock(m);
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
private static Object filter(String string) {
|
||||
if (string.equals("true")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (string.equals("false")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return Integer.valueOf(string);
|
||||
} catch (Throwable e) {Iris.reportError(e);
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
return Double.valueOf(string).intValue();
|
||||
} catch (Throwable e) {Iris.reportError(e);
|
||||
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents a block drop list")
|
||||
@Data
|
||||
public class IrisBlockDrops {
|
||||
@Required
|
||||
@ArrayType(min = 1, type = IrisBlockData.class)
|
||||
@Desc("The blocks that drop loot")
|
||||
private KList<IrisBlockData> blocks = new KList<>();
|
||||
|
||||
|
||||
@Desc("If exact blocks is set to true, minecraft:barrel[axis=x] will only drop for that axis. When exact is false (default) any barrel will drop the defined drops.")
|
||||
private boolean exactBlocks = false;
|
||||
|
||||
|
||||
@Desc("Add in specific items to drop")
|
||||
@ArrayType(min = 1, type = IrisLoot.class)
|
||||
private KList<IrisLoot> drops = new KList<>();
|
||||
|
||||
|
||||
@Desc("If this is in a biome, setting skipParents to true will ignore the drops in the region and dimension for this block type. The default (false) will allow all three nodes to fire and add to a list of drops.")
|
||||
private boolean skipParents = false;
|
||||
|
||||
|
||||
@Desc("Removes the default vanilla block drops and only drops the given items & any parent loot tables specified for this block type.")
|
||||
private boolean replaceVanillaDrops = false;
|
||||
|
||||
private final transient AtomicCache<KList<BlockData>> data = new AtomicCache<>();
|
||||
|
||||
public boolean shouldDropFor(BlockData data, IrisDataManager rdata) {
|
||||
KList<BlockData> list = this.data.aquire(() ->
|
||||
{
|
||||
KList<BlockData> b = new KList<>();
|
||||
|
||||
for (IrisBlockData i : getBlocks()) {
|
||||
BlockData dd = i.getBlockData(rdata);
|
||||
|
||||
if (dd != null) {
|
||||
b.add(dd);
|
||||
}
|
||||
}
|
||||
|
||||
return b.removeDuplicates();
|
||||
});
|
||||
|
||||
for (BlockData i : list) {
|
||||
if (exactBlocks ? i.equals(data) : i.getMaterial().equals(data.getMaterial())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: WARNING USES RNG.R
|
||||
@Deprecated
|
||||
public void fillDrops(boolean debug, KList<ItemStack> d) {
|
||||
for (IrisLoot i : getDrops()) {
|
||||
if (RNG.r.i(1, i.getRarity()) == i.getRarity()) {
|
||||
d.add(i.get(debug, RNG.r));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.noise.CNG;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Translate objects")
|
||||
@Data
|
||||
public class IrisCarveLayer {
|
||||
@Required
|
||||
|
||||
@Desc("The 4d slope this carve layer follows")
|
||||
private IrisGeneratorStyle style = new IrisGeneratorStyle();
|
||||
|
||||
@MaxNumber(512)
|
||||
@MinNumber(-128)
|
||||
@Desc("The max height")
|
||||
private int maxHeight = 220;
|
||||
|
||||
@MinNumber(0.0)
|
||||
@MaxNumber(1.0)
|
||||
@Desc("The full percentage means the 4D opacity of this carver will decay from 100% to 0% at the min & max vertical ranges. Setting the percent to 1.0 will make a very drastic & charp change at the edge of the vertical min & max. Where as 0.15 means only 15% of the vertical range will actually be 100% opacity.")
|
||||
private double fullPercent = 0.5;
|
||||
|
||||
@MaxNumber(512)
|
||||
@MinNumber(-128)
|
||||
@Desc("The min height")
|
||||
private int minHeight = 147;
|
||||
|
||||
@MaxNumber(1)
|
||||
@MinNumber(0)
|
||||
@Desc("The threshold used as: \n\ncarved = noise(x,y,z) > threshold")
|
||||
private double threshold = 0.5;
|
||||
|
||||
private final transient AtomicCache<CNG> cng = new AtomicCache<>();
|
||||
|
||||
public boolean isCarved(RNG rng, double x, double y, double z) {
|
||||
if (y > getMaxHeight() || y < getMinHeight()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double opacity = Math.pow(IrisInterpolation.sinCenter(M.lerpInverse(getMinHeight(), getMaxHeight(), y)), 4);
|
||||
return cng.aquire(() -> getStyle().create(rng.nextParallelRNG(-2340 * getMaxHeight() * getMinHeight()))).fitDouble(0D, 1D, x, y, z) * opacity > getThreshold();
|
||||
}
|
||||
|
||||
public boolean isCarved2(RNG rng, double x, double y, double z) {
|
||||
if (y > getMaxHeight() || y < getMinHeight()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double innerRange = fullPercent * (maxHeight - minHeight);
|
||||
double opacity = 1D;
|
||||
|
||||
if (y <= minHeight + innerRange) {
|
||||
opacity = IrisInterpolation.bezier(M.lerpInverse(getMinHeight(), minHeight + innerRange, y));
|
||||
} else if (y >= maxHeight - innerRange) {
|
||||
opacity = IrisInterpolation.bezier(1D - M.lerpInverse(maxHeight - innerRange, getMaxHeight(), y));
|
||||
}
|
||||
|
||||
return cng.aquire(() -> getStyle().create(rng.nextParallelRNG(-2340 * getMaxHeight() * getMinHeight()))).fitDouble(0D, 1D, x, y, z) * opacity > getThreshold();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Translate objects")
|
||||
@Data
|
||||
public class IrisCaveFluid {
|
||||
@Required
|
||||
@MaxNumber(255)
|
||||
@MinNumber(0)
|
||||
@Desc("The fluid height of the cave")
|
||||
private int fluidHeight = 35;
|
||||
|
||||
|
||||
@Desc("Insead of fluidHeight & below being fluid, turning inverse height on will simply spawn fluid in this cave layer from min(max_height, cave_height) to the fluid height. Basically, fluid will spawn above the fluidHeight value instead of below the fluidHeight.")
|
||||
private boolean inverseHeight = false;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The fluid type that should spawn here")
|
||||
private IrisBlockData fluidType = new IrisBlockData("CAVE_AIR");
|
||||
|
||||
private final transient AtomicCache<BlockData> fluidData = new AtomicCache<>();
|
||||
|
||||
public boolean hasFluid(IrisDataManager rdata) {
|
||||
return !B.isAir(getFluid(rdata));
|
||||
}
|
||||
|
||||
public BlockData getFluid(IrisDataManager rdata) {
|
||||
return fluidData.aquire(() ->
|
||||
{
|
||||
BlockData b = getFluidType().getBlockData(rdata);
|
||||
|
||||
if (b != null) {
|
||||
return b;
|
||||
}
|
||||
|
||||
return B.get("CAVE_AIR");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.MinNumber;
|
||||
import com.volmit.iris.util.Required;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Translate objects")
|
||||
@Data
|
||||
public class IrisCaveLayer {
|
||||
@Required
|
||||
|
||||
@Desc("The vertical slope this cave layer follows")
|
||||
private IrisShapedGeneratorStyle verticalSlope = new IrisShapedGeneratorStyle();
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The horizontal slope this cave layer follows")
|
||||
private IrisShapedGeneratorStyle horizontalSlope = new IrisShapedGeneratorStyle();
|
||||
|
||||
|
||||
@Desc("If defined, a cave fluid will fill this cave below (or above) the specified fluidHeight in this object.")
|
||||
private IrisCaveFluid fluid = new IrisCaveFluid();
|
||||
|
||||
@MinNumber(0.001)
|
||||
@Desc("The cave zoom. Higher values makes caves spread out further and branch less often, but are thicker.")
|
||||
private double caveZoom = 1D;
|
||||
|
||||
@MinNumber(0.001)
|
||||
@Desc("The cave thickness.")
|
||||
private double caveThickness = 1D;
|
||||
|
||||
|
||||
@Desc("If set to true, this cave layer can break the surface")
|
||||
private boolean canBreakSurface = false;
|
||||
|
||||
}
|
||||
122
src/main/java/com/volmit/iris/engine/object/IrisColor.java
Normal file
122
src/main/java/com/volmit/iris/engine/object/IrisColor.java
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.MaxNumber;
|
||||
import com.volmit.iris.util.MinNumber;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@Deprecated()
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@Desc("Represents a color")
|
||||
@Data
|
||||
public class IrisColor {
|
||||
|
||||
@MaxNumber(7)
|
||||
@MinNumber(6)
|
||||
@Desc("Pass in a 6 digit hexadecimal color to fill R G and B values. You can also include the # symbol, but it's not required.")
|
||||
private String hex = null;
|
||||
|
||||
|
||||
@MaxNumber(255)
|
||||
@MinNumber(0)
|
||||
@Desc("Represents the red channel. Only define this if you are not defining the hex value.")
|
||||
private int red = 0;
|
||||
|
||||
|
||||
@MaxNumber(255)
|
||||
@MinNumber(0)
|
||||
@Desc("Represents the green channel. Only define this if you are not defining the hex value.")
|
||||
private int green = 0;
|
||||
|
||||
|
||||
@MaxNumber(255)
|
||||
@MinNumber(0)
|
||||
@Desc("Represents the blue channel. Only define this if you are not defining the hex value.")
|
||||
private int blue = 0;
|
||||
|
||||
private final transient AtomicCache<Color> color = new AtomicCache<>();
|
||||
|
||||
public Color getColor() {
|
||||
return color.aquire(() -> {
|
||||
if (hex != null) {
|
||||
String v = (hex.startsWith("#") ? hex : "#" + hex).trim();
|
||||
try {
|
||||
return Color.decode(v);
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return new Color(red, green, blue);
|
||||
});
|
||||
}
|
||||
|
||||
public org.bukkit.Color getBukkitColor() {
|
||||
return org.bukkit.Color.fromRGB(getColor().getRGB());
|
||||
}
|
||||
|
||||
public static Color blend(Color... c) {
|
||||
if (c == null || c.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
float ratio = 1f / ((float) c.length);
|
||||
|
||||
int a = 0;
|
||||
int r = 0;
|
||||
int g = 0;
|
||||
int b = 0;
|
||||
|
||||
for (Color value : c) {
|
||||
int rgb = value.getRGB();
|
||||
int a1 = (rgb >> 24 & 0xff);
|
||||
int r1 = ((rgb & 0xff0000) >> 16);
|
||||
int g1 = ((rgb & 0xff00) >> 8);
|
||||
int b1 = (rgb & 0xff);
|
||||
a += (a1 * ratio);
|
||||
r += (r1 * ratio);
|
||||
g += (g1 * ratio);
|
||||
b += (b1 * ratio);
|
||||
}
|
||||
|
||||
return new Color(a << 24 | r << 16 | g << 8 | b);
|
||||
}
|
||||
|
||||
public int getAsRGB() {
|
||||
if (hex != null) {
|
||||
try {
|
||||
if (hex.startsWith("#")) hex = hex.substring(1);
|
||||
return Integer.parseInt(hex, 16);
|
||||
} catch (NumberFormatException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return red << 16 | green << 8 | blue;
|
||||
}
|
||||
}
|
||||
355
src/main/java/com/volmit/iris/engine/object/IrisCompat.java
Normal file
355
src/main/java/com/volmit/iris/engine/object/IrisCompat.java
Normal file
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@Data
|
||||
public class IrisCompat {
|
||||
private KList<IrisCompatabilityBlockFilter> blockFilters;
|
||||
private KList<IrisCompatabilityItemFilter> itemFilters;
|
||||
|
||||
public IrisCompat() {
|
||||
blockFilters = getDefaultBlockCompatabilityFilters();
|
||||
itemFilters = getDefaultItemCompatabilityFilters();
|
||||
}
|
||||
|
||||
public BlockData getBlock(String n) {
|
||||
String buf = n;
|
||||
int err = 16;
|
||||
|
||||
BlockData tx = B.getOrNull(buf);
|
||||
|
||||
if (tx != null) {
|
||||
return tx;
|
||||
}
|
||||
|
||||
searching:
|
||||
while (true) {
|
||||
if (err-- <= 0) {
|
||||
return B.get("STONE");
|
||||
}
|
||||
|
||||
for (IrisCompatabilityBlockFilter i : blockFilters) {
|
||||
if (i.getWhen().equalsIgnoreCase(buf)) {
|
||||
BlockData b = i.getReplace();
|
||||
|
||||
if (b != null) {
|
||||
return b;
|
||||
}
|
||||
|
||||
buf = i.getSupplement();
|
||||
continue searching;
|
||||
}
|
||||
}
|
||||
|
||||
return B.get("STONE");
|
||||
}
|
||||
}
|
||||
|
||||
public Material getItem(String n) {
|
||||
String buf = n;
|
||||
int err = 16;
|
||||
Material txf = B.getMaterialOrNull(buf);
|
||||
|
||||
if (txf != null) {
|
||||
return txf;
|
||||
}
|
||||
|
||||
int nomore = 64;
|
||||
|
||||
searching:
|
||||
while (true) {
|
||||
if (nomore < 0) {
|
||||
return B.getMaterial("STONE");
|
||||
}
|
||||
|
||||
nomore--;
|
||||
if (err-- <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (IrisCompatabilityItemFilter i : itemFilters) {
|
||||
if (i.getWhen().equalsIgnoreCase(buf)) {
|
||||
Material b = i.getReplace();
|
||||
|
||||
if (b != null) {
|
||||
return b;
|
||||
}
|
||||
|
||||
buf = i.getSupplement();
|
||||
continue searching;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
buf = n;
|
||||
BlockData tx = B.getOrNull(buf);
|
||||
|
||||
if (tx != null) {
|
||||
return tx.getMaterial();
|
||||
}
|
||||
nomore = 64;
|
||||
|
||||
searching:
|
||||
while (true) {
|
||||
if (nomore < 0) {
|
||||
return B.getMaterial("STONE");
|
||||
}
|
||||
|
||||
nomore--;
|
||||
|
||||
if (err-- <= 0) {
|
||||
return B.getMaterial("STONE");
|
||||
}
|
||||
|
||||
for (IrisCompatabilityBlockFilter i : blockFilters) {
|
||||
if (i.getWhen().equalsIgnoreCase(buf)) {
|
||||
BlockData b = i.getReplace();
|
||||
|
||||
if (b != null) {
|
||||
return b.getMaterial();
|
||||
}
|
||||
|
||||
buf = i.getSupplement();
|
||||
continue searching;
|
||||
}
|
||||
}
|
||||
|
||||
return B.getMaterial("STONE");
|
||||
}
|
||||
}
|
||||
|
||||
public static IrisCompat configured(File f) throws IOException {
|
||||
IrisCompat def = new IrisCompat();
|
||||
String defa = new JSONObject(new Gson().toJson(def)).toString(4);
|
||||
J.attemptAsync(() -> IO.writeAll(new File(f.getParentFile(), "compat.default.json"), defa));
|
||||
|
||||
if (!f.exists()) {
|
||||
J.attemptAsync(() -> IO.writeAll(f, defa));
|
||||
}
|
||||
|
||||
try {
|
||||
IrisCompat rea = new Gson().fromJson(IO.readAll(f), IrisCompat.class);
|
||||
|
||||
for (IrisCompatabilityBlockFilter i : rea.getBlockFilters()) {
|
||||
def.getBlockFilters().add(i);
|
||||
}
|
||||
|
||||
for (IrisCompatabilityItemFilter i : rea.getItemFilters()) {
|
||||
def.getItemFilters().add(i);
|
||||
}
|
||||
} catch (JsonSyntaxException e) {
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
private static KList<IrisCompatabilityItemFilter> getDefaultItemCompatabilityFilters() {
|
||||
KList<IrisCompatabilityItemFilter> filters = new KList<>();
|
||||
|
||||
// Below 1.16
|
||||
filters.add(new IrisCompatabilityItemFilter("NETHERITE_HELMET", "DIAMOND_HELMET"));
|
||||
filters.add(new IrisCompatabilityItemFilter("NETHERITE_CHESTPLATE", "DIAMOND_CHESTPLATE"));
|
||||
filters.add(new IrisCompatabilityItemFilter("NETHERITE_BOOTS", "DIAMOND_BOOTS"));
|
||||
filters.add(new IrisCompatabilityItemFilter("NETHERITE_LEGGINGS", "DIAMOND_LEGGINGS"));
|
||||
filters.add(new IrisCompatabilityItemFilter("MUSIC_DISC_PIGSTEP", "MUSIC_DISC_FAR"));
|
||||
filters.add(new IrisCompatabilityItemFilter("NETHERITE_SWORD", "DIAMOND_SWORD"));
|
||||
filters.add(new IrisCompatabilityItemFilter("NETHERITE_AXE", "DIAMOND_AXE"));
|
||||
filters.add(new IrisCompatabilityItemFilter("NETHERITE_PICKAXE", "DIAMOND_PICKAXE"));
|
||||
filters.add(new IrisCompatabilityItemFilter("NETHERITE_HOE", "DIAMOND_HOE"));
|
||||
filters.add(new IrisCompatabilityItemFilter("NETHERITE_SHOVEL", "DIAMOND_SHOVEL"));
|
||||
filters.add(new IrisCompatabilityItemFilter("NETHERITE_INGOT", "DIAMOND"));
|
||||
filters.add(new IrisCompatabilityItemFilter("PIGLIN_BANNER_PATTERN", "PORKCHOP"));
|
||||
filters.add(new IrisCompatabilityItemFilter("NETHERITE_SCRAP", "GOLD_INGOT"));
|
||||
filters.add(new IrisCompatabilityItemFilter("WARPED_FUNGUS_ON_A_STICK", "CARROT_ON_A_STICK"));
|
||||
|
||||
// Below 1.15
|
||||
filters.add(new IrisCompatabilityItemFilter("HONEY_BOTTLE", "GLASS_BOTTLE"));
|
||||
filters.add(new IrisCompatabilityItemFilter("HONEYCOMB", "GLASS"));
|
||||
|
||||
// Below 1.14
|
||||
filters.add(new IrisCompatabilityItemFilter("SWEET_BERRIES", "APPLE"));
|
||||
filters.add(new IrisCompatabilityItemFilter("SUSPICIOUS_STEW", "MUSHROOM_STEW"));
|
||||
filters.add(new IrisCompatabilityItemFilter("BLACK_DYE", "INK_SAC"));
|
||||
filters.add(new IrisCompatabilityItemFilter("WHITE_DYE", "BONE_MEAL"));
|
||||
filters.add(new IrisCompatabilityItemFilter("BROWN_DYE", "COCOA_BEANS"));
|
||||
filters.add(new IrisCompatabilityItemFilter("BLUE_DYE", "LAPIS_LAZULI"));
|
||||
filters.add(new IrisCompatabilityItemFilter("CROSSBOW", "BOW"));
|
||||
filters.add(new IrisCompatabilityItemFilter("FLOWER_BANNER_PATTERN", "CORNFLOWER"));
|
||||
filters.add(new IrisCompatabilityItemFilter("SKULL_BANNER_PATTERN", "BONE"));
|
||||
filters.add(new IrisCompatabilityItemFilter("GLOBE_BANNER_PATTERN", "WHEAT_SEEDS"));
|
||||
filters.add(new IrisCompatabilityItemFilter("MOJANG_BANNER_PATTERN", "DIRT"));
|
||||
filters.add(new IrisCompatabilityItemFilter("CREEPER_BANNER_PATTERN", "CREEPER_HEAD"));
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
private static KList<IrisCompatabilityBlockFilter> getDefaultBlockCompatabilityFilters() {
|
||||
KList<IrisCompatabilityBlockFilter> filters = new KList<>();
|
||||
|
||||
// Below 1.16
|
||||
filters.add(new IrisCompatabilityBlockFilter("WEEPING_VINES", "NETHER_FENCE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("WEEPING_VINES_PLANT", "NETHER_FENCE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("WARPED_WART_BLOCK", "NETHER_WART_BLOCK"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("TWISTING_VINES", "BAMBOO"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("TWISTING_VINES_PLANT", "BAMBOO"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("TARGET", "COBBLESTONE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SOUL_SOIL", "SOULSAND"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SOUL_TORCH", "TORCH"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SOUL_LANTERN", "LANTERN"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SOUL_FIRE", "FIRE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SOUL_CAMPFIRE", "CAMPFIRE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SHROOMLIGHT", "GLOWSTONE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("RESPAWN_ANCHOR", "OBSIDIAN"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("NETHER_SPROUTS", "RED_MUSHROOM"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("NETHER_GOLD_ORE", "GOLD_ORE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("LODESTONE", "STONE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("STRIPPED_WARPED_HYPHAE", "BROWN_MUSHROOM_BLOCK"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("STRIPPED_CRIMSON_HYPHAE", "RED_MUSHROOM_BLOCK"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("WARPED_HYPHAE", "MUSHROOM_STEM"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CRIMSON_HYPHAE", "RED_MUSHROOM_BLOCK"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("GILDED_BLACKSTONE", "COBBLESTONE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CRYING_OBSIDIAN", "OBSIDIAN"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("STRIPPED_WARPED_STEM", "MUSHROOM_STEM"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("STRIPPED_CRIMSON_STEM", "MUSHROOM_STEM"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("WARPED_STEM", "MUSHROOM_STEM"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CRIMSON_STEM", "MUSHROOM_STEM"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CRIMSON_ROOTS", "RED_MUSHROOM"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("WARPED_ROOTS", "BROWN_MUSHROOM"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CRIMSON_PLANKS", "OAK_PLANKS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("WARPED_PLANKS", "OAK_PLANKS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("WARPED_NYLIUM", "MYCELIUM"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CRIMSON_NYLIUM", "MYCELIUM"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("WARPED_FUNGUS", "BROWN_MUSHROOM"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CRIMSON_FUNGUS", "RED_MUSHROOM"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CRACKED_NETHER_BRICKS", "NETHER_BRICKS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CHISELED_NETHER_BRICKS", "NETHER_BRICKS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("NETHER_FENCE", "LEGACY_NETHER_FENCE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CHAIN", "IRON_BARS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("NETHERITE_BLOCK", "QUARTZ_BLOCK"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("BLACKSTONE", "COBBLESTONE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("BASALT", "STONE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("ANCIENT_DEBRIS", "NETHERRACK"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("NETHERRACK", "LEGACY_NETHERRACK"));
|
||||
|
||||
// Below 1.15
|
||||
filters.add(new IrisCompatabilityBlockFilter("HONEY_BLOCK", "OAK_LEAVES"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("BEEHIVE", "OAK_LEAVES"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("BEE_NEST", "OAK_LEAVES"));
|
||||
|
||||
// Below 1.14
|
||||
filters.add(new IrisCompatabilityBlockFilter("GRANITE_WALL", "COBBLESTONE_WALL"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("BLUE_ICE", "PACKED_ICE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("DIORITE_WALL", "COBBLESTONE_WALL"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("ANDESITE_WALL", "COBBLESTONE_WALL"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SWEET_BERRY_BUSH", "GRASS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("STONECUTTER", "CRAFTING_TABLE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SANDSTONE_STAIRS", "LEGACY_SANDSTONE_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SMOOTH_SANDSTONE_STAIRS", "LEGACY_SANDSTONE_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("MOSSY_COBBLESTONE_STAIRS", "COBBLESTONE_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("MOSSY_STONE_BRICK_STAIRS", "STONE_BRICK_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("POLISHED_GRANITE_STAIRS", "COBBLESTONE_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("GRANITE_STAIRS", "COBBLESTONE_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("POLISHED_DIORITE_STAIRS", "COBBLESTONE_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("DIORITE_STAIRS", "COBBLESTONE_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("POLISHED_ANDESITE_STAIRS", "COBBLESTONE_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("ANDESITE_STAIRS", "COBBLESTONE_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("STONE_STAIRS", "COBBLESTONE_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("END_STONE_BRICK_STAIRS", "LEGACY_SANDSTONE_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("NETHER_BRICK_STAIRS", "LEGACY_NETHER_BRICK_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("RED_NETHER_BRICK_STAIRS", "NETHER_BRICK_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SMOOTH_QUARTZ_STAIRS", "LEGACY_QUARTZ_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("QUARTZ_STAIRS", "LEGACY_QUARTZ_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("RED_SANDSTONE_STAIRS", "LEGACY_RED_SANDSTONE_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SMOOTH_RED_SANDSTONE_STAIRS", "LEGACY_RED_SANDSTONE_STAIRS"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("STONE_SLAB", "SMOOTH_STONE_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SMOKER", "FURNACE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SMITHING_TABLE", "CRAFTING_TABLE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("END_STONE_BRICK_SLAB", "SANDSTONE_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("RED_NETHER_BRICK_SLAB", "NETHER_BRICK_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SMOOTH_QUARTZ_SLAB", "QUARTZ_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CUT_SANDSTONE_SLAB", "SANDSTONE_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CUT_RED_SANDSTONE_SLAB", "RED_SANDSTONE_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SMOOTH_RED_SANDSTONE_SLAB", "RED_SANDSTONE_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SMOOTH_SANDSTONE_SLAB", "SANDSTONE_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("MOSSY_COBBLESTONE_SLAB", "COBBLESTONE_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("MOSSY_STONE_BRICK_SLAB", "STONE_BRICK_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("STONE_SLAB", "SMOOTH_STONE_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("ANDESITE_SLAB", "COBBLESTONE_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("ANDESITE_SLAB", "COBBLESTONE_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("DIORITE_SLAB", "COBBLESTONE_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("GRANITE_SLAB", "COBBLESTONE_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("POLISHED_ANDESITE_SLAB", "SMOOTH_STONE_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("POLISHED_DIORITE_SLAB", "SMOOTH_STONE_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("POLISHED_GRANITE_SLAB", "SMOOTH_STONE_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("WARPED_WALL_SIGN", "LEGACY_WALL_SIGN"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("WARPED_SIGN", "LEGACY_SIGN_POST"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SPRUCE_WALL_SIGN", "LEGACY_WALL_SIGN"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SPRUCE_SIGN", "LEGACY_SIGN_POST"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("OAK_WALL_SIGN", "LEGACY_WALL_SIGN"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("OAK_SIGN", "LEGACY_SIGN_POST"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("JUNGLE_WALL_SIGN", "LEGACY_WALL_SIGN"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("JUNGLE_SIGN", "LEGACY_SIGN_POST"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("DARK_OAK_WALL_SIGN", "LEGACY_WALL_SIGN"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("DARK_OAK_SIGN", "LEGACY_SIGN_POST"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CRIMSON_WALL_SIGN", "LEGACY_WALL_SIGN"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CRIMSON_SIGN", "LEGACY_SIGN_POST"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("BIRCH_WALL_SIGN", "LEGACY_WALL_SIGN"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("BIRCH_SIGN", "LEGACY_SIGN_POST"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("ACACIA_WALL_SIGN", "LEGACY_WALL_SIGN"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("ACACIA_SIGN", "LEGACY_SIGN_POST"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("SCAFFOLDING", "BIRCH_FENCE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("LOOM", "LOOM"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("LECTERN", "BOOKSHELF"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("LANTERN", "REDSTONE_LAMP"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("JIGSAW", "AIR"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("GRINDSTONE", "COBBLESTONE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("FLETCHING_TABLE", "CRAFTING_TABLE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("COMPOSTER", "CHEST"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CARTOGRAPHY_TABLE", "CRAFTING_TABLE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("CAMPFIRE", "DARK_OAK_SLAB"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("BLAST_FURNACE", "FURNACE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("BELL", "REDSTONE_LAMP"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("minecraft:barrel[facing=south]", "minecraft:hay_bale[axis=z]", true));
|
||||
filters.add(new IrisCompatabilityBlockFilter("minecraft:barrel[facing=north]", "minecraft:hay_bale[axis=z]", true));
|
||||
filters.add(new IrisCompatabilityBlockFilter("minecraft:barrel[facing=east]", "minecraft:hay_bale[axis=x]", true));
|
||||
filters.add(new IrisCompatabilityBlockFilter("minecraft:barrel[facing=west]", "minecraft:hay_bale[axis=x]", true));
|
||||
filters.add(new IrisCompatabilityBlockFilter("minecraft:barrel[facing=up]", "minecraft:hay_bale[axis=y]", true));
|
||||
filters.add(new IrisCompatabilityBlockFilter("minecraft:barrel[facing=down]", "minecraft:hay_bale[axis=y]", true));
|
||||
filters.add(new IrisCompatabilityBlockFilter("BAMBOO", "BIRCH_FENCE"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("BAMBOO_SAPLING", "BIRCH_SAPLING"));
|
||||
filters.add(new IrisCompatabilityBlockFilter("POTTED_BAMBOO", "POTTED_BIRCH_SAPLING"));
|
||||
|
||||
return filters;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.B;
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.Required;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Find and replace object materials for compatability")
|
||||
@Data
|
||||
public class IrisCompatabilityBlockFilter {
|
||||
@Required
|
||||
|
||||
@Desc("When iris sees this block, and it's not reconized")
|
||||
private String when = "";
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("Replace it with this block. Dont worry if this block is also not reconized, iris repeat this compat check.")
|
||||
private String supplement = "";
|
||||
|
||||
|
||||
@Desc("If exact is true, it compares block data for example minecraft:some_log[axis=x]")
|
||||
private boolean exact = false;
|
||||
|
||||
private final transient AtomicCache<BlockData> findData = new AtomicCache<>(true);
|
||||
private final transient AtomicCache<BlockData> replaceData = new AtomicCache<>(true);
|
||||
|
||||
public IrisCompatabilityBlockFilter(String when, String supplement) {
|
||||
this(when, supplement, false);
|
||||
}
|
||||
|
||||
public BlockData getFind() {
|
||||
return findData.aquire(() -> B.get(when));
|
||||
}
|
||||
|
||||
public BlockData getReplace() {
|
||||
return replaceData.aquire(() ->
|
||||
{
|
||||
BlockData b = B.getOrNull(supplement);
|
||||
|
||||
if (b == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Iris.warn("Compat: Using " + supplement + " in place of " + when + " since this server doesnt support '" + supplement + "'");
|
||||
|
||||
return b;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.B;
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.Required;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.Material;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@Desc("Find and replace object items for compatability")
|
||||
@Data
|
||||
public class IrisCompatabilityItemFilter {
|
||||
@Required
|
||||
|
||||
@Desc("When iris sees this block, and it's not reconized")
|
||||
private String when = "";
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("Replace it with this block. Dont worry if this block is also not reconized, iris repeat this compat check.")
|
||||
private String supplement = "";
|
||||
|
||||
private final transient AtomicCache<Material> findData = new AtomicCache<>(true);
|
||||
private final transient AtomicCache<Material> replaceData = new AtomicCache<>(true);
|
||||
|
||||
public IrisCompatabilityItemFilter(String when, String supplement) {
|
||||
this.when = when;
|
||||
this.supplement = supplement;
|
||||
}
|
||||
|
||||
public Material getFind() {
|
||||
return findData.aquire(() -> B.getMaterial(when));
|
||||
}
|
||||
|
||||
public Material getReplace() {
|
||||
return replaceData.aquire(() ->
|
||||
{
|
||||
Material b = B.getMaterialOrNull(supplement);
|
||||
|
||||
if (b == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Iris.verbose("Compat: Using " + supplement + " in place of " + when + " since this server doesnt support '" + supplement + "'");
|
||||
|
||||
return b;
|
||||
});
|
||||
}
|
||||
}
|
||||
228
src/main/java/com/volmit/iris/engine/object/IrisDecorator.java
Normal file
228
src/main/java/com/volmit/iris/engine/object/IrisDecorator.java
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.noise.CNG;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("A biome decorator is used for placing flowers, grass, cacti and so on")
|
||||
@Data
|
||||
public class IrisDecorator {
|
||||
|
||||
@Desc("The varience dispersion is used when multiple blocks are put in the palette. Scatter scrambles them, Wispy shows streak-looking varience")
|
||||
private IrisGeneratorStyle variance = NoiseStyle.STATIC.style();
|
||||
|
||||
|
||||
@Desc("Forcefully place this decorant anywhere it is supposed to go even if it should not go on a specific surface block. For example, you could force tallgrass to place on top of stone by using this.")
|
||||
private boolean forcePlace = false;
|
||||
|
||||
|
||||
@Desc("Dispersion is used to pick places to spawn. Scatter randomly places them (vanilla) or Wispy for a streak like patch system.")
|
||||
private IrisGeneratorStyle style = NoiseStyle.STATIC.style();
|
||||
|
||||
@DependsOn({"stackMin", "stackMax"})
|
||||
@Desc("If this decorator has a height more than 1 this changes how it picks the height between your maxes. Scatter = random, Wispy = wavy heights")
|
||||
private IrisGeneratorStyle heightVariance = NoiseStyle.STATIC.style();
|
||||
|
||||
|
||||
@Desc("Tells iris where this decoration is a part of. I.e. SHORE_LINE or SEA_SURFACE")
|
||||
private DecorationPart partOf = DecorationPart.NONE;
|
||||
|
||||
@DependsOn({"stackMin", "stackMax"})
|
||||
@MinNumber(1)
|
||||
@MaxNumber(256) // TODO: WARNING HEIGHT
|
||||
|
||||
@Desc("The minimum repeat stack height (setting to 3 would stack 3 of <block> on top of each other")
|
||||
private int stackMin = 1;
|
||||
|
||||
@DependsOn({"stackMin", "stackMax"})
|
||||
@MinNumber(1)
|
||||
@MaxNumber(256) // TODO: WARNING HEIGHT
|
||||
|
||||
@Desc("The maximum repeat stack height")
|
||||
private int stackMax = 1;
|
||||
|
||||
@Required
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1)
|
||||
@Desc("The chance for this decorator to decorate at a given X,Y coordinate. This is hit 256 times per chunk (per surface block)")
|
||||
// TODO: WARNING HEIGHT
|
||||
private double chance = 0.1;
|
||||
|
||||
@Required
|
||||
@ArrayType(min = 1, type = IrisBlockData.class)
|
||||
@Desc("The palette of blocks to pick from when this decorator needs to place.")
|
||||
private KList<IrisBlockData> palette = new KList<IrisBlockData>().qadd(new IrisBlockData("grass"));
|
||||
|
||||
@ArrayType(min = 1, type = IrisBlockData.class)
|
||||
@Desc("The palette of blocks used at the very top of a 'stackMax' of higher than 1. For example, bamboo tops.")
|
||||
private KList<IrisBlockData> topPalette = new KList<>();
|
||||
|
||||
@DependsOn("topPalette")
|
||||
@MinNumber(0.01)
|
||||
@MaxNumber(1.0)
|
||||
@Desc("When the stack passes the top threshold, the top palette will start being used instead of the normal palette.")
|
||||
private double topThreshold = 1.0;
|
||||
|
||||
private final transient AtomicCache<CNG> layerGenerator = new AtomicCache<>();
|
||||
private final transient AtomicCache<CNG> varianceGenerator = new AtomicCache<>();
|
||||
private final transient AtomicCache<CNG> heightGenerator = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<BlockData>> blockData = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<BlockData>> blockDataTops = new AtomicCache<>();
|
||||
|
||||
public int getHeight(RNG rng, double x, double z, IrisDataManager data) {
|
||||
if (stackMin == stackMax) {
|
||||
return stackMin;
|
||||
}
|
||||
|
||||
return getHeightGenerator(rng, data).fit(stackMin, stackMax, x / heightVariance.getZoom(), z / heightVariance.getZoom()) + 1;
|
||||
}
|
||||
|
||||
public CNG getHeightGenerator(RNG rng, IrisDataManager data) {
|
||||
return heightGenerator.aquire(() ->
|
||||
heightVariance.create(rng.nextParallelRNG(getBlockData(data).size() + stackMax + stackMin)));
|
||||
}
|
||||
|
||||
public CNG getGenerator(RNG rng, IrisDataManager data) {
|
||||
return layerGenerator.aquire(() -> style.create(rng.nextParallelRNG(getBlockData(data).size())));
|
||||
}
|
||||
|
||||
public CNG getVarianceGenerator(RNG rng, IrisDataManager data) {
|
||||
return varianceGenerator.aquire(() ->
|
||||
variance.create(
|
||||
rng.nextParallelRNG(getBlockData(data).size()))
|
||||
|
||||
.scale(1D / variance.getZoom()));
|
||||
}
|
||||
|
||||
public KList<IrisBlockData> add(String b) {
|
||||
palette.add(new IrisBlockData(b));
|
||||
return palette;
|
||||
}
|
||||
|
||||
public BlockData getBlockData(IrisBiome b, RNG rng, double x, double z, IrisDataManager data) {
|
||||
if (getBlockData(data).isEmpty()) {
|
||||
Iris.warn("Empty Block Data for " + b.getName());
|
||||
return null;
|
||||
}
|
||||
|
||||
double xx = x / style.getZoom();
|
||||
double zz = z / style.getZoom();
|
||||
|
||||
if (getGenerator(rng, data).fitDouble(0D, 1D, xx, zz) <= chance) {
|
||||
if (getBlockData(data).size() == 1) {
|
||||
return getBlockData(data).get(0);
|
||||
}
|
||||
|
||||
return getVarianceGenerator(rng, data).fit(getBlockData(data), z, x); //X and Z must be switched
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public BlockData getBlockData100(IrisBiome b, RNG rng, double x, double z, IrisDataManager data) {
|
||||
if (getBlockData(data).isEmpty()) {
|
||||
Iris.warn("Empty Block Data for " + b.getName());
|
||||
return null;
|
||||
}
|
||||
|
||||
double xx = x;
|
||||
double zz = z;
|
||||
|
||||
if (!getVarianceGenerator(rng, data).isStatic()) {
|
||||
xx = x / style.getZoom();
|
||||
zz = z / style.getZoom();
|
||||
}
|
||||
|
||||
if (getBlockData(data).size() == 1) {
|
||||
return getBlockData(data).get(0);
|
||||
}
|
||||
|
||||
return getVarianceGenerator(rng, data).fit(getBlockData(data), z, x).clone(); //X and Z must be switched
|
||||
}
|
||||
|
||||
public BlockData getBlockDataForTop(IrisBiome b, RNG rng, double x, double z, IrisDataManager data) {
|
||||
if (getBlockDataTops(data).isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
double xx = x / style.getZoom();
|
||||
double zz = z / style.getZoom();
|
||||
|
||||
if (getGenerator(rng, data).fitDouble(0D, 1D, xx, zz) <= chance) {
|
||||
if (getBlockData(data).size() == 1) {
|
||||
return getBlockDataTops(data).get(0);
|
||||
}
|
||||
|
||||
return getVarianceGenerator(rng, data).fit(getBlockDataTops(data), z, x); //X and Z must be switched
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public KList<BlockData> getBlockData(IrisDataManager data) {
|
||||
return blockData.aquire(() ->
|
||||
{
|
||||
KList<BlockData> blockData = new KList<>();
|
||||
for (IrisBlockData i : palette) {
|
||||
BlockData bx = i.getBlockData(data);
|
||||
if (bx != null) {
|
||||
for (int n = 0; n < i.getWeight(); n++) {
|
||||
blockData.add(bx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blockData;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<BlockData> getBlockDataTops(IrisDataManager data) {
|
||||
return blockDataTops.aquire(() ->
|
||||
{
|
||||
KList<BlockData> blockDataTops = new KList<>();
|
||||
for (IrisBlockData i : topPalette) {
|
||||
BlockData bx = i.getBlockData(data);
|
||||
if (bx != null) {
|
||||
for (int n = 0; n < i.getWeight(); n++) {
|
||||
blockDataTops.add(bx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blockDataTops;
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean isStacking() {
|
||||
return getStackMax() > 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.util.BlockVector;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Creates ore & other block deposits underground")
|
||||
@Data
|
||||
public class IrisDepositGenerator {
|
||||
@Required
|
||||
@MinNumber(0)
|
||||
@MaxNumber(256) // TODO: WARNING HEIGHT
|
||||
|
||||
@Desc("The minimum height this deposit can generate at")
|
||||
private int minHeight = 7;
|
||||
|
||||
@Required
|
||||
@MinNumber(0)
|
||||
@MaxNumber(256) // TODO: WARNING HEIGHT
|
||||
|
||||
@Desc("The maximum height this deposit can generate at")
|
||||
private int maxHeight = 55;
|
||||
|
||||
@Required
|
||||
@MinNumber(1)
|
||||
@MaxNumber(32)
|
||||
@Desc("The minimum amount of deposit blocks per clump")
|
||||
private int minSize = 3;
|
||||
|
||||
@Required
|
||||
@MinNumber(1)
|
||||
@MaxNumber(32)
|
||||
@Desc("The maximum amount of deposit blocks per clump")
|
||||
private int maxSize = 5;
|
||||
|
||||
@Required
|
||||
@MinNumber(1)
|
||||
@MaxNumber(128)
|
||||
@Desc("The maximum amount of clumps per chunk")
|
||||
private int maxPerChunk = 3;
|
||||
|
||||
@Required
|
||||
@MinNumber(0)
|
||||
@MaxNumber(128)
|
||||
@Desc("The minimum amount of clumps per chunk")
|
||||
private int minPerChunk = 1;
|
||||
|
||||
@Required
|
||||
@ArrayType(min = 1, type = IrisBlockData.class)
|
||||
@Desc("The palette of blocks to be used in this deposit generator")
|
||||
private KList<IrisBlockData> palette = new KList<>();
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(64)
|
||||
@Desc("Ore varience is how many different objects clumps iris will create")
|
||||
private int varience = 3;
|
||||
|
||||
private final transient AtomicCache<KList<IrisObject>> objects = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<BlockData>> blockData = new AtomicCache<>();
|
||||
|
||||
public IrisObject getClump(RNG rng, IrisDataManager rdata) {
|
||||
KList<IrisObject> objects = this.objects.aquire(() ->
|
||||
{
|
||||
RNG rngv = rng.nextParallelRNG(3957778);
|
||||
KList<IrisObject> objectsf = new KList<>();
|
||||
|
||||
for (int i = 0; i < varience; i++) {
|
||||
objectsf.add(generateClumpObject(rngv.nextParallelRNG(2349 * i + 3598), rdata));
|
||||
}
|
||||
|
||||
return objectsf;
|
||||
});
|
||||
return objects.get(rng.i(0, objects.size() - 1));
|
||||
}
|
||||
|
||||
public int getMaxDimension() {
|
||||
return Math.min(11, (int) Math.round(Math.pow(maxSize, 1D / 3D)));
|
||||
}
|
||||
|
||||
private IrisObject generateClumpObject(RNG rngv, IrisDataManager rdata) {
|
||||
int s = rngv.i(minSize, maxSize);
|
||||
int dim = Math.min(11, (int) Math.round(Math.pow(maxSize, 1D / 3D)));
|
||||
int w = dim / 2;
|
||||
IrisObject o = new IrisObject(dim, dim, dim);
|
||||
|
||||
if (s == 1) {
|
||||
o.getBlocks().put(o.getCenter(), nextBlock(rngv, rdata));
|
||||
} else {
|
||||
while (s > 0) {
|
||||
s--;
|
||||
BlockVector ang = new BlockVector(rngv.i(-w, w), rngv.i(-w, w), rngv.i(-w, w));
|
||||
BlockVector pos = o.getCenter().clone().add(ang).toBlockVector();
|
||||
o.getBlocks().put(pos, nextBlock(rngv, rdata));
|
||||
}
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
private BlockData nextBlock(RNG rngv, IrisDataManager rdata) {
|
||||
return getBlockData(rdata).get(rngv.i(0, getBlockData(rdata).size() - 1));
|
||||
}
|
||||
|
||||
public KList<BlockData> getBlockData(IrisDataManager rdata) {
|
||||
return blockData.aquire(() ->
|
||||
{
|
||||
KList<BlockData> blockData = new KList<>();
|
||||
|
||||
for (IrisBlockData ix : palette) {
|
||||
BlockData bx = ix.getBlockData(rdata);
|
||||
|
||||
if (bx != null) {
|
||||
blockData.add(bx);
|
||||
}
|
||||
}
|
||||
|
||||
return blockData;
|
||||
});
|
||||
}
|
||||
}
|
||||
503
src/main/java/com/volmit/iris/engine/object/IrisDimension.java
Normal file
503
src/main/java/com/volmit/iris/engine/object/IrisDimension.java
Normal file
@@ -0,0 +1,503 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.noise.CNG;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.data.DataProvider;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@SuppressWarnings("DefaultAnnotationParam")
|
||||
@Accessors(chain = true)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Desc("Represents a dimension")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisDimension extends IrisRegistrant {
|
||||
public static final BlockData STONE = Material.STONE.createBlockData();
|
||||
public static final BlockData WATER = Material.WATER.createBlockData();
|
||||
|
||||
@MinNumber(2)
|
||||
@Required
|
||||
|
||||
@Desc("The human readable name of this dimension")
|
||||
private String name = "A Dimension";
|
||||
|
||||
@Desc("You can create mutliple dimensions on top of each other taking up less height of the same world. Such as the nether with a floor + ceiling.")
|
||||
@ArrayType(min = 1, type = IrisDimensionIndex.class)
|
||||
private KList<IrisDimensionIndex> dimensionalComposite = new KList<>();
|
||||
|
||||
|
||||
@Desc("Create an inverted dimension in the sky (like the nether)")
|
||||
private IrisDimension sky = null;
|
||||
|
||||
@RegistryListJigsaw
|
||||
|
||||
@Desc("If defined, Iris will place the given jigsaw structure where minecraft should place the overworld stronghold.")
|
||||
private String stronghold;
|
||||
|
||||
|
||||
@Desc("Improves the biome grid variation by shuffling the cell grid more depending on the seed. This makes biomes across multiple seeds look far different than before.")
|
||||
private boolean aggressiveBiomeReshuffle = false;
|
||||
|
||||
|
||||
@Desc("Instead of a flat bottom, applies a clamp (using this noise style) to the bottom instead of a flat bottom. Useful for carving out center-dimensions in a dimension composite world.")
|
||||
private IrisShapedGeneratorStyle undercarriage = null;
|
||||
|
||||
|
||||
@Desc("Upon joining this world, Iris will send a resource pack request to the client. If they have previously selected yes, it will auto-switch depending on which dimension they go to.")
|
||||
private String resourcePack = "";
|
||||
|
||||
|
||||
@Desc("Entity spawns to override or add to this dimension")
|
||||
@ArrayType(min = 1, type = IrisEntitySpawnOverride.class)
|
||||
private KList<IrisEntitySpawnOverride> entitySpawnOverrides = new KList<>();
|
||||
|
||||
|
||||
@Desc("Add specific features in exact positions")
|
||||
@ArrayType(min = 1, type = IrisFeaturePositional.class)
|
||||
private KList<IrisFeaturePositional> specificFeatures = new KList<>();
|
||||
|
||||
|
||||
@Desc("Entity spawns during generation")
|
||||
@ArrayType(min = 1, type = IrisEntityInitialSpawn.class)
|
||||
private KList<IrisEntityInitialSpawn> entityInitialSpawns = new KList<>();
|
||||
|
||||
|
||||
@Desc("Add random chances for terrain features")
|
||||
@ArrayType(min = 1, type = IrisFeaturePotential.class)
|
||||
private KList<IrisFeaturePotential> features = new KList<>();
|
||||
|
||||
|
||||
@Desc("Reference loot tables in this area")
|
||||
private IrisLootReference loot = new IrisLootReference();
|
||||
|
||||
@MinNumber(0)
|
||||
@Desc("The version of this dimension. Changing this will stop users from accidentally upgrading (and breaking their worlds).")
|
||||
private int version = 1;
|
||||
|
||||
@ArrayType(min = 1, type = IrisBlockDrops.class)
|
||||
@Desc("Define custom block drops for this dimension")
|
||||
private KList<IrisBlockDrops> blockDrops = new KList<>();
|
||||
|
||||
|
||||
@Desc("Should bedrock be generated or not.")
|
||||
private boolean bedrock = true;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1)
|
||||
@Desc("The land chance. Up to 1.0 for total land or 0.0 for total sea")
|
||||
private double landChance = 0.625;
|
||||
|
||||
|
||||
@Desc("The placement style of regions")
|
||||
private IrisGeneratorStyle regionStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||
|
||||
|
||||
@Desc("The placement style of land/sea")
|
||||
private IrisGeneratorStyle continentalStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||
|
||||
|
||||
@Desc("The placement style of biomes")
|
||||
private IrisGeneratorStyle landBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||
|
||||
|
||||
@Desc("The placement style of biomes")
|
||||
private IrisGeneratorStyle shoreBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||
|
||||
|
||||
@Desc("The placement style of biomes")
|
||||
private IrisGeneratorStyle seaBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||
|
||||
|
||||
@Desc("The placement style of biomes")
|
||||
private IrisGeneratorStyle caveBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||
|
||||
|
||||
@Desc("The placement style of biomes")
|
||||
private IrisGeneratorStyle riverBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||
|
||||
|
||||
@Desc("The placement style of biomes")
|
||||
private IrisGeneratorStyle lakeBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||
|
||||
|
||||
@Desc("The placement style of biomes")
|
||||
private IrisGeneratorStyle islandBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||
|
||||
|
||||
@Desc("The placement style of biomes")
|
||||
private IrisGeneratorStyle islandBiomeChanceStyle = NoiseStyle.CELLULAR_HEIGHT_IRIS_DOUBLE.style();
|
||||
|
||||
|
||||
@Desc("The placement style of biomes")
|
||||
private IrisGeneratorStyle skylandBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
|
||||
|
||||
|
||||
@Desc("Generate caves or not.")
|
||||
private boolean caves = true;
|
||||
|
||||
|
||||
@Desc("Instead of filling objects with air, fills them with cobweb so you can see them")
|
||||
private boolean debugSmartBore = false;
|
||||
|
||||
|
||||
@Desc("Carve terrain or not")
|
||||
private boolean carving = true;
|
||||
|
||||
|
||||
@Desc("If defined, If air is defined below the area, this fluid will always place")
|
||||
private IrisCaveFluid forceFluid = new IrisCaveFluid();
|
||||
|
||||
|
||||
@Desc("Generate decorations or not")
|
||||
private boolean decorate = true;
|
||||
|
||||
|
||||
@Desc("Generate ravines or not")
|
||||
private boolean ravines = false;
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("The rarity of a ravine layer having a lib (or rib) that sticks in or out by one block. Minecraft's default is 3.")
|
||||
private int ravineRibRarity = 2;
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("The rarity of ravines. Each chunk has a 1 in X chance")
|
||||
private int ravineRarity = 50;
|
||||
|
||||
|
||||
@Desc("Use post processing or not")
|
||||
private boolean postProcessing = true;
|
||||
|
||||
|
||||
@Desc("Add slabs in post processing")
|
||||
private boolean postProcessingSlabs = true;
|
||||
|
||||
|
||||
@Desc("Add painted walls in post processing")
|
||||
private boolean postProcessingWalls = true;
|
||||
|
||||
|
||||
@Desc("Use post processing for caves or not")
|
||||
private boolean postProcessCaves = true;
|
||||
|
||||
|
||||
@Desc("The world environment")
|
||||
private Environment environment = Environment.NORMAL;
|
||||
|
||||
@RegistryListRegion
|
||||
@Required
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
@Desc("Define all of the regions to include in this dimension. Dimensions -> Regions -> Biomes -> Objects etc")
|
||||
private KList<String> regions = new KList<>();
|
||||
|
||||
@ArrayType(min = 1, type = IrisJigsawStructurePlacement.class)
|
||||
@Desc("Jigsaw structures")
|
||||
private KList<IrisJigsawStructurePlacement> jigsawStructures = new KList<>();
|
||||
|
||||
@Required
|
||||
@MinNumber(0)
|
||||
@MaxNumber(255)
|
||||
@Desc("The fluid height for this dimension")
|
||||
private int fluidHeight = 63;
|
||||
|
||||
@RegistryListBiome
|
||||
|
||||
@Desc("Keep this either undefined or empty. Setting any biome name into this will force iris to only generate the specified biome. Great for testing.")
|
||||
private String focus = "";
|
||||
|
||||
@RegistryListBiome
|
||||
|
||||
@Desc("Keep this either undefined or empty. Setting any region name into this will force iris to only generate the specified region. Great for testing.")
|
||||
private String focusRegion = "";
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@MaxNumber(512)
|
||||
@Desc("Zoom in or out the biome size. Higher = bigger biomes")
|
||||
private double biomeZoom = 5D;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@MaxNumber(512)
|
||||
@Desc("Zoom in or out the terrain. This stretches the terrain. Due to performance improvements, Higher than 2.0 may cause weird rounding artifacts. Lower = more terrain changes per block. Its a true zoom-out.")
|
||||
private double terrainZoom = 1D;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(360)
|
||||
@Desc("You can rotate the input coordinates by an angle. This can make terrain appear more natural (less sharp corners and lines). This literally rotates the entire dimension by an angle. Hint: Try 12 degrees or something not on a 90 or 45 degree angle.")
|
||||
private double dimensionAngleDeg = 0;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(8192)
|
||||
@Desc("Coordinate fracturing applies noise to the input coordinates. This creates the 'iris swirls' and wavy features. The distance pushes these waves further into places they shouldnt be. This is a block value multiplier.")
|
||||
private double coordFractureDistance = 20;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@MaxNumber(512)
|
||||
@Desc("Coordinate fracturing zoom. Higher = less frequent warping, Lower = more frequent and rapid warping / swirls.")
|
||||
private double coordFractureZoom = 8;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@MaxNumber(512)
|
||||
@Desc("This zooms in the land space")
|
||||
private double landZoom = 1;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@MaxNumber(512)
|
||||
@Desc("This zooms oceanic biomes")
|
||||
private double seaZoom = 1;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@MaxNumber(512)
|
||||
@Desc("Zoom in continents")
|
||||
private double continentZoom = 1;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@MaxNumber(512)
|
||||
@Desc("Change the size of regions")
|
||||
private double regionZoom = 1;
|
||||
|
||||
|
||||
@Desc("Disable this to stop placing schematics in biomes")
|
||||
private boolean placeObjects = true;
|
||||
|
||||
|
||||
@Desc("Prevent Leaf decay as if placed in creative mode")
|
||||
private boolean preventLeafDecay = false;
|
||||
|
||||
@ArrayType(min = 1, type = IrisDepositGenerator.class)
|
||||
@Desc("Define global deposit generators")
|
||||
private KList<IrisDepositGenerator> deposits = new KList<>();
|
||||
|
||||
@ArrayType(min = 1, type = IrisShapedGeneratorStyle.class)
|
||||
@Desc("Overlay additional noise on top of the interoplated terrain.")
|
||||
private KList<IrisShapedGeneratorStyle> overlayNoise = new KList<>();
|
||||
|
||||
@ArrayType(min = 1, type = IrisCaveLayer.class)
|
||||
@Desc("Define cave layers")
|
||||
private KList<IrisCaveLayer> caveLayers = new KList<>();
|
||||
|
||||
@ArrayType(min = 1, type = IrisCarveLayer.class)
|
||||
@Desc("Define carve layers")
|
||||
private KList<IrisCarveLayer> carveLayers = new KList<>();
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@MaxNumber(512)
|
||||
@Desc("The rock zoom mostly for zooming in on a wispy palette")
|
||||
private double rockZoom = 5;
|
||||
|
||||
|
||||
@Desc("The palette of blocks for 'stone'")
|
||||
private IrisMaterialPalette rockPalette = new IrisMaterialPalette().qclear().qadd("stone");
|
||||
|
||||
|
||||
@Desc("The palette of blocks for 'water'")
|
||||
private IrisMaterialPalette fluidPalette = new IrisMaterialPalette().qclear().qadd("water");
|
||||
|
||||
@ArrayType(min = 1, type = IrisBiomeMutation.class)
|
||||
@Desc("Define biome mutations for this dimension")
|
||||
private KList<IrisBiomeMutation> mutations = new KList<>();
|
||||
|
||||
private final transient AtomicCache<ChunkPosition> parallaxSize = new AtomicCache<>();
|
||||
private final transient AtomicCache<CNG> rockLayerGenerator = new AtomicCache<>();
|
||||
private final transient AtomicCache<CNG> fluidLayerGenerator = new AtomicCache<>();
|
||||
private final transient AtomicCache<CNG> coordFracture = new AtomicCache<>();
|
||||
private final transient AtomicCache<Double> sinr = new AtomicCache<>();
|
||||
private final transient AtomicCache<Double> cosr = new AtomicCache<>();
|
||||
private final transient AtomicCache<Double> rad = new AtomicCache<>();
|
||||
|
||||
public boolean hasSky() {
|
||||
return getSky() != null;
|
||||
}
|
||||
|
||||
public CNG getCoordFracture(RNG rng, int signature) {
|
||||
return coordFracture.aquire(() ->
|
||||
{
|
||||
CNG coordFracture = CNG.signature(rng.nextParallelRNG(signature));
|
||||
coordFracture.scale(0.012 / coordFractureZoom);
|
||||
return coordFracture;
|
||||
});
|
||||
}
|
||||
|
||||
public double getDimensionAngle() {
|
||||
return rad.aquire(() -> Math.toRadians(dimensionAngleDeg));
|
||||
}
|
||||
|
||||
public boolean isCarved(int x, int y, int z, RNG rng, int terrainHeight) {
|
||||
if (isCarving() && terrainHeight > getFluidHeight() || y < terrainHeight) {
|
||||
for (IrisCarveLayer j : getCarveLayers()) {
|
||||
if (j.isCarved(rng, x, y, z)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public Environment getEnvironment() {
|
||||
return environment;
|
||||
}
|
||||
|
||||
public boolean hasFocusRegion() {
|
||||
return !focusRegion.equals("");
|
||||
}
|
||||
|
||||
public String getFocusRegion() {
|
||||
return focusRegion;
|
||||
}
|
||||
|
||||
public double sinRotate() {
|
||||
return sinr.aquire(() -> Math.sin(getDimensionAngle()));
|
||||
}
|
||||
|
||||
public double cosRotate() {
|
||||
return cosr.aquire(() -> Math.cos(getDimensionAngle()));
|
||||
}
|
||||
|
||||
public KList<IrisRegion> getAllRegions(DataProvider g) {
|
||||
KList<IrisRegion> r = new KList<>();
|
||||
|
||||
for (String i : getRegions()) {
|
||||
r.add(g.getData().getRegionLoader().load(i));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
public KList<IrisRegion> getAllAnyRegions() {
|
||||
KList<IrisRegion> r = new KList<>();
|
||||
|
||||
for (String i : getRegions()) {
|
||||
r.add(IrisDataManager.loadAnyRegion(i));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getAllBiomes(DataProvider g) {
|
||||
KList<IrisBiome> r = new KList<>();
|
||||
|
||||
for (IrisRegion i : getAllRegions(g)) {
|
||||
if (i == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
r.addAll(i.getAllBiomes(g));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getAllAnyBiomes() {
|
||||
KList<IrisBiome> r = new KList<>();
|
||||
|
||||
for (IrisRegion i : getAllAnyRegions()) {
|
||||
if (i == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
r.addAll(i.getAllAnyBiomes());
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
public IrisGeneratorStyle getBiomeStyle(InferredType type) {
|
||||
switch (type) {
|
||||
case CAVE:
|
||||
return caveBiomeStyle;
|
||||
case LAKE:
|
||||
return lakeBiomeStyle;
|
||||
case RIVER:
|
||||
return riverBiomeStyle;
|
||||
case LAND:
|
||||
return landBiomeStyle;
|
||||
case SEA:
|
||||
return seaBiomeStyle;
|
||||
case SHORE:
|
||||
return shoreBiomeStyle;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return landBiomeStyle;
|
||||
}
|
||||
|
||||
public boolean installDataPack(DataProvider data, File datapacks) {
|
||||
boolean write = false;
|
||||
boolean changed = false;
|
||||
|
||||
IO.delete(new File(datapacks, "iris/data/" + getLoadKey()));
|
||||
|
||||
for (IrisBiome i : getAllBiomes(data)) {
|
||||
if (i.isCustom()) {
|
||||
write = true;
|
||||
|
||||
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
|
||||
File output = new File(datapacks, "iris/data/" + getLoadKey() + "/worldgen/biome/" + j.getId() + ".json");
|
||||
|
||||
if (!output.exists()) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
Iris.verbose(" Installing Data Pack Biome: " + output.getPath());
|
||||
output.getParentFile().mkdirs();
|
||||
try {
|
||||
IO.writeAll(output, j.generateJson());
|
||||
} catch (IOException e) {Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (write) {
|
||||
File mcm = new File(datapacks, "iris/pack.mcmeta");
|
||||
try {
|
||||
IO.writeAll(mcm, """
|
||||
{
|
||||
"pack": {
|
||||
"description": "Iris Data Pack. This pack contains all installed Iris Packs' resources.",
|
||||
"pack_format": 7
|
||||
}
|
||||
}
|
||||
""");
|
||||
} catch (IOException e) {Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
Iris.verbose(" Installing Data Pack MCMeta: " + mcm.getPath());
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.MinNumber;
|
||||
import com.volmit.iris.util.RegistryListDimension;
|
||||
import com.volmit.iris.util.Required;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@SuppressWarnings("DefaultAnnotationParam")
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents an index for dimensions to take up vertical slots in the same world")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisDimensionIndex {
|
||||
@Required
|
||||
|
||||
@Desc("The weight of this dimension. If there are 2 dimensions, if the weight is the same on both, both dimensions will take up 128 blocks of height.")
|
||||
private double weight = 1D;
|
||||
|
||||
|
||||
@Desc("If inverted is set to true, the dimension will be updide down in the world")
|
||||
private boolean inverted = false;
|
||||
|
||||
|
||||
@Desc("Only one dimension layer should be set to primary. The primary dimension layer is where players spawn, and the biomes that the vanilla structure system uses to figure out what structures to place.")
|
||||
private boolean primary = false;
|
||||
|
||||
|
||||
@Required
|
||||
@RegistryListDimension
|
||||
@MinNumber(1)
|
||||
@Desc("Name of dimension")
|
||||
private String dimension = "";
|
||||
}
|
||||
403
src/main/java/com/volmit/iris/engine/object/IrisDirection.java
Normal file
403
src/main/java/com/volmit/iris/engine/object/IrisDirection.java
Normal file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Cuboid.CuboidDirection;
|
||||
import com.volmit.iris.util.*;
|
||||
import org.bukkit.Axis;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.type.Jigsaw;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Directions
|
||||
*
|
||||
* @author cyberpwn
|
||||
*/
|
||||
@Desc("A direction object")
|
||||
public enum IrisDirection {
|
||||
UP_POSITIVE_Y(0, 1, 0, CuboidDirection.Up),
|
||||
DOWN_NEGATIVE_Y(0, -1, 0, CuboidDirection.Down),
|
||||
NORTH_NEGATIVE_Z(0, 0, -1, CuboidDirection.North),
|
||||
SOUTH_POSITIVE_Z(0, 0, 1, CuboidDirection.South),
|
||||
EAST_POSITIVE_X(1, 0, 0, CuboidDirection.East),
|
||||
WEST_NEGATIVE_X(-1, 0, 0, CuboidDirection.West);
|
||||
|
||||
private static KMap<GBiset<IrisDirection, IrisDirection>, DOP> permute = null;
|
||||
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final CuboidDirection f;
|
||||
|
||||
public static IrisDirection getDirection(BlockFace f) {
|
||||
return switch (f) {
|
||||
case DOWN -> DOWN_NEGATIVE_Y;
|
||||
case EAST, EAST_NORTH_EAST, EAST_SOUTH_EAST -> EAST_POSITIVE_X;
|
||||
case NORTH, NORTH_NORTH_WEST, NORTH_EAST, NORTH_NORTH_EAST, NORTH_WEST -> NORTH_NEGATIVE_Z;
|
||||
case SELF, UP -> UP_POSITIVE_Y;
|
||||
case SOUTH, SOUTH_EAST, SOUTH_SOUTH_EAST, SOUTH_SOUTH_WEST, SOUTH_WEST -> SOUTH_POSITIVE_Z;
|
||||
case WEST, WEST_NORTH_WEST, WEST_SOUTH_WEST -> WEST_NEGATIVE_X;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public static IrisDirection fromJigsawBlock(String direction) {
|
||||
for (IrisDirection i : IrisDirection.values()) {
|
||||
if (i.name().toLowerCase().split("\\Q_\\E")[0]
|
||||
.equals(direction.split("\\Q_\\E")[0])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IrisDirection getDirection(Jigsaw.Orientation orientation) {
|
||||
return switch (orientation) {
|
||||
case DOWN_EAST, UP_EAST, EAST_UP -> EAST_POSITIVE_X;
|
||||
case DOWN_NORTH, UP_NORTH, NORTH_UP -> NORTH_NEGATIVE_Z;
|
||||
case DOWN_SOUTH, UP_SOUTH, SOUTH_UP -> SOUTH_POSITIVE_Z;
|
||||
case DOWN_WEST, UP_WEST, WEST_UP -> WEST_NEGATIVE_X;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return switch (this) {
|
||||
case DOWN_NEGATIVE_Y -> "Down";
|
||||
case EAST_POSITIVE_X -> "East";
|
||||
case NORTH_NEGATIVE_Z -> "North";
|
||||
case SOUTH_POSITIVE_Z -> "South";
|
||||
case UP_POSITIVE_Y -> "Up";
|
||||
case WEST_NEGATIVE_X -> "West";
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public boolean isVertical() {
|
||||
return equals(DOWN_NEGATIVE_Y) || equals(UP_POSITIVE_Y);
|
||||
}
|
||||
|
||||
public static IrisDirection closest(Vector v) {
|
||||
double m = Double.MAX_VALUE;
|
||||
IrisDirection s = null;
|
||||
|
||||
for (IrisDirection i : values()) {
|
||||
Vector x = i.toVector();
|
||||
double g = x.distance(v);
|
||||
|
||||
if (g < m) {
|
||||
m = g;
|
||||
s = i;
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
public static IrisDirection closest(Vector v, IrisDirection... d) {
|
||||
double m = Double.MAX_VALUE;
|
||||
IrisDirection s = null;
|
||||
|
||||
for (IrisDirection i : d) {
|
||||
Vector x = i.toVector();
|
||||
double g = x.distance(v);
|
||||
|
||||
if (g < m) {
|
||||
m = g;
|
||||
s = i;
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
public static IrisDirection closest(Vector v, KList<IrisDirection> d) {
|
||||
double m = Double.MAX_VALUE;
|
||||
IrisDirection s = null;
|
||||
|
||||
for (IrisDirection i : d) {
|
||||
Vector x = i.toVector();
|
||||
double g = x.distance(v);
|
||||
|
||||
if (g < m) {
|
||||
m = g;
|
||||
s = i;
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
public Vector toVector() {
|
||||
return new Vector(x, y, z);
|
||||
}
|
||||
|
||||
public boolean isCrooked(IrisDirection to) {
|
||||
if (equals(to.reverse())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !equals(to);
|
||||
}
|
||||
|
||||
IrisDirection(int x, int y, int z, CuboidDirection f) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
public Vector angle(Vector initial, IrisDirection d) {
|
||||
calculatePermutations();
|
||||
|
||||
for (Map.Entry<GBiset<IrisDirection, IrisDirection>, DOP> entry : permute.entrySet()) {
|
||||
GBiset<IrisDirection, IrisDirection> i = entry.getKey();
|
||||
if (i.getA().equals(this) && i.getB().equals(d)) {
|
||||
return entry.getValue().op(initial);
|
||||
}
|
||||
}
|
||||
|
||||
return initial;
|
||||
}
|
||||
|
||||
public IrisDirection reverse() {
|
||||
switch (this) {
|
||||
case DOWN_NEGATIVE_Y:
|
||||
return UP_POSITIVE_Y;
|
||||
case EAST_POSITIVE_X:
|
||||
return WEST_NEGATIVE_X;
|
||||
case NORTH_NEGATIVE_Z:
|
||||
return SOUTH_POSITIVE_Z;
|
||||
case SOUTH_POSITIVE_Z:
|
||||
return NORTH_NEGATIVE_Z;
|
||||
case UP_POSITIVE_Y:
|
||||
return DOWN_NEGATIVE_Y;
|
||||
case WEST_NEGATIVE_X:
|
||||
return EAST_POSITIVE_X;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return EAST_POSITIVE_X;
|
||||
}
|
||||
|
||||
public int x() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int y() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public int z() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public CuboidDirection f() {
|
||||
return f;
|
||||
}
|
||||
|
||||
public static KList<IrisDirection> news() {
|
||||
return new KList<IrisDirection>().add(NORTH_NEGATIVE_Z, EAST_POSITIVE_X, WEST_NEGATIVE_X, SOUTH_POSITIVE_Z);
|
||||
}
|
||||
|
||||
public static IrisDirection getDirection(Vector v) {
|
||||
Vector k = VectorMath.triNormalize(v.clone().normalize());
|
||||
|
||||
for (IrisDirection i : udnews()) {
|
||||
if (i.x == k.getBlockX() && i.y == k.getBlockY() && i.z == k.getBlockZ()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return IrisDirection.NORTH_NEGATIVE_Z;
|
||||
}
|
||||
|
||||
public static KList<IrisDirection> udnews() {
|
||||
return new KList<IrisDirection>().add(UP_POSITIVE_Y, DOWN_NEGATIVE_Y, NORTH_NEGATIVE_Z, EAST_POSITIVE_X, WEST_NEGATIVE_X, SOUTH_POSITIVE_Z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the directional value from the given byte from common directional blocks
|
||||
* (MUST BE BETWEEN 0 and 5 INCLUSIVE)
|
||||
*
|
||||
* @param b the byte
|
||||
* @return the direction or null if the byte is outside of the inclusive range
|
||||
* 0-5
|
||||
*/
|
||||
public static IrisDirection fromByte(byte b) {
|
||||
if (b > 5 || b < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (b == 0) {
|
||||
return DOWN_NEGATIVE_Y;
|
||||
} else if (b == 1) {
|
||||
return UP_POSITIVE_Y;
|
||||
} else if (b == 2) {
|
||||
return NORTH_NEGATIVE_Z;
|
||||
} else if (b == 3) {
|
||||
return SOUTH_POSITIVE_Z;
|
||||
} else if (b == 4) {
|
||||
return WEST_NEGATIVE_X;
|
||||
} else {
|
||||
return EAST_POSITIVE_X;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the byte value represented in some directional blocks
|
||||
*
|
||||
* @return the byte value
|
||||
*/
|
||||
public byte byteValue() {
|
||||
switch (this) {
|
||||
case DOWN_NEGATIVE_Y:
|
||||
return 0;
|
||||
case EAST_POSITIVE_X:
|
||||
return 5;
|
||||
case NORTH_NEGATIVE_Z:
|
||||
return 2;
|
||||
case SOUTH_POSITIVE_Z:
|
||||
return 3;
|
||||
case UP_POSITIVE_Y:
|
||||
return 1;
|
||||
case WEST_NEGATIVE_X:
|
||||
return 4;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void calculatePermutations() {
|
||||
if (permute != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
permute = new KMap<>();
|
||||
|
||||
for (IrisDirection i : udnews()) {
|
||||
for (IrisDirection j : udnews()) {
|
||||
GBiset<IrisDirection, IrisDirection> b = new GBiset<>(i, j);
|
||||
|
||||
if (i.equals(j)) {
|
||||
permute.put(b, new DOP("DIRECT") {
|
||||
@Override
|
||||
public Vector op(Vector v) {
|
||||
return v;
|
||||
}
|
||||
});
|
||||
} else if (i.reverse().equals(j)) {
|
||||
if (i.isVertical()) {
|
||||
permute.put(b, new DOP("R180CCZ") {
|
||||
@Override
|
||||
public Vector op(Vector v) {
|
||||
return VectorMath.rotate90CCZ(VectorMath.rotate90CCZ(v));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
permute.put(b, new DOP("R180CCY") {
|
||||
@Override
|
||||
public Vector op(Vector v) {
|
||||
return VectorMath.rotate90CCY(VectorMath.rotate90CCY(v));
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (getDirection(VectorMath.rotate90CX(i.toVector())).equals(j)) {
|
||||
permute.put(b, new DOP("R90CX") {
|
||||
@Override
|
||||
public Vector op(Vector v) {
|
||||
return VectorMath.rotate90CX(v);
|
||||
}
|
||||
});
|
||||
} else if (getDirection(VectorMath.rotate90CCX(i.toVector())).equals(j)) {
|
||||
permute.put(b, new DOP("R90CCX") {
|
||||
@Override
|
||||
public Vector op(Vector v) {
|
||||
return VectorMath.rotate90CCX(v);
|
||||
}
|
||||
});
|
||||
} else if (getDirection(VectorMath.rotate90CY(i.toVector())).equals(j)) {
|
||||
permute.put(b, new DOP("R90CY") {
|
||||
@Override
|
||||
public Vector op(Vector v) {
|
||||
return VectorMath.rotate90CY(v);
|
||||
}
|
||||
});
|
||||
} else if (getDirection(VectorMath.rotate90CCY(i.toVector())).equals(j)) {
|
||||
permute.put(b, new DOP("R90CCY") {
|
||||
@Override
|
||||
public Vector op(Vector v) {
|
||||
return VectorMath.rotate90CCY(v);
|
||||
}
|
||||
});
|
||||
} else if (getDirection(VectorMath.rotate90CZ(i.toVector())).equals(j)) {
|
||||
permute.put(b, new DOP("R90CZ") {
|
||||
@Override
|
||||
public Vector op(Vector v) {
|
||||
return VectorMath.rotate90CZ(v);
|
||||
}
|
||||
});
|
||||
} else if (getDirection(VectorMath.rotate90CCZ(i.toVector())).equals(j)) {
|
||||
permute.put(b, new DOP("R90CCZ") {
|
||||
@Override
|
||||
public Vector op(Vector v) {
|
||||
return VectorMath.rotate90CCZ(v);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
permute.put(b, new DOP("FAIL") {
|
||||
@Override
|
||||
public Vector op(Vector v) {
|
||||
return v;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BlockFace getFace() {
|
||||
return switch (this) {
|
||||
case DOWN_NEGATIVE_Y -> BlockFace.DOWN;
|
||||
case EAST_POSITIVE_X -> BlockFace.EAST;
|
||||
case NORTH_NEGATIVE_Z -> BlockFace.NORTH;
|
||||
case SOUTH_POSITIVE_Z -> BlockFace.SOUTH;
|
||||
case UP_POSITIVE_Y -> BlockFace.UP;
|
||||
case WEST_NEGATIVE_X -> BlockFace.WEST;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public Axis getAxis() {
|
||||
return switch (this) {
|
||||
case DOWN_NEGATIVE_Y, UP_POSITIVE_Y -> Axis.Y;
|
||||
case EAST_POSITIVE_X, WEST_NEGATIVE_X -> Axis.X;
|
||||
case NORTH_NEGATIVE_Z, SOUTH_POSITIVE_Z -> Axis.Z;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
257
src/main/java/com/volmit/iris/engine/object/IrisEffect.java
Normal file
257
src/main/java/com/volmit/iris/engine/object/IrisEffect.java
Normal file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.framework.GeneratorAccess;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("An iris effect")
|
||||
@Data
|
||||
public class IrisEffect {
|
||||
|
||||
|
||||
@Desc("The potion effect to apply in this area")
|
||||
private String potionEffect = "";
|
||||
|
||||
|
||||
@Desc("The particle effect to apply in the area")
|
||||
private Particle particleEffect = null;
|
||||
|
||||
@DependsOn({"particleEffect"})
|
||||
@MinNumber(-32)
|
||||
@MaxNumber(32)
|
||||
@Desc("Randomly offset from the surface to this surface+value")
|
||||
private int particleOffset = 0;
|
||||
|
||||
@DependsOn({"particleEffect"})
|
||||
@MinNumber(-8)
|
||||
@MaxNumber(8)
|
||||
@Desc("The alt x, usually represents motion if the particle count is zero. Otherwise an offset.")
|
||||
private double particleAltX = 0;
|
||||
|
||||
@DependsOn({"particleEffect"})
|
||||
@MinNumber(-8)
|
||||
@MaxNumber(8)
|
||||
@Desc("The alt y, usually represents motion if the particle count is zero. Otherwise an offset.")
|
||||
private double particleAltY = 0;
|
||||
|
||||
@DependsOn({"particleEffect"})
|
||||
@MinNumber(-8)
|
||||
@MaxNumber(8)
|
||||
@Desc("The alt z, usually represents motion if the particle count is zero. Otherwise an offset.")
|
||||
private double particleAltZ = 0;
|
||||
|
||||
@DependsOn({"particleEffect"})
|
||||
@Desc("Randomize the altX by -altX to altX")
|
||||
private boolean randomAltX = true;
|
||||
|
||||
@DependsOn({"particleEffect"})
|
||||
@Desc("Randomize the altY by -altY to altY")
|
||||
private boolean randomAltY = false;
|
||||
|
||||
@DependsOn({"particleEffect"})
|
||||
@Desc("Randomize the altZ by -altZ to altZ")
|
||||
private boolean randomAltZ = true;
|
||||
|
||||
|
||||
@Desc("The sound to play")
|
||||
private Sound sound = null;
|
||||
|
||||
@DependsOn({"sound"})
|
||||
@MinNumber(0)
|
||||
@MaxNumber(512)
|
||||
@Desc("The max distance from the player the sound will play")
|
||||
private int soundDistance = 12;
|
||||
|
||||
@DependsOn({"sound", "maxPitch"})
|
||||
@MinNumber(0.01)
|
||||
@MaxNumber(1.99)
|
||||
@Desc("The minimum sound pitch")
|
||||
private double minPitch = 0.5D;
|
||||
|
||||
@DependsOn({"sound", "minVolume"})
|
||||
@MinNumber(0.01)
|
||||
@MaxNumber(1.99)
|
||||
@Desc("The max sound pitch")
|
||||
private double maxPitch = 1.5D;
|
||||
|
||||
@DependsOn({"sound"})
|
||||
@MinNumber(0.001)
|
||||
@MaxNumber(512)
|
||||
@Desc("The sound volume.")
|
||||
private double volume = 1.5D;
|
||||
|
||||
@DependsOn({"particleEffect"})
|
||||
@MinNumber(0)
|
||||
@MaxNumber(512)
|
||||
@Desc("The particle count. Try setting to zero for using the alt xyz to a motion value instead of an offset")
|
||||
private int particleCount = 0;
|
||||
|
||||
@DependsOn({"particleEffect"})
|
||||
@MinNumber(0)
|
||||
@MaxNumber(64)
|
||||
@Desc("How far away from the player particles can play")
|
||||
private int particleDistance = 20;
|
||||
|
||||
@DependsOn({"particleEffect"})
|
||||
@MinNumber(0)
|
||||
@MaxNumber(128)
|
||||
@Desc("How wide the particles can play (player's view left and right) RADIUS")
|
||||
private int particleDistanceWidth = 24;
|
||||
|
||||
@DependsOn({"particleEffect"})
|
||||
@Desc("An extra value for some particles... Which bukkit doesn't even document.")
|
||||
private double extra = 0;
|
||||
|
||||
@DependsOn({"potionEffect"})
|
||||
@MinNumber(-1)
|
||||
@MaxNumber(1024)
|
||||
@Desc("The Potion Strength or -1 to disable")
|
||||
private int potionStrength = -1;
|
||||
|
||||
@DependsOn({"potionEffect", "potionTicksMin"})
|
||||
@MinNumber(1)
|
||||
@Desc("The max time the potion will last for")
|
||||
private int potionTicksMax = 155;
|
||||
|
||||
@DependsOn({"potionEffect", "potionTicksMax"})
|
||||
@MinNumber(1)
|
||||
@Desc("The min time the potion will last for")
|
||||
private int potionTicksMin = 75;
|
||||
|
||||
@Required
|
||||
@MinNumber(0)
|
||||
@Desc("The effect interval in milliseconds")
|
||||
private int interval = 150;
|
||||
|
||||
@DependsOn({"particleEffect"})
|
||||
@MinNumber(0)
|
||||
@MaxNumber(16)
|
||||
@Desc("The effect distance start away")
|
||||
private int particleAway = 5;
|
||||
|
||||
@Required
|
||||
@MinNumber(1)
|
||||
@Desc("The chance is 1 in CHANCE per interval")
|
||||
private int chance = 50;
|
||||
|
||||
private final transient AtomicCache<PotionEffectType> pt = new AtomicCache<>();
|
||||
private final transient AtomicCache<ChronoLatch> latch = new AtomicCache<>();
|
||||
|
||||
public boolean canTick() {
|
||||
return latch.aquire(() -> new ChronoLatch(interval)).flip();
|
||||
}
|
||||
|
||||
public PotionEffectType getRealType() {
|
||||
return pt.aquire(() ->
|
||||
{
|
||||
PotionEffectType t = PotionEffectType.LUCK;
|
||||
|
||||
if (getPotionEffect().isEmpty()) {
|
||||
return t;
|
||||
}
|
||||
|
||||
try {
|
||||
for (PotionEffectType i : PotionEffectType.values()) {
|
||||
if (i.getName().toUpperCase().replaceAll("\\Q \\E", "_").equals(getPotionEffect())) {
|
||||
t = i;
|
||||
|
||||
return t;
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {Iris.reportError(e);
|
||||
|
||||
}
|
||||
|
||||
Iris.warn("Unknown Potion Effect Type: " + getPotionEffect());
|
||||
|
||||
return t;
|
||||
});
|
||||
}
|
||||
|
||||
public void apply(Player p, GeneratorAccess g) {
|
||||
if (!canTick()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (RNG.r.nextInt(chance) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sound != null) {
|
||||
Location part = p.getLocation().clone().add(RNG.r.i(-soundDistance, soundDistance), RNG.r.i(-soundDistance, soundDistance), RNG.r.i(-soundDistance, soundDistance));
|
||||
|
||||
J.s(() -> p.playSound(part, getSound(), (float) volume, (float) RNG.r.d(minPitch, maxPitch)));
|
||||
}
|
||||
|
||||
if (particleEffect != null) {
|
||||
Location part = p.getLocation().clone().add(p.getLocation().getDirection().clone().multiply(RNG.r.i(particleDistance) + particleAway)).clone().add(p.getLocation().getDirection().clone().rotateAroundY(Math.toRadians(90)).multiply(RNG.r.d(-particleDistanceWidth, particleDistanceWidth)));
|
||||
|
||||
part.setY(Math.round(g.getHeight(part.getBlockX(), part.getBlockZ())) + 1);
|
||||
part.add(RNG.r.d(), 0, RNG.r.d());
|
||||
if (extra != 0) {
|
||||
J.s(() -> p.spawnParticle(particleEffect, part.getX(), part.getY() + RNG.r.i(particleOffset),
|
||||
part.getZ(),
|
||||
particleCount,
|
||||
randomAltX ? RNG.r.d(-particleAltX, particleAltX) : particleAltX,
|
||||
randomAltY ? RNG.r.d(-particleAltY, particleAltY) : particleAltY,
|
||||
randomAltZ ? RNG.r.d(-particleAltZ, particleAltZ) : particleAltZ,
|
||||
extra));
|
||||
} else {
|
||||
J.s(() -> p.spawnParticle(particleEffect, part.getX(), part.getY() + RNG.r.i(particleOffset), part.getZ(),
|
||||
particleCount,
|
||||
randomAltX ? RNG.r.d(-particleAltX, particleAltX) : particleAltX,
|
||||
randomAltY ? RNG.r.d(-particleAltY, particleAltY) : particleAltY,
|
||||
randomAltZ ? RNG.r.d(-particleAltZ, particleAltZ) : particleAltZ));
|
||||
}
|
||||
}
|
||||
|
||||
if (potionStrength > -1) {
|
||||
if (p.hasPotionEffect(getRealType())) {
|
||||
PotionEffect e = p.getPotionEffect(getRealType());
|
||||
if (e.getAmplifier() > getPotionStrength()) {
|
||||
return;
|
||||
}
|
||||
|
||||
J.s(() -> p.removePotionEffect(getRealType()));
|
||||
}
|
||||
|
||||
J.s(() -> p.addPotionEffect(new PotionEffect(getRealType(),
|
||||
RNG.r.i(Math.min(potionTicksMax, potionTicksMin),
|
||||
Math.max(potionTicksMax, potionTicksMin)),
|
||||
getPotionStrength(),
|
||||
true, false, false)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents an enchantment & level")
|
||||
@Data
|
||||
public class IrisEnchantment {
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The enchantment")
|
||||
private String enchantment = "";
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("Minimum amount of this loot")
|
||||
private int minLevel = 1;
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("Maximum amount of this loot")
|
||||
private int maxLevel = 1;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1)
|
||||
@Desc("The chance that this enchantment is applied (0 to 1)")
|
||||
private double chance = 1;
|
||||
|
||||
public void apply(RNG rng, ItemMeta meta) {
|
||||
try {
|
||||
if (rng.nextDouble() < chance) {
|
||||
if (meta instanceof EnchantmentStorageMeta) {
|
||||
((EnchantmentStorageMeta) meta).addStoredEnchant(getEnchant(), getLevel(rng), true);
|
||||
return;
|
||||
}
|
||||
meta.addEnchant(getEnchant(), getLevel(rng), true);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public Enchantment getEnchant() {
|
||||
for (Field i : Enchantment.class.getDeclaredFields()) {
|
||||
if (i.getType().equals(Enchantment.class) && i.getName().equals(getEnchantment())) {
|
||||
try {
|
||||
return (Enchantment) i.get(null);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
e.printStackTrace();Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getLevel(RNG rng) {
|
||||
return rng.i(getMinLevel(), getMaxLevel());
|
||||
}
|
||||
}
|
||||
313
src/main/java/com/volmit/iris/engine/object/IrisEntity.java
Normal file
313
src/main/java/com/volmit/iris/engine/object/IrisEntity.java
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.attribute.Attributable;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.entity.Panda.Gene;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.loot.LootContext;
|
||||
import org.bukkit.loot.LootTable;
|
||||
import org.bukkit.loot.Lootable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
|
||||
@Desc("Represents an iris entity.")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisEntity extends IrisRegistrant {
|
||||
@Required
|
||||
|
||||
@Desc("The type of entity to spawn. To spawn a mythic mob, set this type to unknown and define mythic type.")
|
||||
private EntityType type = EntityType.UNKNOWN;
|
||||
|
||||
@RegistryListMythical
|
||||
@Desc("The type of mythic mob (if mythic mobs is installed). If this is set, make sure to set 'type' to UNKNOWN")
|
||||
|
||||
private String mythicalType = "";
|
||||
|
||||
|
||||
@Desc("The custom name of this entity")
|
||||
private String customName = "";
|
||||
|
||||
|
||||
@Desc("Should the name on this entity be visible even if you arent looking at it.")
|
||||
private boolean customNameVisible = false;
|
||||
|
||||
|
||||
@Desc("If this entity type is a mob, should it be aware of it's surroundings & interact with the world.")
|
||||
private boolean aware = true;
|
||||
|
||||
|
||||
@Desc("If this entity type is a creature, should it have ai goals.")
|
||||
private boolean ai = true;
|
||||
|
||||
|
||||
@Desc("Should this entity be glowing")
|
||||
private boolean glowing = false;
|
||||
|
||||
|
||||
@Desc("Should gravity apply to this entity")
|
||||
private boolean gravity = true;
|
||||
|
||||
|
||||
@Desc("When an entity is invulnerable it can only be damaged by players increative mode.")
|
||||
private boolean invulnerable = false;
|
||||
|
||||
|
||||
@Desc("When an entity is silent it will not produce any sound.")
|
||||
private boolean silent = false;
|
||||
|
||||
|
||||
@Desc("Should this entity be allowed to pickup items")
|
||||
private boolean pickupItems = false;
|
||||
|
||||
|
||||
@Desc("Should this entity be removed when far away")
|
||||
private boolean removable = true;
|
||||
|
||||
|
||||
@Desc("Entity helmet equipment")
|
||||
private IrisLoot helmet = null;
|
||||
|
||||
|
||||
@Desc("Entity chestplate equipment")
|
||||
private IrisLoot chestplate = null;
|
||||
|
||||
|
||||
@Desc("Entity boots equipment")
|
||||
private IrisLoot boots = null;
|
||||
|
||||
|
||||
@Desc("Entity leggings equipment")
|
||||
private IrisLoot leggings = null;
|
||||
|
||||
|
||||
@Desc("Entity main hand equipment")
|
||||
private IrisLoot mainHand = null;
|
||||
|
||||
|
||||
@Desc("Entity off hand equipment")
|
||||
private IrisLoot offHand = null;
|
||||
|
||||
|
||||
@Desc("Make other entities ride this entity")
|
||||
@ArrayType(min = 1, type = IrisEntity.class)
|
||||
private KList<IrisEntity> passengers = new KList<>();
|
||||
|
||||
|
||||
@Desc("Attribute modifiers for this entity")
|
||||
@ArrayType(min = 1, type = IrisAttributeModifier.class)
|
||||
private KList<IrisAttributeModifier> attributes = new KList<>();
|
||||
|
||||
|
||||
@Desc("Loot tables for drops")
|
||||
private IrisLootReference loot = new IrisLootReference();
|
||||
|
||||
|
||||
@Desc("If specified, this entity will be leashed by this entity. I.e. THIS ENTITY Leashed by SPECIFIED. This has no effect on EnderDragons, Withers, Players, or Bats.Non-living entities excluding leashes will not persist as leashholders.")
|
||||
private IrisEntity leashHolder = null;
|
||||
|
||||
|
||||
@Desc("The main gene for a panda if the entity type is a panda")
|
||||
private Gene pandaMainGene = Gene.NORMAL;
|
||||
|
||||
|
||||
@Desc("The hidden gene for a panda if the entity type is a panda")
|
||||
private Gene pandaHiddenGene = Gene.NORMAL;
|
||||
|
||||
|
||||
@Desc("The this entity is ageable, set it's baby status")
|
||||
private boolean baby = false;
|
||||
|
||||
public Entity spawn(Engine gen, Location at) {
|
||||
return spawn(gen, at, new RNG(at.hashCode()));
|
||||
}
|
||||
|
||||
public Entity spawn(Engine gen, Location at, RNG rng) {
|
||||
Entity e = doSpawn(at);
|
||||
e.setCustomName(getCustomName() != null ? C.translateAlternateColorCodes('&', getCustomName()) : null);
|
||||
e.setCustomNameVisible(isCustomNameVisible());
|
||||
e.setGlowing(isGlowing());
|
||||
e.setGravity(isGravity());
|
||||
e.setInvulnerable(isInvulnerable());
|
||||
e.setSilent(isSilent());
|
||||
e.setPersistent(true);
|
||||
|
||||
int gg = 0;
|
||||
for (IrisEntity i : passengers) {
|
||||
e.addPassenger(i.spawn(gen, at, rng.nextParallelRNG(234858 + gg++)));
|
||||
}
|
||||
|
||||
if (e instanceof Attributable) {
|
||||
Attributable a = (Attributable) e;
|
||||
|
||||
for (IrisAttributeModifier i : getAttributes()) {
|
||||
i.apply(rng, a);
|
||||
}
|
||||
}
|
||||
|
||||
if (e instanceof Lootable) {
|
||||
Lootable l = (Lootable) e;
|
||||
|
||||
if (getLoot().getTables().isNotEmpty()) {
|
||||
l.setLootTable(new LootTable() {
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return new NamespacedKey(Iris.instance, "loot-" + IrisEntity.this.hashCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ItemStack> populateLoot(Random random, LootContext context) {
|
||||
KList<ItemStack> items = new KList<>();
|
||||
|
||||
for (String fi : getLoot().getTables()) {
|
||||
IrisLootTable i = gen.getData().getLootLoader().load(fi);
|
||||
items.addAll(i.getLoot(gen.isStudio(), false, rng.nextParallelRNG(345911), InventorySlotType.STORAGE, at.getBlockX(), at.getBlockY(), at.getBlockZ(), 8, 4));
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillInventory(Inventory inventory, Random random, LootContext context) {
|
||||
for (ItemStack i : populateLoot(random, context)) {
|
||||
inventory.addItem(i);
|
||||
}
|
||||
|
||||
gen.getCompound().getEngine(at.getBlockY()).scramble(inventory, rng);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (e instanceof LivingEntity) {
|
||||
LivingEntity l = (LivingEntity) e;
|
||||
l.setAI(isAi());
|
||||
l.setCanPickupItems(isPickupItems());
|
||||
|
||||
if (getLeashHolder() != null) {
|
||||
l.setLeashHolder(getLeashHolder().spawn(gen, at, rng.nextParallelRNG(234548)));
|
||||
}
|
||||
|
||||
l.setRemoveWhenFarAway(isRemovable());
|
||||
|
||||
if (getHelmet() != null && rng.i(1, getHelmet().getRarity()) == 1) {
|
||||
l.getEquipment().setHelmet(getHelmet().get(gen.isStudio(), rng));
|
||||
}
|
||||
|
||||
if (getChestplate() != null && rng.i(1, getChestplate().getRarity()) == 1) {
|
||||
l.getEquipment().setChestplate(getChestplate().get(gen.isStudio(), rng));
|
||||
}
|
||||
|
||||
if (getLeggings() != null && rng.i(1, getLeggings().getRarity()) == 1) {
|
||||
l.getEquipment().setLeggings(getLeggings().get(gen.isStudio(), rng));
|
||||
}
|
||||
|
||||
if (getBoots() != null && rng.i(1, getBoots().getRarity()) == 1) {
|
||||
l.getEquipment().setBoots(getBoots().get(gen.isStudio(), rng));
|
||||
}
|
||||
|
||||
if (getMainHand() != null && rng.i(1, getMainHand().getRarity()) == 1) {
|
||||
l.getEquipment().setItemInMainHand(getMainHand().get(gen.isStudio(), rng));
|
||||
}
|
||||
|
||||
if (getOffHand() != null && rng.i(1, getOffHand().getRarity()) == 1) {
|
||||
l.getEquipment().setItemInOffHand(getOffHand().get(gen.isStudio(), rng));
|
||||
}
|
||||
}
|
||||
|
||||
if (e instanceof Ageable && isBaby()) {
|
||||
((Ageable) e).setBaby();
|
||||
}
|
||||
|
||||
if (e instanceof Panda) {
|
||||
((Panda) e).setMainGene(getPandaMainGene());
|
||||
((Panda) e).setMainGene(getPandaHiddenGene());
|
||||
}
|
||||
|
||||
if (e instanceof Villager) {
|
||||
Villager villager = (Villager) e;
|
||||
villager.setRemoveWhenFarAway(false);
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, () -> {
|
||||
villager.setPersistent(true);
|
||||
villager.setCustomName(" ");
|
||||
villager.setCustomNameVisible(false);
|
||||
}, 1);
|
||||
}
|
||||
|
||||
if (Iris.awareEntities && e instanceof Mob) {
|
||||
Mob m = (Mob) e;
|
||||
m.setAware(isAware());
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
private Entity doSpawn(Location at) {
|
||||
if (!Bukkit.isPrimaryThread()) {
|
||||
// Someone called spawn (worldedit maybe?) on a non server thread
|
||||
// Due to the structure of iris, we will call it sync and busy wait until it's done.
|
||||
AtomicReference<Entity> ae = new AtomicReference<>();
|
||||
J.s(() -> ae.set(doSpawn(at)));
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
|
||||
while (ae.get() == null) {
|
||||
J.sleep(3);
|
||||
}
|
||||
|
||||
return ae.get();
|
||||
}
|
||||
|
||||
if (isMythical()) {
|
||||
return Iris.linkMythicMobs.spawn(getMythicalType(), at);
|
||||
}
|
||||
|
||||
return at.getWorld().spawnEntity(at, getType());
|
||||
}
|
||||
|
||||
public boolean isMythical() {
|
||||
return Iris.linkMythicMobs.supported() && !getMythicalType().trim().isEmpty();
|
||||
}
|
||||
|
||||
public boolean isCitizens() {
|
||||
return false;
|
||||
|
||||
// TODO: return Iris.linkCitizens.supported() && someType is not empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents an entity spawn during initial chunk generation")
|
||||
@Data
|
||||
public class IrisEntityInitialSpawn {
|
||||
@RegistryListEntity
|
||||
@Required
|
||||
|
||||
@Desc("The entity")
|
||||
private String entity = "";
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("The 1 in RARITY chance for this entity to spawn")
|
||||
private int rarity = 1;
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("The minumum of this entity to spawn")
|
||||
private int minSpawns = 1;
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("The max of this entity to spawn")
|
||||
private int maxSpawns = 1;
|
||||
|
||||
private final transient AtomicCache<RNG> rng = new AtomicCache<>();
|
||||
private final transient AtomicCache<IrisEntity> ent = new AtomicCache<>();
|
||||
|
||||
public void spawn(Engine gen, Chunk c, RNG rng) {
|
||||
int spawns = rng.i(1, rarity) == 1 ? rng.i(minSpawns, maxSpawns) : 0;
|
||||
|
||||
if (spawns > 0) {
|
||||
for (int i = 0; i < spawns; i++) {
|
||||
int x = (c.getX() * 16) + rng.i(15);
|
||||
int z = (c.getZ() * 16) + rng.i(15);
|
||||
int h = gen.getHeight(x, z) + gen.getMinHeight();
|
||||
spawn100(gen, new Location(c.getWorld(), x, h, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IrisEntity getRealEntity(Engine g) {
|
||||
return ent.aquire(() -> g.getData().getEntityLoader().load(getEntity()));
|
||||
}
|
||||
|
||||
public Entity spawn(Engine g, Location at) {
|
||||
if (getRealEntity(g) == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (rng.aquire(() -> new RNG(g.getTarget().getWorld().getSeed() + 4)).i(1, getRarity()) == 1) {
|
||||
return spawn100(g, at);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Entity spawn100(Engine g, Location at) {
|
||||
return getRealEntity(g).spawn(g, at.clone().add(0.5, 1, 0.5), rng.aquire(() -> new RNG(g.getTarget().getWorld().getSeed() + 4)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.entity.EntitySpawnEvent;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents an entity spawn")
|
||||
@Data
|
||||
public class IrisEntitySpawnOverride {
|
||||
|
||||
@RegistryListEntity
|
||||
@Required
|
||||
|
||||
@Desc("The entity")
|
||||
private String entity = "";
|
||||
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("If the following entity type spawns, spawn this entity. Set to unknown for any entity spawn")
|
||||
private EntityType trigger = EntityType.UNKNOWN;
|
||||
|
||||
|
||||
@Desc("If the source is triggered, cancel spawning the original entity instead of ADDING a new entity.")
|
||||
private boolean cancelSourceSpawn = false;
|
||||
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("The 1 in RARITY chance for this entity to spawn")
|
||||
private int rarity = 1;
|
||||
|
||||
private final transient AtomicCache<RNG> rng = new AtomicCache<>();
|
||||
private final transient AtomicCache<IrisEntity> ent = new AtomicCache<>();
|
||||
|
||||
|
||||
public Entity on(Engine g, Location at, EntityType t, EntitySpawnEvent ee) {
|
||||
if (!trigger.equals(EntityType.UNKNOWN)) {
|
||||
if (!trigger.equals(t)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Entity e = spawn(g, at);
|
||||
|
||||
if (e != null && isCancelSourceSpawn()) {
|
||||
ee.setCancelled(true);
|
||||
ee.getEntity().remove();
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
public Entity spawn(Engine g, Location at) {
|
||||
if (getRealEntity(g) == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (rng.aquire(() -> new RNG(g.getTarget().getWorld().getSeed() + 4)).i(1, getRarity()) == 1) {
|
||||
return getRealEntity(g).spawn(g, at, rng.aquire(() -> new RNG(g.getTarget().getWorld().getSeed() + 4)));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IrisEntity getRealEntity(Engine g) {
|
||||
return ent.aquire(() -> g.getData().getEntityLoader().load(getEntity()));
|
||||
}
|
||||
}
|
||||
110
src/main/java/com/volmit/iris/engine/object/IrisFeature.java
Normal file
110
src/main/java/com/volmit/iris/engine/object/IrisFeature.java
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
@Data
|
||||
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents an Iris zone")
|
||||
public class IrisFeature {
|
||||
@Required
|
||||
|
||||
@Desc("The block radius of this zone")
|
||||
private double blockRadius = 32;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1)
|
||||
@Required
|
||||
|
||||
@Desc("The chance an object that should be place actually will place. Set to below 1 to affect objects in this zone")
|
||||
private double objectChance = 1;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The interpolation radius of this zone")
|
||||
private double interpolationRadius = 7;
|
||||
|
||||
@Required
|
||||
|
||||
@MaxNumber(1)
|
||||
@MinNumber(0)
|
||||
@Desc("The strength of this effect")
|
||||
private double strength = 0.75;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The interpolator to use for smoothing the strength")
|
||||
private InterpolationMethod interpolator = InterpolationMethod.BILINEAR_STARCAST_9;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("If set, this will shift the terrain height in blocks (up or down)")
|
||||
private double shiftHeight = 0;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("If set, this will force the terrain closer to the specified height.")
|
||||
private double convergeToHeight = -1;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("Multiplies the input noise")
|
||||
private double multiplyHeight = 1;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("Invert the zone so that anything outside this zone is affected.")
|
||||
private boolean invertZone = false;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("Add additional noise to this spot")
|
||||
private IrisGeneratorStyle addNoise = NoiseStyle.FLAT.style();
|
||||
|
||||
|
||||
private transient AtomicCache<Double> actualRadius = new AtomicCache<>();
|
||||
|
||||
public double getActualRadius() {
|
||||
return actualRadius.aquire(() -> IrisInterpolation.getRealRadius(getInterpolator(), getInterpolationRadius()));
|
||||
}
|
||||
|
||||
public static IrisFeature read(DataInputStream s) throws IOException {
|
||||
return new Gson().fromJson(s.readUTF(), IrisFeature.class);
|
||||
}
|
||||
|
||||
public void write(DataOutputStream s) throws IOException {
|
||||
s.writeUTF(new Gson().toJson(this));
|
||||
}
|
||||
|
||||
public int getRealSize() {
|
||||
return (int) Math.ceil((getActualRadius() + blockRadius) * 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
@Data
|
||||
|
||||
@NoArgsConstructor
|
||||
@Desc("Represents an Iris zone")
|
||||
public class IrisFeaturePositional {
|
||||
public IrisFeaturePositional(int x, int z, IrisFeature feature) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.feature = feature;
|
||||
}
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The x coordinate of this zone")
|
||||
private int x;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The z coordinate of this zone")
|
||||
private int z;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The Terrain Feature to apply")
|
||||
private IrisFeature feature;
|
||||
|
||||
private transient AtomicCache<NoiseProvider> provider = new AtomicCache<>();
|
||||
private static double BLOCK = 1D / 256D; // TODO: WARNING HEIGHT
|
||||
|
||||
public static IrisFeaturePositional read(DataInputStream s) throws IOException {
|
||||
return new Gson().fromJson(s.readUTF(), IrisFeaturePositional.class);
|
||||
}
|
||||
|
||||
public void write(DataOutputStream s) throws IOException {
|
||||
s.writeUTF(new Gson().toJson(this));
|
||||
}
|
||||
|
||||
public boolean shouldFilter(double x, double z) {
|
||||
double actualRadius = getFeature().getActualRadius();
|
||||
double dist2 = distance2(x, z);
|
||||
|
||||
if (getFeature().isInvertZone()) {
|
||||
if (dist2 < Math.pow(getFeature().getBlockRadius() - actualRadius, 2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !(dist2 > Math.pow(getFeature().getBlockRadius() + actualRadius, 2));
|
||||
}
|
||||
|
||||
public double getStrength(double x, double z) {
|
||||
double actualRadius = getFeature().getActualRadius();
|
||||
double dist2 = distance2(x, z);
|
||||
|
||||
if (getFeature().isInvertZone()) {
|
||||
if (dist2 < Math.pow(getFeature().getBlockRadius() - actualRadius, 2)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
NoiseProvider d = provider.aquire(this::getNoiseProvider);
|
||||
double s = IrisInterpolation.getNoise(getFeature().getInterpolator(), (int) x, (int) z, getFeature().getInterpolationRadius(), d);
|
||||
|
||||
if (s <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return getFeature().getStrength() * s;
|
||||
} else {
|
||||
if (dist2 > Math.pow(getFeature().getBlockRadius() + actualRadius, 2)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
NoiseProvider d = provider.aquire(this::getNoiseProvider);
|
||||
double s = IrisInterpolation.getNoise(getFeature().getInterpolator(), (int) x, (int) z, getFeature().getInterpolationRadius(), d);
|
||||
|
||||
if (s <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return getFeature().getStrength() * s;
|
||||
}
|
||||
}
|
||||
|
||||
public double getObjectChanceModifier(double x, double z) {
|
||||
if (getFeature().getObjectChance() >= 1) {
|
||||
return getFeature().getObjectChance();
|
||||
}
|
||||
|
||||
return M.lerp(1, getFeature().getObjectChance(), getStrength(x, z));
|
||||
}
|
||||
|
||||
public double filter(double x, double z, double noise) {
|
||||
double s = getStrength(x, z);
|
||||
|
||||
if (s <= 0) {
|
||||
return noise;
|
||||
}
|
||||
|
||||
double fx = noise;
|
||||
|
||||
if (getFeature().getConvergeToHeight() >= 0) {
|
||||
fx = getFeature().getConvergeToHeight();
|
||||
}
|
||||
|
||||
fx *= getFeature().getMultiplyHeight();
|
||||
fx += getFeature().getShiftHeight();
|
||||
|
||||
return M.lerp(noise, fx, s);
|
||||
}
|
||||
|
||||
public double distance(double x, double z) {
|
||||
return Math.sqrt(Math.pow(this.x - x, 2) + Math.pow(this.z - z, 2));
|
||||
}
|
||||
|
||||
public double distance2(double x, double z) {
|
||||
return Math.pow(this.x - x, 2) + Math.pow(this.z - z, 2);
|
||||
}
|
||||
|
||||
private NoiseProvider getNoiseProvider() {
|
||||
if (getFeature().isInvertZone()) {
|
||||
return (x, z) -> distance(x, z) > getFeature().getBlockRadius() ? 1D : 0D;
|
||||
} else {
|
||||
return (x, z) -> distance(x, z) < getFeature().getBlockRadius() ? 1D : 0D;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.MinNumber;
|
||||
import com.volmit.iris.util.RNG;
|
||||
import com.volmit.iris.util.Required;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
|
||||
@Desc("Represents a potential Iris zone")
|
||||
public class IrisFeaturePotential {
|
||||
|
||||
@MinNumber(0)
|
||||
@Required
|
||||
|
||||
@Desc("The rarity is 1 in X chance per chunk")
|
||||
private int rarity = 100;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("")
|
||||
private IrisFeature zone = new IrisFeature();
|
||||
|
||||
public boolean hasZone(RNG rng, int cx, int cz) {
|
||||
return rng.nextInt(rarity) == 0;
|
||||
}
|
||||
}
|
||||
285
src/main/java/com/volmit/iris/engine/object/IrisGenerator.java
Normal file
285
src/main/java/com/volmit/iris/engine/object/IrisGenerator.java
Normal file
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.noise.CellGenerator;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings("DefaultAnnotationParam")
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents a composite generator of noise gens")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisGenerator extends IrisRegistrant {
|
||||
@MinNumber(0.001)
|
||||
@Desc("The zoom or frequency.")
|
||||
private double zoom = 1;
|
||||
|
||||
@MinNumber(0)
|
||||
@Desc("The opacity, essentially a multiplier on the output.")
|
||||
private double opacity = 1;
|
||||
|
||||
|
||||
@Desc("Multiply the compsites instead of adding them")
|
||||
private boolean multiplicitive = false;
|
||||
|
||||
@MinNumber(0.001)
|
||||
@Desc("The size of the cell fractures")
|
||||
private double cellFractureZoom = 1D;
|
||||
|
||||
@MinNumber(0)
|
||||
@Desc("Cell Fracture Coordinate Shuffling")
|
||||
private double cellFractureShuffle = 12D;
|
||||
|
||||
|
||||
@Desc("The height of fracture cells. Set to 0 to disable")
|
||||
private double cellFractureHeight = 0D;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1)
|
||||
@Desc("How big are the cells (X,Z) relative to the veins that touch them. Between 0 and 1. 0.1 means thick veins, small cells.")
|
||||
private double cellPercentSize = 0.75D;
|
||||
|
||||
|
||||
@Desc("The offset to shift this noise x")
|
||||
private double offsetX = 0;
|
||||
|
||||
|
||||
@Desc("The offset to shift this noise z")
|
||||
private double offsetZ = 0;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The seed for this generator")
|
||||
private long seed = 1;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The interpolator to use when smoothing this generator into other regions & generators")
|
||||
private IrisInterpolator interpolator = new IrisInterpolator();
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(8192)
|
||||
@Desc("Cliff Height Max. Disable with 0 for min and max")
|
||||
private double cliffHeightMax = 0;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(8192)
|
||||
@Desc("Cliff Height Min. Disable with 0 for min and max")
|
||||
private double cliffHeightMin = 0;
|
||||
|
||||
@ArrayType(min = 1, type = IrisNoiseGenerator.class)
|
||||
@Desc("The list of noise gens this gen contains.")
|
||||
private KList<IrisNoiseGenerator> composite = new KList<>();
|
||||
|
||||
|
||||
@Desc("The noise gen for cliff height.")
|
||||
private IrisNoiseGenerator cliffHeightGenerator = new IrisNoiseGenerator();
|
||||
|
||||
private final transient AtomicCache<CellGenerator> cellGen = new AtomicCache<>();
|
||||
|
||||
public double getMax() {
|
||||
return opacity;
|
||||
}
|
||||
|
||||
public boolean hasCliffs() {
|
||||
return cliffHeightMax > 0;
|
||||
}
|
||||
|
||||
public CellGenerator getCellGenerator(long seed) {
|
||||
return cellGen.aquire(() -> new CellGenerator(new RNG(seed + 239466)));
|
||||
}
|
||||
|
||||
public <T extends IRare> T fitRarity(KList<T> b, long superSeed, double rx, double rz) {
|
||||
if (b.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (b.size() == 1) {
|
||||
return b.get(0);
|
||||
}
|
||||
|
||||
KList<T> rarityMapped = new KList<>();
|
||||
boolean o = false;
|
||||
int max = 1;
|
||||
for (T i : b) {
|
||||
if (i.getRarity() > max) {
|
||||
max = i.getRarity();
|
||||
}
|
||||
}
|
||||
|
||||
max++;
|
||||
|
||||
for (T i : b) {
|
||||
for (int j = 0; j < max - i.getRarity(); j++) {
|
||||
if (o = !o) {
|
||||
rarityMapped.add(i);
|
||||
} else {
|
||||
rarityMapped.add(0, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rarityMapped.size() == 1) {
|
||||
return rarityMapped.get(0);
|
||||
}
|
||||
|
||||
if (rarityMapped.isEmpty()) {
|
||||
throw new RuntimeException("BAD RARITY MAP! RELATED TO: " + b.toString(", or possibly "));
|
||||
}
|
||||
|
||||
return fit(rarityMapped, superSeed, rx, rz);
|
||||
}
|
||||
|
||||
public <T> T fit(T[] v, long superSeed, double rx, double rz) {
|
||||
if (v.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (v.length == 1) {
|
||||
return v[0];
|
||||
}
|
||||
|
||||
return v[fit(0, v.length - 1, superSeed, rx, rz)];
|
||||
}
|
||||
|
||||
public <T> T fit(List<T> v, long superSeed, double rx, double rz) {
|
||||
if (v.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (v.size() == 1) {
|
||||
return v.get(0);
|
||||
}
|
||||
|
||||
return v.get(fit(0, v.size() - 1, superSeed, rx, rz));
|
||||
}
|
||||
|
||||
public int fit(int min, int max, long superSeed, double rx, double rz) {
|
||||
if (min == max) {
|
||||
return min;
|
||||
}
|
||||
|
||||
double noise = getHeight(rx, rz, superSeed);
|
||||
|
||||
return (int) Math.round(IrisInterpolation.lerp(min, max, noise));
|
||||
}
|
||||
|
||||
public int fit(double min, double max, long superSeed, double rx, double rz) {
|
||||
if (min == max) {
|
||||
return (int) Math.round(min);
|
||||
}
|
||||
|
||||
double noise = getHeight(rx, rz, superSeed);
|
||||
|
||||
return (int) Math.round(IrisInterpolation.lerp(min, max, noise));
|
||||
}
|
||||
|
||||
public double fitDouble(double min, double max, long superSeed, double rx, double rz) {
|
||||
if (min == max) {
|
||||
return min;
|
||||
}
|
||||
|
||||
double noise = getHeight(rx, rz, superSeed);
|
||||
|
||||
return IrisInterpolation.lerp(min, max, noise);
|
||||
}
|
||||
|
||||
public double getHeight(double rx, double rz, long superSeed) {
|
||||
return getHeight(rx, 0, rz, superSeed);
|
||||
}
|
||||
|
||||
public double getHeight(double rx, double ry, double rz, long superSeed) {
|
||||
if (composite.isEmpty()) {
|
||||
Iris.warn("Useless Generator: Composite is empty in " + getLoadKey());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hc = (int) ((cliffHeightMin * 10) + 10 + cliffHeightMax * seed + offsetX + offsetZ);
|
||||
double h = 0;
|
||||
double tp = multiplicitive ? 1 : 0;
|
||||
|
||||
for (IrisNoiseGenerator i : composite) {
|
||||
if (multiplicitive) {
|
||||
tp *= i.getOpacity();
|
||||
h *= i.getNoise(seed + superSeed + hc, (rx + offsetX) / zoom, (rz + offsetZ) / zoom);
|
||||
} else {
|
||||
tp += i.getOpacity();
|
||||
h += i.getNoise(seed + superSeed + hc, (rx + offsetX) / zoom, (rz + offsetZ) / zoom);
|
||||
}
|
||||
}
|
||||
|
||||
double v = multiplicitive ? h * opacity : (h / tp) * opacity;
|
||||
|
||||
if (Double.isNaN(v)) {
|
||||
Iris.warn("Nan value on gen: " + getLoadKey() + ": H = " + h + " TP = " + tp + " OPACITY = " + opacity + " ZOOM = " + zoom);
|
||||
}
|
||||
|
||||
v = hasCliffs() ? cliff(rx, rz, v, superSeed + 294596 + hc) : v;
|
||||
v = hasCellCracks() ? cell(rx, rz, v, superSeed + 48622 + hc) : v;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public double cell(double rx, double rz, double v, double superSeed) {
|
||||
getCellGenerator(seed + 46222).setShuffle(getCellFractureShuffle());
|
||||
return getCellGenerator(seed + 46222).getDistance(rx / getCellFractureZoom(), rz / getCellFractureZoom()) > getCellPercentSize() ? (v * getCellFractureHeight()) : v;
|
||||
}
|
||||
|
||||
private boolean hasCellCracks() {
|
||||
return getCellFractureHeight() != 0;
|
||||
}
|
||||
|
||||
public double getCliffHeight(double rx, double rz, double superSeed) {
|
||||
int hc = (int) ((cliffHeightMin * 10) + 10 + cliffHeightMax * seed + offsetX + offsetZ);
|
||||
double h = cliffHeightGenerator.getNoise((long) (seed + superSeed + hc), (rx + offsetX) / zoom, (rz + offsetZ) / zoom);
|
||||
return IrisInterpolation.lerp(cliffHeightMin, cliffHeightMax, h);
|
||||
}
|
||||
|
||||
public double cliff(double rx, double rz, double v, double superSeed) {
|
||||
double cliffHeight = getCliffHeight(rx, rz, superSeed - 34857);
|
||||
return (Math.round((v * 255D) / cliffHeight) * cliffHeight) / 255D;
|
||||
}
|
||||
|
||||
public IrisGenerator rescale(double scale) {
|
||||
zoom /= scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public KList<IrisNoiseGenerator> getAllComposites() {
|
||||
KList<IrisNoiseGenerator> g = new KList<>();
|
||||
|
||||
for (IrisNoiseGenerator i : composite) {
|
||||
g.addAll(i.getAllComposites());
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.noise.CNG;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("A gen style")
|
||||
@Data
|
||||
public class IrisGeneratorStyle {
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The chance is 1 in CHANCE per interval")
|
||||
private NoiseStyle style = NoiseStyle.IRIS;
|
||||
|
||||
|
||||
@MinNumber(0.00001)
|
||||
@Desc("The zoom of this style")
|
||||
private double zoom = 1;
|
||||
|
||||
|
||||
@MinNumber(0.00001)
|
||||
@Desc("The Output multiplier. Only used if parent is fracture.")
|
||||
private double multiplier = 1;
|
||||
|
||||
|
||||
@Desc("If set to true, each dimension will be fractured with a different order of input coordinates. This is usually 2 or 3 times slower than normal.")
|
||||
private boolean maxFractureAccuracy = false;
|
||||
|
||||
|
||||
@Desc("Apply a generator to the coordinate field fed into this parent generator. I.e. Distort your generator with another generator.")
|
||||
private IrisGeneratorStyle fracture = null;
|
||||
|
||||
|
||||
@MinNumber(0.01562)
|
||||
@MaxNumber(64)
|
||||
@Desc("The exponent")
|
||||
private double exponent = 1;
|
||||
|
||||
private final transient AtomicCache<CNG> cng = new AtomicCache<>();
|
||||
|
||||
public IrisGeneratorStyle(NoiseStyle s) {
|
||||
this.style = s;
|
||||
}
|
||||
|
||||
public IrisGeneratorStyle zoomed(double z) {
|
||||
this.zoom = z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CNG create(RNG rng) {
|
||||
return cng.aquire(() ->
|
||||
{
|
||||
CNG cng = style.create(rng).bake().scale(1D / zoom).pow(exponent).bake();
|
||||
cng.setTrueFracturing(maxFractureAccuracy);
|
||||
|
||||
if (fracture != null) {
|
||||
cng.fractureWith(fracture.create(rng.nextParallelRNG(2934)), fracture.getMultiplier());
|
||||
}
|
||||
|
||||
return cng;
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean isFlat() {
|
||||
return style.equals(NoiseStyle.FLAT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Configures rotation for iris")
|
||||
@Data
|
||||
public class IrisInterpolator {
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The interpolation method when two biomes use different heights but this same generator")
|
||||
private InterpolationMethod function = InterpolationMethod.BICUBIC;
|
||||
|
||||
@Required
|
||||
@MinNumber(1)
|
||||
@MaxNumber(8192)
|
||||
@Desc("The range checked horizontally. Smaller ranges yeild more detail but are not as smooth.")
|
||||
private double horizontalScale = 3;
|
||||
|
||||
public double interpolate(double x, double z, NoiseProvider provider) {
|
||||
return interpolate((int) Math.round(x), (int) Math.round(z), provider);
|
||||
}
|
||||
|
||||
public double interpolate(int x, int z, NoiseProvider provider) {
|
||||
return IrisInterpolation.getNoise(getFunction(), x, z, getHorizontalScale(), provider);
|
||||
}
|
||||
}
|
||||
122
src/main/java/com/volmit/iris/engine/object/IrisJigsawPiece.java
Normal file
122
src/main/java/com/volmit/iris/engine/object/IrisJigsawPiece.java
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.util.BlockVector;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@SuppressWarnings("DefaultAnnotationParam")
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
|
||||
@Desc("Represents a structure tile")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisJigsawPiece extends IrisRegistrant {
|
||||
@RegistryListObject
|
||||
@Required
|
||||
|
||||
@Desc("The object this piece represents")
|
||||
private String object = "";
|
||||
|
||||
@Required
|
||||
|
||||
@ArrayType(type = IrisJigsawPieceConnector.class, min = 1)
|
||||
@Desc("The connectors this object contains")
|
||||
private KList<IrisJigsawPieceConnector> connectors = new KList<>();
|
||||
|
||||
@Desc("Configure everything about the object placement. Please don't define this unless you actually need it as using this option will slow down the jigsaw deign stage. Use this where you need it, just avoid using it everywhere to keep things fast.")
|
||||
|
||||
private IrisObjectPlacement placementOptions = new IrisObjectPlacement().setMode(ObjectPlaceMode.FAST_MAX_HEIGHT);
|
||||
|
||||
private transient AtomicCache<Integer> max2dDim = new AtomicCache<>();
|
||||
private transient AtomicCache<Integer> max3dDim = new AtomicCache<>();
|
||||
|
||||
public int getMax2dDimension() {
|
||||
return max2dDim.aquire(() -> {
|
||||
try {
|
||||
BlockVector v = IrisObject.sampleSize(getLoader().getObjectLoader().findFile(getObject()));
|
||||
return Math.max(v.getBlockX(), v.getBlockZ());
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
public int getMax3dDimension() {
|
||||
return max3dDim.aquire(() -> {
|
||||
try {
|
||||
BlockVector v = IrisObject.sampleSize(getLoader().getObjectLoader().findFile(getObject()));
|
||||
return Math.max(Math.max(v.getBlockX(), v.getBlockZ()), v.getBlockY());
|
||||
} catch (IOException e) {Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return -1;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public IrisJigsawPieceConnector getConnector(IrisPosition relativePosition) {
|
||||
for (IrisJigsawPieceConnector i : connectors) {
|
||||
if (i.getPosition().equals(relativePosition)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IrisJigsawPiece copy() {
|
||||
IrisJigsawPiece p = new IrisJigsawPiece();
|
||||
p.setObject(getObject());
|
||||
p.setLoader(getLoader());
|
||||
p.setLoadKey(getLoadKey());
|
||||
p.setLoadFile(getLoadFile());
|
||||
p.setConnectors(new KList<>());
|
||||
p.setPlacementOptions(getPlacementOptions());
|
||||
|
||||
for (IrisJigsawPieceConnector i : getConnectors()) {
|
||||
p.getConnectors().add(i.copy());
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
public boolean isTerminal() {
|
||||
return connectors.size() == 1;
|
||||
}
|
||||
|
||||
public ObjectPlaceMode getPlaceMode() {
|
||||
return getPlacementOptions().getMode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@SuppressWarnings("DefaultAnnotationParam")
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
|
||||
@Desc("Represents a structure tile")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisJigsawPieceConnector {
|
||||
@Required
|
||||
|
||||
@Desc("The name of this connector, such as entry, or table node. This is a name for organization. Other connectors can specifically use targetName to target a specific connector type. Multiple connectors can use the same name.")
|
||||
private String name = "";
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("Target a piece's connector with the specified name. For any piece's connector, define * or don't define it.")
|
||||
private String targetName = "*";
|
||||
|
||||
|
||||
@Desc("Rotates the placed piece on this connector. If rotation is enabled, this connector will effectivley rotate, if this connector is facing the Z direction, then the connected piece would rotate in the X,Y direction in 90 degree segments.")
|
||||
private boolean rotateConnector = false;
|
||||
|
||||
|
||||
@Desc("If set to true, this connector is allowed to place pieces inside of it's own piece. For example if you are adding a light post, or house on top of a path piece, you would set this to true to allow the piece to collide with the path bounding box.")
|
||||
private boolean innerConnector = false;
|
||||
|
||||
@RegistryListJigsawPool
|
||||
@Desc("Pick piece pools to place onto this connector")
|
||||
@ArrayType(type = String.class, min = 1)
|
||||
@Required
|
||||
private KList<String> pools = new KList<>();
|
||||
|
||||
@RegistryListEntity
|
||||
|
||||
@Desc("Pick an entity to spawn on this connector")
|
||||
private String spawnEntity;
|
||||
|
||||
|
||||
@Desc("Stop the entity from despawning")
|
||||
private boolean keepEntity;
|
||||
|
||||
|
||||
@MaxNumber(50)
|
||||
@MinNumber(1)
|
||||
@Desc("The amount of entities to spawn (must be a whole number)")
|
||||
private int entityCount = 1;
|
||||
|
||||
|
||||
@Desc("The relative position this connector is located at for connecting to other pieces")
|
||||
@Required
|
||||
private IrisPosition position = new IrisPosition(0, 0, 0);
|
||||
|
||||
|
||||
@Desc("The relative position to this connector to place entities at")
|
||||
@DependsOn({"spawnEntity"})
|
||||
private IrisPosition entityPosition = null;
|
||||
|
||||
|
||||
@Desc("The direction this connector is facing. If the direction is set to UP, then pieces will place ABOVE the connector.")
|
||||
@Required
|
||||
private IrisDirection direction = IrisDirection.UP_POSITIVE_Y;
|
||||
|
||||
public String toString() {
|
||||
return direction.getFace().name() + "@(" + position.getX() + "," + position.getY() + "," + position.getZ() + ")";
|
||||
}
|
||||
|
||||
public IrisJigsawPieceConnector copy() {
|
||||
IrisJigsawPieceConnector c = new IrisJigsawPieceConnector();
|
||||
c.setInnerConnector(isInnerConnector());
|
||||
c.setTargetName(getTargetName());
|
||||
c.setPosition(getPosition().copy());
|
||||
c.setDirection(getDirection());
|
||||
c.setRotateConnector(isRotateConnector());
|
||||
c.setName(getName());
|
||||
c.setSpawnEntity(getSpawnEntity());
|
||||
c.setPools(getPools().copy());
|
||||
return c;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.MinNumber;
|
||||
import com.volmit.iris.util.RegistryListJigsaw;
|
||||
import com.volmit.iris.util.Required;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents a jigsaw placement")
|
||||
@Data
|
||||
public class IrisJigsawPlacement {
|
||||
@RegistryListJigsaw
|
||||
@Required
|
||||
|
||||
@Desc("The jigsaw structure to use")
|
||||
private String structure = "";
|
||||
|
||||
@Required
|
||||
@MinNumber(1)
|
||||
@Desc("The rarity for this jigsaw structure to place on a per chunk basis")
|
||||
private int rarity = 29;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@SuppressWarnings("DefaultAnnotationParam")
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
|
||||
@Desc("Represents a structure piece pool")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisJigsawPool extends IrisRegistrant {
|
||||
@RegistryListJigsawPiece
|
||||
@Required
|
||||
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
@Desc("A list of structure piece pools")
|
||||
private KList<String> pieces = new KList<>();
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@SuppressWarnings("DefaultAnnotationParam")
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
|
||||
@Desc("Represents a jigsaw structure")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisJigsawStructure extends IrisRegistrant {
|
||||
@RegistryListJigsawPiece
|
||||
@Required
|
||||
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
@Desc("The starting pieces. Randomly chooses a starting piece, then connects pieces using the pools define in the starting piece.")
|
||||
private KList<String> pieces = new KList<>();
|
||||
|
||||
@MaxNumber(32)
|
||||
@MinNumber(1)
|
||||
@Desc("The maximum pieces that can step out from the center piece")
|
||||
private int maxDepth = 9;
|
||||
|
||||
|
||||
@Desc("Jigsaw grows the parallax layer which slows iris down a bit. Since there are so many pieces, Iris takes the avg piece size and calculates the parallax radius from that. Unless your structures are using only the biggest pieces, your structure should fit in the chosen size fine. If you are seeing cut-off parts of your structures or broken terrain, turn this option on. This option will pick the biggest piece dimensions and multiply it by your (maxDepth+1) * 2 as the size to grow the parallax layer by. But typically keep this off.")
|
||||
private boolean useMaxPieceSizeForParallaxRadius = false;
|
||||
|
||||
@Desc("Add a noise feature to this village")
|
||||
|
||||
private IrisFeature feature = null;
|
||||
|
||||
|
||||
@Desc("If set to true, iris will look for any pieces with only one connector in valid pools for edge connectors and attach them to 'terminate' the paths/piece connectors. Essentially it caps off ends. For example in a village, Iris would add houses to the ends of roads where possible. For terminators to be selected, they can only have one connector or they wont be chosen.")
|
||||
private boolean terminate = true;
|
||||
|
||||
private transient AtomicCache<Integer> maxDimension = new AtomicCache<>();
|
||||
|
||||
private void loadPool(String p, KList<String> pools, KList<String> pieces) {
|
||||
if (p.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
IrisJigsawPool pool = getLoader().getJigsawPoolLoader().load(p);
|
||||
|
||||
if (pool == null) {
|
||||
Iris.warn("Can't find jigsaw pool: " + p);
|
||||
return;
|
||||
}
|
||||
|
||||
for (String i : pool.getPieces()) {
|
||||
if (pieces.addIfMissing(i)) {
|
||||
loadPiece(i, pools, pieces);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadPiece(String p, KList<String> pools, KList<String> pieces) {
|
||||
IrisJigsawPiece piece = getLoader().getJigsawPieceLoader().load(p);
|
||||
|
||||
if (piece == null) {
|
||||
Iris.warn("Can't find jigsaw piece: " + p);
|
||||
return;
|
||||
}
|
||||
|
||||
for (IrisJigsawPieceConnector i : piece.getConnectors()) {
|
||||
for (String j : i.getPools()) {
|
||||
if (pools.addIfMissing(j)) {
|
||||
loadPool(j, pools, pieces);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxDimension() {
|
||||
return maxDimension.aquire(() -> {
|
||||
if (useMaxPieceSizeForParallaxRadius) {
|
||||
int max = 0;
|
||||
KList<String> pools = new KList<>();
|
||||
KList<String> pieces = new KList<>();
|
||||
|
||||
for (String i : getPieces()) {
|
||||
loadPiece(i, pools, pieces);
|
||||
}
|
||||
|
||||
for (String i : pieces) {
|
||||
max = Math.max(max, getLoader().getJigsawPieceLoader().load(i).getMax3dDimension());
|
||||
}
|
||||
|
||||
return max * (((getMaxDepth() + 1) * 2) + 1);
|
||||
} else {
|
||||
KList<String> pools = new KList<>();
|
||||
KList<String> pieces = new KList<>();
|
||||
|
||||
for (String i : getPieces()) {
|
||||
loadPiece(i, pools, pieces);
|
||||
}
|
||||
|
||||
int avg = 0;
|
||||
|
||||
for (String i : pieces) {
|
||||
avg += getLoader().getJigsawPieceLoader().load(i).getMax2dDimension();
|
||||
}
|
||||
|
||||
return (avg / (pieces.size() > 0 ? pieces.size() : 1)) * (((getMaxDepth() + 1) * 2) + 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.RegistryListJigsaw;
|
||||
import com.volmit.iris.util.Required;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@SuppressWarnings("DefaultAnnotationParam")
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
|
||||
@Desc("Represents a jigsaw structure placer")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisJigsawStructurePlacement extends IrisRegistrant {
|
||||
@RegistryListJigsaw
|
||||
@Required
|
||||
|
||||
@Desc("The structure to place")
|
||||
private String structure;
|
||||
|
||||
|
||||
@Required
|
||||
@Desc("The 1 in X chance rarity")
|
||||
private int rarity = 100;
|
||||
}
|
||||
269
src/main/java/com/volmit/iris/engine/object/IrisLoot.java
Normal file
269
src/main/java/com/volmit/iris/engine/object/IrisLoot.java
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.noise.CNG;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.Damageable;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
import org.bukkit.material.Colorable;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents a loot entry")
|
||||
@Data
|
||||
public class IrisLoot {
|
||||
|
||||
@Desc("The target inventory slot types to fill this loot with")
|
||||
private InventorySlotType slotTypes = InventorySlotType.STORAGE;
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("The sub rarity of this loot. Calculated after this loot table has been picked.")
|
||||
private int rarity = 1;
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("Minimum amount of this loot")
|
||||
private int minAmount = 1;
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("Maximum amount of this loot")
|
||||
private int maxAmount = 1;
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("The display name of this item")
|
||||
private String displayName = null;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1)
|
||||
@Desc("Minimum durability percent")
|
||||
private double minDurability = 0;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1)
|
||||
@Desc("Maximum durability percent")
|
||||
private double maxDurability = 1;
|
||||
|
||||
|
||||
@Desc("Define a custom model identifier 1.14+ only")
|
||||
private Integer customModel = null;
|
||||
|
||||
|
||||
@Desc("Set this to true to prevent it from being broken")
|
||||
private boolean unbreakable = false;
|
||||
|
||||
@ArrayType(min = 1, type = ItemFlag.class)
|
||||
@Desc("The item flags to add")
|
||||
private KList<ItemFlag> itemFlags = new KList<>();
|
||||
|
||||
|
||||
@Desc("Apply enchantments to this item")
|
||||
@ArrayType(min = 1, type = IrisEnchantment.class)
|
||||
private KList<IrisEnchantment> enchantments = new KList<>();
|
||||
|
||||
|
||||
@Desc("Apply attribute modifiers to this item")
|
||||
@ArrayType(min = 1, type = IrisAttributeModifier.class)
|
||||
private KList<IrisAttributeModifier> attributes = new KList<>();
|
||||
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
@Desc("Add lore to this item")
|
||||
private KList<String> lore = new KList<>();
|
||||
|
||||
@RegistryListItemType
|
||||
@Required
|
||||
|
||||
@Desc("This is the item or block type. Does not accept minecraft:*. Only materials such as DIAMOND_SWORD or DIRT.")
|
||||
private String type = "";
|
||||
|
||||
|
||||
@Desc("The dye color")
|
||||
private DyeColor dyeColor = null;
|
||||
|
||||
|
||||
@Desc("The leather armor color")
|
||||
private String leatherColor = null;
|
||||
|
||||
private final transient AtomicCache<CNG> chance = new AtomicCache<>();
|
||||
|
||||
public Material getType() {
|
||||
return B.getMaterial(type);
|
||||
}
|
||||
|
||||
public ItemStack get(boolean debug, RNG rng) {
|
||||
try {
|
||||
ItemStack is = new ItemStack(getType(), Math.max(1, rng.i(getMinAmount(), getMaxAmount())));
|
||||
ItemMeta m = is.getItemMeta();
|
||||
|
||||
if (getType().getMaxDurability() > 0 && m instanceof Damageable d) {
|
||||
int max = getType().getMaxDurability();
|
||||
d.setDamage((int) Math.round(Math.max(0, Math.min(max, (1D - rng.d(getMinDurability(), getMaxDurability())) * max))));
|
||||
}
|
||||
|
||||
for (IrisEnchantment i : getEnchantments()) {
|
||||
i.apply(rng, m);
|
||||
}
|
||||
|
||||
for (IrisAttributeModifier i : getAttributes()) {
|
||||
i.apply(rng, m);
|
||||
}
|
||||
|
||||
if (Iris.customModels) {
|
||||
m.setCustomModelData(getCustomModel());
|
||||
}
|
||||
|
||||
m.setLocalizedName(C.translateAlternateColorCodes('&', displayName));
|
||||
m.setDisplayName(C.translateAlternateColorCodes('&', displayName));
|
||||
m.setUnbreakable(isUnbreakable());
|
||||
|
||||
for (ItemFlag i : getItemFlags()) {
|
||||
m.addItemFlags(i);
|
||||
}
|
||||
|
||||
KList<String> lore = new KList<>();
|
||||
|
||||
getLore().forEach((i) ->
|
||||
{
|
||||
String mf = C.translateAlternateColorCodes('&', i);
|
||||
|
||||
if (mf.length() > 24) {
|
||||
for (String g : Form.wrapWords(mf, 24).split("\\Q\n\\E")) {
|
||||
lore.add(g.trim());
|
||||
}
|
||||
} else {
|
||||
lore.add(mf);
|
||||
}
|
||||
});
|
||||
|
||||
if (debug) {
|
||||
if (lore.isNotEmpty()) {
|
||||
lore.add(C.GRAY + "--------------------");
|
||||
}
|
||||
|
||||
lore.add(C.GRAY + "1 in " + (getRarity()) + " Chance (" + Form.pc(1D / (getRarity()), 5) + ")");
|
||||
}
|
||||
|
||||
m.setLore(lore);
|
||||
|
||||
if (getLeatherColor() != null && m instanceof LeatherArmorMeta) {
|
||||
Color c = Color.decode(getLeatherColor());
|
||||
((LeatherArmorMeta) m).setColor(org.bukkit.Color.fromRGB(c.getRed(), c.getGreen(), c.getBlue()));
|
||||
}
|
||||
|
||||
if (getDyeColor() != null && m instanceof Colorable) {
|
||||
((Colorable) m).setColor(getDyeColor());
|
||||
}
|
||||
|
||||
is.setItemMeta(m);
|
||||
return is;
|
||||
} catch (Throwable e) {Iris.reportError(e);
|
||||
|
||||
}
|
||||
|
||||
return new ItemStack(Material.AIR);
|
||||
}
|
||||
|
||||
public ItemStack get(boolean debug, boolean giveSomething, IrisLootTable table, RNG rng, int x, int y, int z) {
|
||||
if (debug) {
|
||||
chance.reset();
|
||||
}
|
||||
|
||||
if (giveSomething || chance.aquire(() -> NoiseStyle.STATIC.create(rng)).fit(1, rarity * table.getRarity(), x, y, z) == 1) {
|
||||
if (getType() == null) {
|
||||
Iris.warn("Cant find item type " + type);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
ItemStack is = new ItemStack(getType(), Math.max(1, rng.i(getMinAmount(), getMaxAmount())));
|
||||
ItemMeta m = is.getItemMeta();
|
||||
|
||||
if (getType().getMaxDurability() > 0 && m instanceof Damageable d) {
|
||||
int max = getType().getMaxDurability();
|
||||
d.setDamage((int) Math.round(Math.max(0, Math.min(max, (1D - rng.d(getMinDurability(), getMaxDurability())) * max))));
|
||||
}
|
||||
|
||||
for (IrisEnchantment i : getEnchantments()) {
|
||||
i.apply(rng, m);
|
||||
}
|
||||
|
||||
for (IrisAttributeModifier i : getAttributes()) {
|
||||
i.apply(rng, m);
|
||||
}
|
||||
|
||||
if (Iris.customModels) {
|
||||
m.setCustomModelData(getCustomModel());
|
||||
}
|
||||
|
||||
m.setLocalizedName(C.translateAlternateColorCodes('&', displayName));
|
||||
m.setDisplayName(C.translateAlternateColorCodes('&', displayName));
|
||||
m.setUnbreakable(isUnbreakable());
|
||||
|
||||
for (ItemFlag i : getItemFlags()) {
|
||||
m.addItemFlags(i);
|
||||
}
|
||||
|
||||
KList<String> lore = new KList<>();
|
||||
|
||||
getLore().forEach((i) ->
|
||||
{
|
||||
String mf = C.translateAlternateColorCodes('&', i);
|
||||
|
||||
if (mf.length() > 24) {
|
||||
for (String g : Form.wrapWords(mf, 24).split("\\Q\n\\E")) {
|
||||
lore.add(g.trim());
|
||||
}
|
||||
} else {
|
||||
lore.add(mf);
|
||||
}
|
||||
});
|
||||
|
||||
if (debug) {
|
||||
if (lore.isNotEmpty()) {
|
||||
lore.add(C.GRAY + "--------------------");
|
||||
}
|
||||
|
||||
lore.add(C.GRAY + "From: " + table.getName() + " (" + Form.pc(1D / table.getRarity(), 5) + ")");
|
||||
lore.add(C.GRAY + "1 in " + (table.getRarity() * getRarity()) + " Chance (" + Form.pc(1D / (table.getRarity() * getRarity()), 5) + ")");
|
||||
}
|
||||
|
||||
m.setLore(lore);
|
||||
is.setItemMeta(m);
|
||||
return is;
|
||||
} catch (Throwable e) {Iris.reportError(e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.data.DataProvider;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents a loot entry")
|
||||
@Data
|
||||
public class IrisLootReference {
|
||||
|
||||
|
||||
@Desc("Add = add on top of parent tables, Replace = clear first then add these. Clear = Remove all and dont add loot from this or parent.")
|
||||
private LootMode mode = LootMode.ADD;
|
||||
|
||||
|
||||
@RegistryListLoot
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
@Desc("Add loot table registries here")
|
||||
private KList<String> tables = new KList<>();
|
||||
|
||||
@MinNumber(0)
|
||||
@Desc("Increase the chance of loot in this area")
|
||||
private double multiplier = 1D;
|
||||
|
||||
private final transient AtomicCache<KList<IrisLootTable>> tt = new AtomicCache<>();
|
||||
|
||||
public KList<IrisLootTable> getLootTables(DataProvider g) {
|
||||
return tt.aquire(() ->
|
||||
{
|
||||
KList<IrisLootTable> t = new KList<>();
|
||||
|
||||
for (String i : tables) {
|
||||
t.add(g.getData().getLootLoader().load(i));
|
||||
}
|
||||
|
||||
return t;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@SuppressWarnings("DefaultAnnotationParam")
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents a loot table. Biomes, Regions & Objects can add or replace the virtual table with these loot tables")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisLootTable extends IrisRegistrant {
|
||||
@Required
|
||||
|
||||
@Desc("The name of this loot table")
|
||||
|
||||
@MinNumber(2)
|
||||
private String name = "";
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("The rarity as in 1 in X chance")
|
||||
private int rarity = 1;
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("The maximum amount of loot that can be picked in this table at a time.")
|
||||
private int maxPicked = 5;
|
||||
|
||||
@MinNumber(0)
|
||||
@Desc("The minimum amount of loot that can be picked in this table at a time.")
|
||||
private int minPicked = 1;
|
||||
|
||||
|
||||
@Desc("The loot in this table")
|
||||
@ArrayType(min = 1, type = IrisLoot.class)
|
||||
private KList<IrisLoot> loot = new KList<>();
|
||||
|
||||
public KList<ItemStack> getLoot(boolean debug, boolean doSomething, RNG rng, InventorySlotType slot, int x, int y, int z, int gg, int ffs) {
|
||||
KList<ItemStack> lootf = new KList<>();
|
||||
|
||||
int m = 0;
|
||||
int mx = rng.i(getMinPicked(), getMaxPicked());
|
||||
|
||||
while (m < mx) {
|
||||
int num = rng.i(loot.size());
|
||||
|
||||
IrisLoot l = loot.get(num);
|
||||
|
||||
if (l.getSlotTypes() == slot) {
|
||||
ItemStack item = l.get(debug, false, this, rng, x, y, z);
|
||||
|
||||
if (item != null && item.getType() != Material.AIR) {
|
||||
lootf.add(item);
|
||||
m++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lootf;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.noise.CNG;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("A palette of materials")
|
||||
@Data
|
||||
public class IrisMaterialPalette {
|
||||
|
||||
@Desc("The style of noise")
|
||||
private IrisGeneratorStyle style = NoiseStyle.STATIC.style();
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@Desc("The terrain zoom mostly for zooming in on a wispy palette")
|
||||
private double zoom = 5;
|
||||
|
||||
@Required
|
||||
@ArrayType(min = 1, type = IrisBlockData.class)
|
||||
@Desc("The palette of blocks to be used in this layer")
|
||||
private KList<IrisBlockData> palette = new KList<IrisBlockData>().qadd(new IrisBlockData("STONE"));
|
||||
|
||||
private final transient AtomicCache<KList<BlockData>> blockData = new AtomicCache<>();
|
||||
private final transient AtomicCache<CNG> layerGenerator = new AtomicCache<>();
|
||||
private final transient AtomicCache<CNG> heightGenerator = new AtomicCache<>();
|
||||
|
||||
public BlockData get(RNG rng, double x, double y, double z, IrisDataManager rdata) {
|
||||
if (getBlockData(rdata).isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (getBlockData(rdata).size() == 1) {
|
||||
return getBlockData(rdata).get(0);
|
||||
}
|
||||
|
||||
return getLayerGenerator(rng, rdata).fit(getBlockData(rdata), x / zoom, y / zoom, z / zoom);
|
||||
}
|
||||
|
||||
public CNG getLayerGenerator(RNG rng, IrisDataManager rdata) {
|
||||
return layerGenerator.aquire(() ->
|
||||
{
|
||||
RNG rngx = rng.nextParallelRNG(-23498896 + getBlockData(rdata).size());
|
||||
return style.create(rngx);
|
||||
});
|
||||
}
|
||||
|
||||
public IrisMaterialPalette qclear() {
|
||||
palette.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
public KList<IrisBlockData> add(String b) {
|
||||
palette.add(new IrisBlockData(b));
|
||||
|
||||
return palette;
|
||||
}
|
||||
|
||||
public IrisMaterialPalette qadd(String b) {
|
||||
palette.add(new IrisBlockData(b));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public KList<BlockData> getBlockData(IrisDataManager rdata) {
|
||||
return blockData.aquire(() ->
|
||||
{
|
||||
KList<BlockData> blockData = new KList<>();
|
||||
for (IrisBlockData ix : palette) {
|
||||
BlockData bx = ix.getBlockData(rdata);
|
||||
if (bx != null) {
|
||||
for (int i = 0; i < ix.getWeight(); i++) {
|
||||
blockData.add(bx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blockData;
|
||||
});
|
||||
}
|
||||
|
||||
public IrisMaterialPalette zero() {
|
||||
palette.clear();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.noise.CNG;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("A noise generator")
|
||||
@Data
|
||||
public class IrisNoiseGenerator {
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@Desc("The coordinate input zoom")
|
||||
private double zoom = 1;
|
||||
|
||||
|
||||
@Desc("Reverse the output. So that noise = -noise + opacity")
|
||||
private boolean negative = false;
|
||||
|
||||
@MinNumber(0)
|
||||
@Desc("The output multiplier")
|
||||
private double opacity = 1;
|
||||
|
||||
|
||||
@Desc("Coordinate offset x")
|
||||
private double offsetX = 0;
|
||||
|
||||
|
||||
@Desc("Height output offset y")
|
||||
private double offsetY = 0;
|
||||
|
||||
|
||||
@Desc("Coordinate offset z")
|
||||
private double offsetZ = 0;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The seed")
|
||||
private long seed = 0;
|
||||
|
||||
|
||||
@Desc("Apply a parametric curve on the output")
|
||||
private boolean parametric = false;
|
||||
|
||||
|
||||
@Desc("Apply a bezier curve on the output")
|
||||
private boolean bezier = false;
|
||||
|
||||
|
||||
@Desc("Apply a sin-center curve on the output (0, and 1 = 0 and 0.5 = 1.0 using a sinoid shape.)")
|
||||
private boolean sinCentered = false;
|
||||
|
||||
|
||||
@Desc("The exponent noise^EXPONENT")
|
||||
private double exponent = 1;
|
||||
|
||||
|
||||
@Desc("Enable / disable. Outputs offsetY if disabled")
|
||||
private boolean enabled = true;
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The Noise Style")
|
||||
private IrisGeneratorStyle style = NoiseStyle.IRIS.style();
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("Multiple octaves for multple generators of changing zooms added together")
|
||||
private int octaves = 1;
|
||||
|
||||
@ArrayType(min = 1, type = IrisNoiseGenerator.class)
|
||||
@Desc("Apply a child noise generator to fracture the input coordinates of this generator")
|
||||
private KList<IrisNoiseGenerator> fracture = new KList<>();
|
||||
|
||||
private final transient AtomicCache<CNG> generator = new AtomicCache<>();
|
||||
|
||||
public IrisNoiseGenerator(boolean enabled) {
|
||||
this();
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
protected CNG getGenerator(long superSeed) {
|
||||
return generator.aquire(() -> style.create(new RNG(superSeed + 33955677 - seed)).oct(octaves));
|
||||
}
|
||||
|
||||
public double getMax() {
|
||||
return getOffsetY() + opacity;
|
||||
}
|
||||
|
||||
public double getNoise(long superSeed, double xv, double zv) {
|
||||
if (!enabled) {
|
||||
return offsetY;
|
||||
}
|
||||
|
||||
double x = xv;
|
||||
double z = zv;
|
||||
int g = 33;
|
||||
|
||||
for (IrisNoiseGenerator i : fracture) {
|
||||
if (i.isEnabled()) {
|
||||
x += i.getNoise(superSeed + seed + g, xv, zv) - (opacity / 2D);
|
||||
z -= i.getNoise(superSeed + seed + g, zv, xv) - (opacity / 2D);
|
||||
}
|
||||
g += 819;
|
||||
}
|
||||
|
||||
double n = getGenerator(superSeed).fitDouble(0, opacity, (x / zoom) + offsetX, (z / zoom) + offsetZ);
|
||||
n = negative ? (-n + opacity) : n;
|
||||
n = (exponent != 1 ? n < 0 ? -Math.pow(-n, exponent) : Math.pow(n, exponent) : n) + offsetY;
|
||||
n = parametric ? IrisInterpolation.parametric(n, 1) : n;
|
||||
n = bezier ? IrisInterpolation.bezier(n) : n;
|
||||
n = sinCentered ? IrisInterpolation.sinCenter(n) : n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
public KList<IrisNoiseGenerator> getAllComposites() {
|
||||
KList<IrisNoiseGenerator> g = new KList<>();
|
||||
|
||||
g.add(this);
|
||||
|
||||
for (IrisNoiseGenerator i : getFracture()) {
|
||||
g.addAll(i.getAllComposites());
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
}
|
||||
981
src/main/java/com/volmit/iris/engine/object/IrisObject.java
Normal file
981
src/main/java/com/volmit/iris/engine/object/IrisObject.java
Normal file
@@ -0,0 +1,981 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.engine.object.tile.TileData;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.TileState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Waterlogged;
|
||||
import org.bukkit.block.data.type.Leaves;
|
||||
import org.bukkit.util.BlockVector;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@SuppressWarnings("DefaultAnnotationParam")
|
||||
@Accessors(chain = true)
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisObject extends IrisRegistrant {
|
||||
private static final Vector HALF = new Vector(0.5, 0.5, 0.5);
|
||||
private static final BlockData AIR = B.get("CAVE_AIR");
|
||||
private static final BlockData VAIR = B.get("VOID_AIR");
|
||||
private static final BlockData VAIR_DEBUG = B.get("COBWEB");
|
||||
private static final BlockData[] SNOW_LAYERS = new BlockData[]{B.get("minecraft:snow[layers=1]"), B.get("minecraft:snow[layers=2]"), B.get("minecraft:snow[layers=3]"), B.get("minecraft:snow[layers=4]"), B.get("minecraft:snow[layers=5]"), B.get("minecraft:snow[layers=6]"), B.get("minecraft:snow[layers=7]"), B.get("minecraft:snow[layers=8]")};
|
||||
public static boolean shitty = false;
|
||||
private KMap<BlockVector, BlockData> blocks;
|
||||
private KMap<BlockVector, TileData<? extends TileState>> states;
|
||||
private int w;
|
||||
private int d;
|
||||
private int h;
|
||||
private transient final IrisLock readLock = new IrisLock("read-conclock");
|
||||
private transient BlockVector center;
|
||||
private transient volatile boolean smartBored = false;
|
||||
private transient IrisLock lock = new IrisLock("Preloadcache");
|
||||
private transient AtomicCache<AxisAlignedBB> aabb;
|
||||
|
||||
public AxisAlignedBB getAABB() {
|
||||
return getAABBFor(new BlockVector(w, h, d));
|
||||
}
|
||||
|
||||
public static BlockVector getCenterForSize(BlockVector size) {
|
||||
return new BlockVector(size.getX() / 2, size.getY() / 2, size.getZ() / 2);
|
||||
}
|
||||
|
||||
public static AxisAlignedBB getAABBFor(BlockVector size) {
|
||||
BlockVector center = new BlockVector(size.getX() / 2, size.getY() / 2, size.getZ() / 2);
|
||||
return new AxisAlignedBB(new IrisPosition(new BlockVector(0, 0, 0).subtract(center).toBlockVector()),
|
||||
new IrisPosition(new BlockVector(size.getX() - 1, size.getY() - 1, size.getZ() - 1).subtract(center).toBlockVector()));
|
||||
}
|
||||
|
||||
public void ensureSmartBored(boolean debug) {
|
||||
if (smartBored) {
|
||||
return;
|
||||
}
|
||||
|
||||
lock.lock();
|
||||
int applied = 0;
|
||||
if (getBlocks().isEmpty()) {
|
||||
lock.unlock();
|
||||
Iris.warn("Cannot Smart Bore " + getLoadKey() + " because it has 0 blocks in it.");
|
||||
smartBored = true;
|
||||
return;
|
||||
}
|
||||
|
||||
BlockVector max = new BlockVector(Double.MIN_VALUE, Double.MIN_VALUE, Double.MIN_VALUE);
|
||||
BlockVector min = new BlockVector(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE);
|
||||
|
||||
for (BlockVector i : getBlocks().keySet()) {
|
||||
max.setX(Math.max(i.getX(), max.getX()));
|
||||
min.setX(Math.min(i.getX(), min.getX()));
|
||||
max.setY(Math.max(i.getY(), max.getY()));
|
||||
min.setY(Math.min(i.getY(), min.getY()));
|
||||
max.setZ(Math.max(i.getZ(), max.getZ()));
|
||||
min.setZ(Math.min(i.getZ(), min.getZ()));
|
||||
}
|
||||
|
||||
// Smash X
|
||||
for (int rayY = min.getBlockY(); rayY <= max.getBlockY(); rayY++) {
|
||||
for (int rayZ = min.getBlockZ(); rayZ <= max.getBlockZ(); rayZ++) {
|
||||
int start = Integer.MAX_VALUE;
|
||||
int end = Integer.MIN_VALUE;
|
||||
|
||||
for (int ray = min.getBlockX(); ray <= max.getBlockX(); ray++) {
|
||||
if (getBlocks().containsKey(new BlockVector(ray, rayY, rayZ))) {
|
||||
start = Math.min(ray, start);
|
||||
end = Math.max(ray, end);
|
||||
}
|
||||
}
|
||||
|
||||
if (start != Integer.MAX_VALUE && end != Integer.MIN_VALUE) {
|
||||
for (int i = start; i <= end; i++) {
|
||||
BlockVector v = new BlockVector(i, rayY, rayZ);
|
||||
|
||||
if (!getBlocks().containsKey(v) || B.isAir(getBlocks().get(v))) {
|
||||
getBlocks().put(v, debug ? VAIR_DEBUG : VAIR);
|
||||
applied++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Smash Y
|
||||
for (int rayX = min.getBlockX(); rayX <= max.getBlockX(); rayX++) {
|
||||
for (int rayZ = min.getBlockZ(); rayZ <= max.getBlockZ(); rayZ++) {
|
||||
int start = Integer.MAX_VALUE;
|
||||
int end = Integer.MIN_VALUE;
|
||||
|
||||
for (int ray = min.getBlockY(); ray <= max.getBlockY(); ray++) {
|
||||
if (getBlocks().containsKey(new BlockVector(rayX, ray, rayZ))) {
|
||||
start = Math.min(ray, start);
|
||||
end = Math.max(ray, end);
|
||||
}
|
||||
}
|
||||
|
||||
if (start != Integer.MAX_VALUE && end != Integer.MIN_VALUE) {
|
||||
for (int i = start; i <= end; i++) {
|
||||
BlockVector v = new BlockVector(rayX, i, rayZ);
|
||||
|
||||
if (!getBlocks().containsKey(v) || B.isAir(getBlocks().get(v))) {
|
||||
getBlocks().put(v, debug ? VAIR_DEBUG : VAIR);
|
||||
applied++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Smash Z
|
||||
for (int rayX = min.getBlockX(); rayX <= max.getBlockX(); rayX++) {
|
||||
for (int rayY = min.getBlockY(); rayY <= max.getBlockY(); rayY++) {
|
||||
int start = Integer.MAX_VALUE;
|
||||
int end = Integer.MIN_VALUE;
|
||||
|
||||
for (int ray = min.getBlockZ(); ray <= max.getBlockZ(); ray++) {
|
||||
if (getBlocks().containsKey(new BlockVector(rayX, rayY, ray))) {
|
||||
start = Math.min(ray, start);
|
||||
end = Math.max(ray, end);
|
||||
}
|
||||
}
|
||||
|
||||
if (start != Integer.MAX_VALUE && end != Integer.MIN_VALUE) {
|
||||
for (int i = start; i <= end; i++) {
|
||||
BlockVector v = new BlockVector(rayX, rayY, i);
|
||||
|
||||
if (!getBlocks().containsKey(v) || B.isAir(getBlocks().get(v))) {
|
||||
getBlocks().put(v, debug ? VAIR_DEBUG : VAIR);
|
||||
applied++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Iris.verbose("- Applied Smart Bore to " + getLoadKey() + " Filled with " + applied + " VOID_AIR blocks.");
|
||||
|
||||
smartBored = true;
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
public synchronized IrisObject copy() {
|
||||
IrisObject o = new IrisObject(w, h, d);
|
||||
o.setLoadKey(o.getLoadKey());
|
||||
o.setCenter(getCenter().clone());
|
||||
|
||||
for (BlockVector i : getBlocks().keySet()) {
|
||||
o.getBlocks().put(i.clone(), Objects.requireNonNull(getBlocks().get(i)).clone());
|
||||
}
|
||||
|
||||
for (BlockVector i : getStates().keySet()) {
|
||||
o.getStates().put(i.clone(), Objects.requireNonNull(getStates().get(i)).clone());
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
public IrisObject(int w, int h, int d) {
|
||||
blocks = new KMap<>();
|
||||
states = new KMap<>();
|
||||
this.w = w;
|
||||
this.h = h;
|
||||
this.d = d;
|
||||
center = new BlockVector(w / 2, h / 2, d / 2);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"resource", "RedundantSuppression"})
|
||||
public static BlockVector sampleSize(File file) throws IOException {
|
||||
FileInputStream in = new FileInputStream(file);
|
||||
DataInputStream din = new DataInputStream(in);
|
||||
BlockVector bv = new BlockVector(din.readInt(), din.readInt(), din.readInt());
|
||||
Iris.later(din::close);
|
||||
return bv;
|
||||
}
|
||||
|
||||
public void readLegacy(InputStream in) throws IOException {
|
||||
DataInputStream din = new DataInputStream(in);
|
||||
this.w = din.readInt();
|
||||
this.h = din.readInt();
|
||||
this.d = din.readInt();
|
||||
center = new BlockVector(w / 2, h / 2, d / 2);
|
||||
int s = din.readInt();
|
||||
|
||||
for (int i = 0; i < s; i++) {
|
||||
getBlocks().put(new BlockVector(din.readShort(), din.readShort(), din.readShort()), B.get(din.readUTF()));
|
||||
}
|
||||
|
||||
try {
|
||||
int size = din.readInt();
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
getStates().put(new BlockVector(din.readShort(), din.readShort(), din.readShort()), TileData.read(din));
|
||||
}
|
||||
} catch (Throwable e) {Iris.reportError(e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void read(InputStream in) throws Throwable {
|
||||
DataInputStream din = new DataInputStream(in);
|
||||
this.w = din.readInt();
|
||||
this.h = din.readInt();
|
||||
this.d = din.readInt();
|
||||
if (!din.readUTF().equals("Iris V2 IOB;")) {
|
||||
throw new IOException("Not V2 Format");
|
||||
}
|
||||
center = new BlockVector(w / 2, h / 2, d / 2);
|
||||
int s = din.readShort();
|
||||
int i;
|
||||
KList<String> palette = new KList<>();
|
||||
|
||||
for (i = 0; i < s; i++) {
|
||||
palette.add(din.readUTF());
|
||||
}
|
||||
|
||||
s = din.readInt();
|
||||
|
||||
for (i = 0; i < s; i++) {
|
||||
getBlocks().put(new BlockVector(din.readShort(), din.readShort(), din.readShort()), B.get(palette.get(din.readShort())));
|
||||
}
|
||||
|
||||
s = din.readInt();
|
||||
|
||||
for (i = 0; i < s; i++) {
|
||||
getStates().put(new BlockVector(din.readShort(), din.readShort(), din.readShort()), TileData.read(din));
|
||||
}
|
||||
}
|
||||
|
||||
public void write(OutputStream o) throws IOException {
|
||||
DataOutputStream dos = new DataOutputStream(o);
|
||||
dos.writeInt(w);
|
||||
dos.writeInt(h);
|
||||
dos.writeInt(d);
|
||||
dos.writeUTF("Iris V2 IOB;");
|
||||
KList<String> palette = new KList<>();
|
||||
|
||||
for (BlockData i : getBlocks().values()) {
|
||||
palette.addIfMissing(i.getAsString());
|
||||
}
|
||||
|
||||
dos.writeShort(palette.size());
|
||||
|
||||
for (String i : palette) {
|
||||
dos.writeUTF(i);
|
||||
}
|
||||
|
||||
dos.writeInt(getBlocks().size());
|
||||
|
||||
for (BlockVector i : getBlocks().keySet()) {
|
||||
dos.writeShort(i.getBlockX());
|
||||
dos.writeShort(i.getBlockY());
|
||||
dos.writeShort(i.getBlockZ());
|
||||
dos.writeShort(palette.indexOf(Objects.requireNonNull(getBlocks().get(i)).getAsString()));
|
||||
}
|
||||
|
||||
dos.writeInt(getStates().size());
|
||||
for (BlockVector i : getStates().keySet()) {
|
||||
dos.writeShort(i.getBlockX());
|
||||
dos.writeShort(i.getBlockY());
|
||||
dos.writeShort(i.getBlockZ());
|
||||
Objects.requireNonNull(getStates().get(i)).toBinary(dos);
|
||||
}
|
||||
}
|
||||
|
||||
public void read(File file) throws IOException {
|
||||
if (shitty) {
|
||||
return;
|
||||
}
|
||||
|
||||
FileInputStream fin = new FileInputStream(file);
|
||||
try {
|
||||
read(fin);
|
||||
fin.close();
|
||||
} catch (Throwable e) {Iris.reportError(e);
|
||||
fin.close();
|
||||
fin = new FileInputStream(file);
|
||||
readLegacy(fin);
|
||||
fin.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void write(File file) throws IOException {
|
||||
file.getParentFile().mkdirs();
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
write(out);
|
||||
out.close();
|
||||
}
|
||||
|
||||
public void clean() {
|
||||
KMap<BlockVector, BlockData> d = new KMap<>();
|
||||
|
||||
for (BlockVector i : getBlocks().keySet()) {
|
||||
d.put(new BlockVector(i.getBlockX(), i.getBlockY(), i.getBlockZ()), Objects.requireNonNull(getBlocks().get(i)));
|
||||
}
|
||||
|
||||
KMap<BlockVector, TileData<? extends TileState>> dx = new KMap<>();
|
||||
|
||||
for (BlockVector i : getBlocks().keySet()) {
|
||||
d.put(new BlockVector(i.getBlockX(), i.getBlockY(), i.getBlockZ()), Objects.requireNonNull(getBlocks().get(i)));
|
||||
}
|
||||
|
||||
for (BlockVector i : getStates().keySet()) {
|
||||
dx.put(new BlockVector(i.getBlockX(), i.getBlockY(), i.getBlockZ()), Objects.requireNonNull(getStates().get(i)));
|
||||
}
|
||||
|
||||
blocks = d;
|
||||
states = dx;
|
||||
}
|
||||
|
||||
public BlockVector getSigned(int x, int y, int z) {
|
||||
if (x >= w || y >= h || z >= d) {
|
||||
throw new RuntimeException(x + " " + y + " " + z + " exceeds limit of " + w + " " + h + " " + d);
|
||||
}
|
||||
|
||||
return new BlockVector(x, y, z).subtract(center).toBlockVector();
|
||||
}
|
||||
|
||||
public void setUnsigned(int x, int y, int z, BlockData block) {
|
||||
BlockVector v = getSigned(x, y, z);
|
||||
|
||||
if (block == null) {
|
||||
getBlocks().remove(v);
|
||||
getStates().remove(v);
|
||||
} else {
|
||||
getBlocks().put(v, block);
|
||||
}
|
||||
}
|
||||
|
||||
public void setUnsigned(int x, int y, int z, Block block) {
|
||||
BlockVector v = getSigned(x, y, z);
|
||||
|
||||
if (block == null) {
|
||||
getBlocks().remove(v);
|
||||
getStates().remove(v);
|
||||
} else {
|
||||
BlockData data = block.getBlockData();
|
||||
getBlocks().put(v, data);
|
||||
TileData<? extends TileState> state = TileData.getTileState(block);
|
||||
if (state != null) {
|
||||
Iris.info("Saved State " + v);
|
||||
getStates().put(v, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int place(int x, int z, IObjectPlacer placer, IrisObjectPlacement config, RNG rng, IrisDataManager rdata) {
|
||||
return place(x, -1, z, placer, config, rng, rdata);
|
||||
}
|
||||
|
||||
public int place(int x, int z, IObjectPlacer placer, IrisObjectPlacement config, RNG rng, CarveResult c, IrisDataManager rdata) {
|
||||
return place(x, -1, z, placer, config, rng, null, c, rdata);
|
||||
}
|
||||
|
||||
public int place(int x, int yv, int z, IObjectPlacer placer, IrisObjectPlacement config, RNG rng, IrisDataManager rdata) {
|
||||
return place(x, yv, z, placer, config, rng, null, null, rdata);
|
||||
}
|
||||
|
||||
public int place(int x, int yv, int z, IObjectPlacer oplacer, IrisObjectPlacement config, RNG rng, Consumer<BlockPosition> listener, CarveResult c, IrisDataManager rdata) {
|
||||
IObjectPlacer placer = (config.getHeightmap() != null) ? new IObjectPlacer() {
|
||||
final long s = rng.nextLong() + yv + z - x;
|
||||
|
||||
public int getHighest(int param1Int1, int param1Int2) {
|
||||
return (int) Math.round(config.getHeightmap().getNoise(this.s, param1Int1, param1Int2));
|
||||
}
|
||||
|
||||
public int getHighest(int param1Int1, int param1Int2, boolean param1Boolean) {
|
||||
return (int) Math.round(config.getHeightmap().getNoise(this.s, param1Int1, param1Int2));
|
||||
}
|
||||
|
||||
public void set(int param1Int1, int param1Int2, int param1Int3, BlockData param1BlockData) {
|
||||
oplacer.set(param1Int1, param1Int2, param1Int3, param1BlockData);
|
||||
}
|
||||
|
||||
public BlockData get(int param1Int1, int param1Int2, int param1Int3) {
|
||||
return oplacer.get(param1Int1, param1Int2, param1Int3);
|
||||
}
|
||||
|
||||
public boolean isPreventingDecay() {
|
||||
return oplacer.isPreventingDecay();
|
||||
}
|
||||
|
||||
public boolean isSolid(int param1Int1, int param1Int2, int param1Int3) {
|
||||
return oplacer.isSolid(param1Int1, param1Int2, param1Int3);
|
||||
}
|
||||
|
||||
public boolean isUnderwater(int param1Int1, int param1Int2) {
|
||||
return oplacer.isUnderwater(param1Int1, param1Int2);
|
||||
}
|
||||
|
||||
public int getFluidHeight() {
|
||||
return oplacer.getFluidHeight();
|
||||
}
|
||||
|
||||
public boolean isDebugSmartBore() {
|
||||
return oplacer.isDebugSmartBore();
|
||||
}
|
||||
|
||||
public void setTile(int param1Int1, int param1Int2, int param1Int3, TileData<? extends TileState> param1TileData) {
|
||||
oplacer.setTile(param1Int1, param1Int2, param1Int3, param1TileData);
|
||||
}
|
||||
} : oplacer;
|
||||
|
||||
if (config.isSmartBore()) {
|
||||
ensureSmartBored(placer.isDebugSmartBore());
|
||||
}
|
||||
|
||||
boolean warped = !config.getWarp().isFlat();
|
||||
boolean stilting = (config.getMode().equals(ObjectPlaceMode.STILT) || config.getMode().equals(ObjectPlaceMode.FAST_STILT));
|
||||
KMap<ChunkPosition, Integer> heightmap = config.getSnow() > 0 ? new KMap<>() : null;
|
||||
int spinx = rng.imax() / 1000;
|
||||
int spiny = rng.imax() / 1000;
|
||||
int spinz = rng.imax() / 1000;
|
||||
int rty = config.getRotation().rotate(new BlockVector(0, getCenter().getBlockY(), 0), spinx, spiny, spinz).getBlockY();
|
||||
int ty = config.getTranslate().translate(new BlockVector(0, getCenter().getBlockY(), 0), config.getRotation(), spinx, spiny, spinz).getBlockY();
|
||||
int y = -1;
|
||||
int xx, zz;
|
||||
int yrand = config.getTranslate().getYRandom();
|
||||
yrand = yrand > 0 ? rng.i(0, yrand) : yrand < 0 ? rng.i(yrand, 0) : yrand;
|
||||
|
||||
if (yv < 0) {
|
||||
if (config.getMode().equals(ObjectPlaceMode.CENTER_HEIGHT)) {
|
||||
y = (c != null ? c.getSurface() : placer.getHighest(x, z, config.isUnderwater())) + rty;
|
||||
} else if (config.getMode().equals(ObjectPlaceMode.MAX_HEIGHT) || config.getMode().equals(ObjectPlaceMode.STILT)) {
|
||||
BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ());
|
||||
BlockVector rotatedDimensions = config.getRotation().rotate(new BlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone();
|
||||
|
||||
for (int i = x - (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i <= x + (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i++) {
|
||||
for (int j = z - (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j <= z + (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j++) {
|
||||
int h = placer.getHighest(i, j, config.isUnderwater()) + rty;
|
||||
|
||||
if (h > y) {
|
||||
y = h;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (config.getMode().equals(ObjectPlaceMode.FAST_MAX_HEIGHT) || config.getMode().equals(ObjectPlaceMode.VACUUM) || config.getMode().equals(ObjectPlaceMode.FAST_STILT)) {
|
||||
BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ());
|
||||
BlockVector rotatedDimensions = config.getRotation().rotate(new BlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone();
|
||||
|
||||
for (int i = x - (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i <= x + (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i += (rotatedDimensions.getBlockX() / 2) + 1) {
|
||||
for (int j = z - (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j <= z + (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j += (rotatedDimensions.getBlockZ() / 2) + 1) {
|
||||
int h = placer.getHighest(i, j, config.isUnderwater()) + rty;
|
||||
|
||||
if (h > y) {
|
||||
y = h;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (config.getMode().equals(ObjectPlaceMode.MIN_HEIGHT)) {
|
||||
y = 257;
|
||||
BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ());
|
||||
BlockVector rotatedDimensions = config.getRotation().rotate(new BlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone();
|
||||
|
||||
for (int i = x - (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i <= x + (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i++) {
|
||||
for (int j = z - (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j <= z + (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j++) {
|
||||
int h = placer.getHighest(i, j, config.isUnderwater()) + rty;
|
||||
|
||||
if (h < y) {
|
||||
y = h;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (config.getMode().equals(ObjectPlaceMode.FAST_MIN_HEIGHT)) {
|
||||
y = 257;
|
||||
BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ());
|
||||
BlockVector rotatedDimensions = config.getRotation().rotate(new BlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone();
|
||||
|
||||
for (int i = x - (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i <= x + (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i += (rotatedDimensions.getBlockX() / 2) + 1) {
|
||||
for (int j = z - (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j <= z + (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j += (rotatedDimensions.getBlockZ() / 2) + 1) {
|
||||
int h = placer.getHighest(i, j, config.isUnderwater()) + rty;
|
||||
|
||||
if (h < y) {
|
||||
y = h;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (config.getMode().equals(ObjectPlaceMode.PAINT)) {
|
||||
y = placer.getHighest(x, z, config.isUnderwater()) + rty;
|
||||
}
|
||||
} else {
|
||||
y = yv;
|
||||
}
|
||||
|
||||
if (yv >= 0 && config.isBottom()) {
|
||||
y += Math.floorDiv(h, 2);
|
||||
}
|
||||
|
||||
if (yv < 0) {
|
||||
if (!config.isUnderwater() && !config.isOnwater() && placer.isUnderwater(x, z)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (c != null && Math.max(0, h + yrand + ty) + 1 >= c.getHeight()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (config.isUnderwater() && y + rty + ty >= placer.getFluidHeight()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!config.getClamp().canPlace(y + rty + ty, y - rty + ty)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (config.isBore()) {
|
||||
BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ());
|
||||
for (int i = x - Math.floorDiv(w, 2) + (int) offset.getX(); i <= x + Math.floorDiv(w, 2) - (w % 2 == 0 ? 1 : 0) + (int) offset.getX(); i++) {
|
||||
for (int j = y - Math.floorDiv(h, 2) - config.getBoreExtendMinY() + (int) offset.getY(); j <= y + Math.floorDiv(h, 2) + config.getBoreExtendMaxY() - (h % 2 == 0 ? 1 : 0) + (int) offset.getY(); j++) {
|
||||
for (int k = z - Math.floorDiv(d, 2) + (int) offset.getZ(); k <= z + Math.floorDiv(d, 2) - (d % 2 == 0 ? 1 : 0) + (int) offset.getX(); k++) {
|
||||
placer.set(i, j, k, AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int lowest = Integer.MAX_VALUE;
|
||||
y += yrand;
|
||||
readLock.lock();
|
||||
for (BlockVector g : getBlocks().keySet()) {
|
||||
BlockData d;
|
||||
TileData<? extends TileState> tile = null;
|
||||
|
||||
try {
|
||||
d = getBlocks().get(g);
|
||||
tile = getStates().get(g);
|
||||
} catch (Throwable e) {Iris.reportError(e);
|
||||
Iris.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (cme)");
|
||||
d = AIR;
|
||||
}
|
||||
|
||||
if (d == null) {
|
||||
Iris.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (null)");
|
||||
d = AIR;
|
||||
}
|
||||
|
||||
BlockVector i = g.clone();
|
||||
BlockData data = d.clone();
|
||||
i = config.getRotation().rotate(i.clone(), spinx, spiny, spinz).clone();
|
||||
i = config.getTranslate().translate(i.clone(), config.getRotation(), spinx, spiny, spinz).clone();
|
||||
|
||||
if (stilting && i.getBlockY() < lowest && !B.isAir(data)) {
|
||||
lowest = i.getBlockY();
|
||||
}
|
||||
|
||||
if (placer.isPreventingDecay() && (data) instanceof Leaves && !((Leaves) (data)).isPersistent()) {
|
||||
((Leaves) data).setPersistent(true);
|
||||
}
|
||||
|
||||
for (IrisObjectReplace j : config.getEdit()) {
|
||||
if (rng.chance(j.getChance())) {
|
||||
for (BlockData k : j.getFind(rdata)) {
|
||||
if (j.isExact() ? k.matches(data) : k.getMaterial().equals(data.getMaterial())) {
|
||||
BlockData newData = j.getReplace(rng, i.getX() + x, i.getY() + y, i.getZ() + z, rdata).clone();
|
||||
|
||||
if (newData.getMaterial() == data.getMaterial())
|
||||
data = data.merge(newData);
|
||||
else
|
||||
data = newData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data = config.getRotation().rotate(data, spinx, spiny, spinz);
|
||||
xx = x + (int) Math.round(i.getX());
|
||||
int yy = y + (int) Math.round(i.getY());
|
||||
zz = z + (int) Math.round(i.getZ());
|
||||
|
||||
if (warped) {
|
||||
xx += config.warp(rng, i.getX() + x, i.getY() + y, i.getZ() + z);
|
||||
zz += config.warp(rng, i.getZ() + z, i.getY() + y, i.getX() + x);
|
||||
}
|
||||
|
||||
if (yv < 0 && (config.getMode().equals(ObjectPlaceMode.PAINT))) {
|
||||
yy = (int) Math.round(i.getY()) + Math.floorDiv(h, 2) + placer.getHighest(xx, zz, config.isUnderwater());
|
||||
}
|
||||
|
||||
if (heightmap != null) {
|
||||
ChunkPosition pos = new ChunkPosition(xx, zz);
|
||||
|
||||
if (!heightmap.containsKey(pos)) {
|
||||
heightmap.put(pos, yy);
|
||||
}
|
||||
|
||||
if (heightmap.get(pos) < yy) {
|
||||
heightmap.put(pos, yy);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.isMeld() && !placer.isSolid(xx, yy, zz)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config.isWaterloggable() && yy <= placer.getFluidHeight() && data instanceof Waterlogged) {
|
||||
((Waterlogged) data).setWaterlogged(true);
|
||||
}
|
||||
|
||||
if (listener != null) {
|
||||
listener.accept(new BlockPosition(xx, yy, zz));
|
||||
}
|
||||
|
||||
if (!data.getMaterial().equals(Material.AIR) && !data.getMaterial().equals(Material.CAVE_AIR)) {
|
||||
placer.set(xx, yy, zz, data);
|
||||
|
||||
if (tile != null) {
|
||||
placer.setTile(xx, yy, zz, tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
readLock.unlock();
|
||||
|
||||
if (stilting) {
|
||||
readLock.lock();
|
||||
for (BlockVector g : getBlocks().keySet()) {
|
||||
BlockData d;
|
||||
|
||||
try {
|
||||
d = getBlocks().get(g);
|
||||
} catch (Throwable e) {Iris.reportError(e);
|
||||
Iris.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (stilt cme)");
|
||||
d = AIR;
|
||||
}
|
||||
|
||||
if (d == null) {
|
||||
Iris.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (stilt null)");
|
||||
d = AIR;
|
||||
}
|
||||
|
||||
BlockVector i = g.clone();
|
||||
i = config.getRotation().rotate(i.clone(), spinx, spiny, spinz).clone();
|
||||
i = config.getTranslate().translate(i.clone(), config.getRotation(), spinx, spiny, spinz).clone();
|
||||
|
||||
if (i.getBlockY() != lowest) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (d == null || B.isAir(d)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
xx = x + (int) Math.round(i.getX());
|
||||
zz = z + (int) Math.round(i.getZ());
|
||||
|
||||
if (warped) {
|
||||
xx += config.warp(rng, i.getX() + x, i.getY() + y, i.getZ() + z);
|
||||
zz += config.warp(rng, i.getZ() + z, i.getY() + y, i.getX() + x);
|
||||
}
|
||||
|
||||
int yg = placer.getHighest(xx, zz, config.isUnderwater());
|
||||
|
||||
if (yv >= 0 && config.isBottom()) {
|
||||
y += Math.floorDiv(h, 2);
|
||||
}
|
||||
|
||||
for (int j = lowest + y; j > yg - config.getOverStilt() - 1; j--) {
|
||||
placer.set(xx, j, zz, d);
|
||||
}
|
||||
}
|
||||
|
||||
readLock.unlock();
|
||||
}
|
||||
|
||||
if (heightmap != null) {
|
||||
RNG rngx = rng.nextParallelRNG(3468854);
|
||||
|
||||
for (ChunkPosition i : heightmap.k()) {
|
||||
int vx = i.getX();
|
||||
int vy = heightmap.get(i);
|
||||
int vz = i.getZ();
|
||||
|
||||
if (config.getSnow() > 0) {
|
||||
int height = rngx.i(0, (int) (config.getSnow() * 7));
|
||||
placer.set(vx, vy + 1, vz, SNOW_LAYERS[Math.max(Math.min(height, 7), 0)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
public IrisObject rotateCopy(IrisObjectRotation rt) {
|
||||
IrisObject copy = copy();
|
||||
copy.rotate(rt, 0, 0, 0);
|
||||
return copy;
|
||||
}
|
||||
|
||||
public void rotate(IrisObjectRotation r, int spinx, int spiny, int spinz) {
|
||||
KMap<BlockVector, BlockData> d = new KMap<>();
|
||||
|
||||
for (BlockVector i : getBlocks().keySet()) {
|
||||
d.put(r.rotate(i.clone(), spinx, spiny, spinz), r.rotate(Objects.requireNonNull(getBlocks().get(i)).clone(), spinx, spiny, spinz));
|
||||
}
|
||||
|
||||
KMap<BlockVector, TileData<? extends TileState>> dx = new KMap<>();
|
||||
|
||||
for (BlockVector i : getStates().keySet()) {
|
||||
dx.put(r.rotate(i.clone(), spinx, spiny, spinz), Objects.requireNonNull(getStates().get(i)));
|
||||
}
|
||||
|
||||
blocks = d;
|
||||
states = dx;
|
||||
}
|
||||
|
||||
public void place(Location at) {
|
||||
for (BlockVector i : getBlocks().keySet()) {
|
||||
Block b = at.clone().add(0, getCenter().getY(), 0).add(i).getBlock();
|
||||
b.setBlockData(Objects.requireNonNull(getBlocks().get(i)), false);
|
||||
|
||||
if (getStates().containsKey(i)) {
|
||||
Iris.info(Objects.requireNonNull(states.get(i)).toString());
|
||||
BlockState st = b.getState();
|
||||
Objects.requireNonNull(getStates().get(i)).toBukkitTry(st);
|
||||
st.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void placeCenterY(Location at) {
|
||||
for (BlockVector i : getBlocks().keySet()) {
|
||||
Block b = at.clone().add(getCenter().getX(), getCenter().getY(), getCenter().getZ()).add(i).getBlock();
|
||||
b.setBlockData(Objects.requireNonNull(getBlocks().get(i)), false);
|
||||
|
||||
if (getStates().containsKey(i)) {
|
||||
Objects.requireNonNull(getStates().get(i)).toBukkitTry(b.getState());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized KMap<BlockVector, BlockData> getBlocks() {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
public synchronized KMap<BlockVector, TileData<? extends TileState>> getStates() {
|
||||
return states;
|
||||
}
|
||||
|
||||
public void unplaceCenterY(Location at) {
|
||||
for (BlockVector i : getBlocks().keySet()) {
|
||||
at.clone().add(getCenter().getX(), getCenter().getY(), getCenter().getZ()).add(i).getBlock().setBlockData(AIR, false);
|
||||
}
|
||||
}
|
||||
|
||||
public IrisObject scaled(double scale, IrisObjectPlacementScaleInterpolator interpolation) {
|
||||
Vector sm1 = new Vector(scale - 1, scale - 1, scale - 1);
|
||||
scale = Math.max(0.001, Math.min(50, scale));
|
||||
if (scale < 1) {
|
||||
scale = scale - 0.0001;
|
||||
}
|
||||
|
||||
IrisPosition l1 = getAABB().max();
|
||||
IrisPosition l2 = getAABB().min();
|
||||
Vector center = getCenter();
|
||||
if (getH() == 2) {
|
||||
center = center.setY(center.getBlockY() + 0.5);
|
||||
}
|
||||
if (getW() == 2) {
|
||||
center = center.setX(center.getBlockX() + 0.5);
|
||||
}
|
||||
if (getD() == 2) {
|
||||
center = center.setZ(center.getBlockZ() + 0.5);
|
||||
}
|
||||
@SuppressWarnings({"unchecked", "rawtypes"}) HashMap<BlockVector, BlockData> placeBlock = new HashMap();
|
||||
|
||||
IrisObject oo = new IrisObject((int) Math.ceil((w * scale) + (scale * 2)), (int) Math.ceil((h * scale) + (scale * 2)), (int) Math.ceil((d * scale) + (scale * 2)));
|
||||
|
||||
for (Map.Entry<BlockVector, BlockData> entry : blocks.entrySet()) {
|
||||
BlockData bd = entry.getValue();
|
||||
placeBlock.put(entry.getKey().clone().add(HALF).subtract(center)
|
||||
.multiply(scale).toBlockVector(), bd);
|
||||
}
|
||||
|
||||
for (Map.Entry<BlockVector, BlockData> entry : placeBlock.entrySet()) {
|
||||
BlockVector v = entry.getKey();
|
||||
if (scale > 1) {
|
||||
for (BlockVector vec : blocksBetweenTwoPoints(v.clone().add(center), v.clone().add(center).add(sm1))) {
|
||||
oo.getBlocks().put(vec, entry.getValue());
|
||||
}
|
||||
} else {
|
||||
oo.setUnsigned(v.getBlockX(), v.getBlockY(), v.getBlockZ(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (scale > 1) {
|
||||
switch (interpolation) {
|
||||
case TRILINEAR -> oo.trilinear((int) Math.round(scale));
|
||||
case TRICUBIC -> oo.tricubic((int) Math.round(scale));
|
||||
case TRIHERMITE -> oo.trihermite((int) Math.round(scale));
|
||||
}
|
||||
}
|
||||
|
||||
return oo;
|
||||
}
|
||||
|
||||
public void trilinear(int rad) {
|
||||
KMap<BlockVector, BlockData> v = getBlocks().copy();
|
||||
KMap<BlockVector, BlockData> b = new KMap<>();
|
||||
BlockVector min = getAABB().minbv();
|
||||
BlockVector max = getAABB().maxbv();
|
||||
|
||||
for (int x = min.getBlockX(); x <= max.getBlockX(); x++) {
|
||||
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
|
||||
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
|
||||
if (IrisInterpolation.getTrilinear(x, y, z, rad, (xx, yy, zz) -> {
|
||||
BlockData data = v.get(new BlockVector((int) xx, (int) yy, (int) zz));
|
||||
|
||||
if (data == null || data.getMaterial().isAir()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}) >= 0.5) {
|
||||
b.put(new BlockVector(x, y, z), nearestBlockData(x, y, z));
|
||||
} else {
|
||||
b.put(new BlockVector(x, y, z), AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setBlocks(b);
|
||||
}
|
||||
|
||||
public void tricubic(int rad) {
|
||||
KMap<BlockVector, BlockData> v = getBlocks().copy();
|
||||
KMap<BlockVector, BlockData> b = new KMap<>();
|
||||
BlockVector min = getAABB().minbv();
|
||||
BlockVector max = getAABB().maxbv();
|
||||
|
||||
for (int x = min.getBlockX(); x <= max.getBlockX(); x++) {
|
||||
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
|
||||
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
|
||||
if (IrisInterpolation.getTricubic(x, y, z, rad, (xx, yy, zz) -> {
|
||||
BlockData data = v.get(new BlockVector((int) xx, (int) yy, (int) zz));
|
||||
|
||||
if (data == null || data.getMaterial().isAir()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}) >= 0.5) {
|
||||
b.put(new BlockVector(x, y, z), nearestBlockData(x, y, z));
|
||||
} else {
|
||||
b.put(new BlockVector(x, y, z), AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setBlocks(b);
|
||||
}
|
||||
|
||||
public void trihermite(int rad) {
|
||||
trihermite(rad, 0D, 0D);
|
||||
}
|
||||
|
||||
public void trihermite(int rad, double tension, double bias) {
|
||||
KMap<BlockVector, BlockData> v = getBlocks().copy();
|
||||
KMap<BlockVector, BlockData> b = new KMap<>();
|
||||
BlockVector min = getAABB().minbv();
|
||||
BlockVector max = getAABB().maxbv();
|
||||
|
||||
for (int x = min.getBlockX(); x <= max.getBlockX(); x++) {
|
||||
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
|
||||
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
|
||||
if (IrisInterpolation.getTrihermite(x, y, z, rad, (xx, yy, zz) -> {
|
||||
BlockData data = v.get(new BlockVector((int) xx, (int) yy, (int) zz));
|
||||
|
||||
if (data == null || data.getMaterial().isAir()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}, tension, bias) >= 0.5) {
|
||||
b.put(new BlockVector(x, y, z), nearestBlockData(x, y, z));
|
||||
} else {
|
||||
b.put(new BlockVector(x, y, z), AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setBlocks(b);
|
||||
}
|
||||
|
||||
private BlockData nearestBlockData(int x, int y, int z) {
|
||||
BlockVector vv = new BlockVector(x, y, z);
|
||||
BlockData r = getBlocks().get(vv);
|
||||
|
||||
if (r != null && !r.getMaterial().isAir()) {
|
||||
return r;
|
||||
}
|
||||
|
||||
double d = Double.MAX_VALUE;
|
||||
|
||||
for (Map.Entry<BlockVector, BlockData> entry : blocks.entrySet()) {
|
||||
BlockData dat = entry.getValue();
|
||||
|
||||
if (dat.getMaterial().isAir()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double dx = entry.getKey().distanceSquared(vv);
|
||||
|
||||
if (dx < d) {
|
||||
d = dx;
|
||||
r = dat;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
private static List<BlockVector> blocksBetweenTwoPoints(Vector loc1, Vector loc2) {
|
||||
List<BlockVector> locations = new ArrayList<>();
|
||||
int topBlockX = Math.max(loc1.getBlockX(), loc2.getBlockX());
|
||||
int bottomBlockX = Math.min(loc1.getBlockX(), loc2.getBlockX());
|
||||
int topBlockY = Math.max(loc1.getBlockY(), loc2.getBlockY());
|
||||
int bottomBlockY = Math.min(loc1.getBlockY(), loc2.getBlockY());
|
||||
int topBlockZ = Math.max(loc1.getBlockZ(), loc2.getBlockZ());
|
||||
int bottomBlockZ = Math.min(loc1.getBlockZ(), loc2.getBlockZ());
|
||||
|
||||
for (int x = bottomBlockX; x <= topBlockX; x++) {
|
||||
for (int z = bottomBlockZ; z <= topBlockZ; z++) {
|
||||
for (int y = bottomBlockY; y <= topBlockY; y++) {
|
||||
locations.add(new BlockVector(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
return locations;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.MaxNumber;
|
||||
import com.volmit.iris.util.MinNumber;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Translate objects")
|
||||
@Data
|
||||
public class IrisObjectLimit {
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(255)
|
||||
@Desc("The minimum height for placement (bottom of object)")
|
||||
private int minimumHeight = 0;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(255)
|
||||
@Desc("The maximum height for placement (top of object)")
|
||||
private int maximumHeight = 255;
|
||||
|
||||
public boolean canPlace(int h, int l) {
|
||||
return h <= maximumHeight && l >= minimumHeight;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents loot within this object or jigsaw piece")
|
||||
@Data
|
||||
public class IrisObjectLoot {
|
||||
|
||||
|
||||
@ArrayType(min = 1, type = IrisBlockData.class)
|
||||
@Desc("The list of blocks this loot table should apply to")
|
||||
private KList<IrisBlockData> filter = new KList<>();
|
||||
|
||||
@Desc("Exactly match the block data or not")
|
||||
|
||||
private boolean exact = false;
|
||||
|
||||
|
||||
@Desc("The loot table name")
|
||||
@Required
|
||||
@RegistryListLoot
|
||||
private String name;
|
||||
|
||||
|
||||
@Desc("The weight of this loot table being chosen")
|
||||
private int weight = 1;
|
||||
|
||||
private final transient AtomicCache<KList<BlockData>> filterCache = new AtomicCache<>();
|
||||
|
||||
public KList<BlockData> getFilter(IrisDataManager rdata) {
|
||||
return filterCache.aquire(() ->
|
||||
{
|
||||
KList<BlockData> b = new KList<>();
|
||||
|
||||
for (IrisBlockData i : filter) {
|
||||
BlockData bx = i.getBlockData(rdata);
|
||||
|
||||
if (bx != null) {
|
||||
b.add(bx);
|
||||
}
|
||||
}
|
||||
|
||||
return b;
|
||||
});
|
||||
}
|
||||
|
||||
public boolean matchesFilter(IrisDataManager manager, BlockData data) {
|
||||
for (BlockData filterData : getFilter(manager)) {
|
||||
if (filterData.matches(data)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.noise.CNG;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.data.DataProvider;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
@EqualsAndHashCode()
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents an iris object placer. It places objects.")
|
||||
@Data
|
||||
public class IrisObjectPlacement {
|
||||
@RegistryListObject
|
||||
@Required
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
@Desc("List of objects to place")
|
||||
private KList<String> place = new KList<>();
|
||||
|
||||
@Desc("Rotate this objects placement")
|
||||
private IrisObjectRotation rotation = new IrisObjectRotation();
|
||||
|
||||
|
||||
@Desc("Limit the max height or min height of placement.")
|
||||
private IrisObjectLimit clamp = new IrisObjectLimit();
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1)
|
||||
@Desc("The maximum layer level of a snow filter overtop of this placement. Set to 0 to disable. Max of 1.")
|
||||
private double snow = 0;
|
||||
|
||||
@Required
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1)
|
||||
@Desc("The chance for this to place in a chunk. If you need multiple per chunk, set this to 1 and use density.")
|
||||
private double chance = 1;
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("If the chance check passes, place this many in a single chunk")
|
||||
private int density = 1;
|
||||
|
||||
@MaxNumber(64)
|
||||
@MinNumber(0)
|
||||
@Desc("If the place mode is set to stilt, you can over-stilt it even further into the ground. Especially useful when using fast stilt due to inaccuracies.")
|
||||
private int overStilt = 0;
|
||||
|
||||
@MaxNumber(64)
|
||||
@MinNumber(0)
|
||||
@Desc("When bore is enabled, expand max-y of the cuboid it removes")
|
||||
private int boreExtendMaxY = 0;
|
||||
|
||||
@MaxNumber(64)
|
||||
@MinNumber(-1)
|
||||
@Desc("When bore is enabled, lower min-y of the cuboid it removes")
|
||||
private int boreExtendMinY = 0;
|
||||
|
||||
|
||||
@Desc("If set to true, objects will place on the terrain height, ignoring the water surface.")
|
||||
private boolean underwater = false;
|
||||
|
||||
|
||||
@Desc("If set to true, objects will place in carvings (such as underground) or under an overhang.")
|
||||
private CarvingMode carvingSupport = CarvingMode.SURFACE_ONLY;
|
||||
|
||||
|
||||
@Desc("If this is defined, this object wont place on the terrain heightmap, but instead on this virtual heightmap")
|
||||
private IrisNoiseGenerator heightmap;
|
||||
|
||||
|
||||
@Desc("If set to true, Iris will try to fill the insides of 'rooms' and 'pockets' where air should fit based off of raytrace checks. This prevents a village house placing in an area where a tree already exists, and instead replaces the parts of the tree where the interior of the structure is. \n\nThis operation does not affect warmed-up generation speed however it does slow down loading objects.")
|
||||
private boolean smartBore = false;
|
||||
|
||||
|
||||
@Desc("If set to true, Blocks placed underwater that could be waterlogged are waterlogged.")
|
||||
private boolean waterloggable = false;
|
||||
|
||||
|
||||
@Desc("If set to true, objects will place on the fluid height level Such as boats.")
|
||||
private boolean onwater = false;
|
||||
|
||||
|
||||
@Desc("If set to true, this object will only place parts of itself where blocks already exist. Warning: Melding is very performance intensive!")
|
||||
private boolean meld = false;
|
||||
|
||||
|
||||
@Desc("If set to true, this object will place from the ground up instead of height checks when not y locked to the surface. This is not compatable with X and Z axis rotations (it may look off)")
|
||||
private boolean bottom = false;
|
||||
|
||||
|
||||
@Desc("If set to true, air will be placed before the schematic places.")
|
||||
private boolean bore = false;
|
||||
|
||||
|
||||
@Desc("Use a generator to warp the field of coordinates. Using simplex for example would make a square placement warp like a flag")
|
||||
private IrisGeneratorStyle warp = new IrisGeneratorStyle(NoiseStyle.FLAT);
|
||||
|
||||
|
||||
@Desc("If the place mode is set to CENTER_HEIGHT_RIGID and you have an X/Z translation, Turning on translate center will also translate the center height check.")
|
||||
private boolean translateCenter = false;
|
||||
|
||||
|
||||
@Desc("The placement mode")
|
||||
private ObjectPlaceMode mode = ObjectPlaceMode.CENTER_HEIGHT;
|
||||
|
||||
@ArrayType(min = 1, type = IrisObjectReplace.class)
|
||||
@Desc("Find and replace blocks")
|
||||
private KList<IrisObjectReplace> edit = new KList<>();
|
||||
|
||||
|
||||
@Desc("Translate this object's placement")
|
||||
private IrisObjectTranslate translate = new IrisObjectTranslate();
|
||||
|
||||
|
||||
@Desc("Scale Objects")
|
||||
private IrisObjectScale scale = new IrisObjectScale();
|
||||
|
||||
@ArrayType(min = 1, type = IrisObjectLoot.class)
|
||||
@Desc("The loot tables to apply to these objects")
|
||||
private KList<IrisObjectLoot> loot = new KList<>();
|
||||
|
||||
public IrisObjectPlacement toPlacement(String... place) {
|
||||
IrisObjectPlacement p = new IrisObjectPlacement();
|
||||
p.setPlace(new KList<>(place));
|
||||
p.setTranslateCenter(translateCenter);
|
||||
p.setMode(mode);
|
||||
p.setEdit(edit);
|
||||
p.setTranslate(translate);
|
||||
p.setWarp(warp);
|
||||
p.setBore(bore);
|
||||
p.setMeld(meld);
|
||||
p.setWaterloggable(waterloggable);
|
||||
p.setOnwater(onwater);
|
||||
p.setSmartBore(smartBore);
|
||||
p.setCarvingSupport(carvingSupport);
|
||||
p.setUnderwater(underwater);
|
||||
p.setBoreExtendMaxY(boreExtendMaxY);
|
||||
p.setBoreExtendMinY(boreExtendMinY);
|
||||
p.setOverStilt(overStilt);
|
||||
p.setDensity(density);
|
||||
p.setChance(chance);
|
||||
p.setSnow(snow);
|
||||
p.setClamp(clamp);
|
||||
p.setRotation(rotation);
|
||||
p.setLoot(loot);
|
||||
return p;
|
||||
}
|
||||
|
||||
private final transient AtomicCache<CNG> surfaceWarp = new AtomicCache<>();
|
||||
|
||||
public CNG getSurfaceWarp(RNG rng) {
|
||||
return surfaceWarp.aquire(() ->
|
||||
getWarp().create(rng));
|
||||
}
|
||||
|
||||
public double warp(RNG rng, double x, double y, double z) {
|
||||
return getSurfaceWarp(rng).fitDouble(-(getWarp().getMultiplier() / 2D), (getWarp().getMultiplier() / 2D), x, y, z);
|
||||
}
|
||||
|
||||
public int getTriesForChunk(RNG random) {
|
||||
if (chance <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (chance >= 1 || random.nextDouble() < chance) {
|
||||
return density;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public IrisObject getObject(DataProvider g, RNG random) {
|
||||
if (place.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return g.getData().getObjectLoader().load(place.get(random.nextInt(place.size())));
|
||||
}
|
||||
|
||||
public boolean isVacuum() {
|
||||
return getMode().equals(ObjectPlaceMode.VACUUM);
|
||||
}
|
||||
|
||||
private transient AtomicCache<TableCache> cache = new AtomicCache<>();
|
||||
|
||||
private static class TableCache {
|
||||
final transient WeightedRandom<IrisLootTable> global = new WeightedRandom<>();
|
||||
final transient KMap<Material, WeightedRandom<IrisLootTable>> basic = new KMap<>();
|
||||
final transient KMap<Material, KMap<BlockData, WeightedRandom<IrisLootTable>>> exact = new KMap<>();
|
||||
}
|
||||
|
||||
private TableCache getCache(IrisDataManager manager) {
|
||||
return cache.aquire(() -> {
|
||||
TableCache tc = new TableCache();
|
||||
|
||||
for (IrisObjectLoot loot : getLoot()) {
|
||||
IrisLootTable table = manager.getLootLoader().load(loot.getName());
|
||||
if (table == null) {
|
||||
Iris.warn("Couldn't find loot table " + loot.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (loot.getFilter().isEmpty()) //Table applies to all containers
|
||||
{
|
||||
tc.global.put(table, loot.getWeight());
|
||||
} else if (!loot.isExact()) //Table is meant to be by type
|
||||
{
|
||||
for (BlockData filterData : loot.getFilter(manager)) {
|
||||
if (!tc.basic.containsKey(filterData.getMaterial())) {
|
||||
tc.basic.put(filterData.getMaterial(), new WeightedRandom<>());
|
||||
}
|
||||
|
||||
tc.basic.get(filterData.getMaterial()).put(table, loot.getWeight());
|
||||
}
|
||||
} else //Filter is exact
|
||||
{
|
||||
for (BlockData filterData : loot.getFilter(manager)) {
|
||||
if (!tc.exact.containsKey(filterData.getMaterial())) {
|
||||
tc.exact.put(filterData.getMaterial(), new KMap<>());
|
||||
}
|
||||
|
||||
if (!tc.exact.get(filterData.getMaterial()).containsKey(filterData)) {
|
||||
tc.exact.get(filterData.getMaterial()).put(filterData, new WeightedRandom<>());
|
||||
}
|
||||
|
||||
tc.exact.get(filterData.getMaterial()).get(filterData).put(table, loot.getWeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
return tc;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the loot table that should be used for the block
|
||||
*
|
||||
* @param data The block data of the block
|
||||
* @param dataManager Iris Data Manager
|
||||
* @return The loot table it should use.
|
||||
*/
|
||||
public IrisLootTable getTable(BlockData data, IrisDataManager dataManager) {
|
||||
TableCache cache = getCache(dataManager);
|
||||
|
||||
if (B.isStorageChest(data)) {
|
||||
IrisLootTable picked = null;
|
||||
if (cache.exact.containsKey(data.getMaterial()) && cache.exact.containsKey(data)) {
|
||||
picked = cache.exact.get(data.getMaterial()).get(data).pullRandom();
|
||||
} else if (cache.basic.containsKey(data.getMaterial())) {
|
||||
picked = cache.basic.get(data.getMaterial()).pullRandom();
|
||||
} else if (cache.global.getSize() > 0) {
|
||||
picked = cache.global.pullRandom();
|
||||
}
|
||||
|
||||
return picked;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
|
||||
@Desc("Use 3D Interpolation on scaled objects if they are larger than the origin.")
|
||||
public enum IrisObjectPlacementScaleInterpolator {
|
||||
|
||||
@Desc("Don't interpolate, big cubes")
|
||||
NONE,
|
||||
|
||||
|
||||
@Desc("Uses linear interpolation in 3 dimensions, generally pretty good, but slow")
|
||||
TRILINEAR,
|
||||
|
||||
|
||||
@Desc("Uses cubic spline interpolation in 3 dimensions, even better, but extreme slowdowns")
|
||||
TRICUBIC,
|
||||
|
||||
|
||||
@Desc("Uses hermite spline interpolation in 3 dimensions, even better, but extreme slowdowns")
|
||||
TRIHERMITE
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.noise.CNG;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Find and replace object materials")
|
||||
@Data
|
||||
public class IrisObjectReplace {
|
||||
@ArrayType(min = 1, type = IrisBlockData.class)
|
||||
@Required
|
||||
@Desc("Find this block")
|
||||
|
||||
private KList<IrisBlockData> find = new KList<>();
|
||||
|
||||
@Required
|
||||
@Desc("Replace it with this block palette")
|
||||
|
||||
private IrisMaterialPalette replace = new IrisMaterialPalette();
|
||||
|
||||
@Desc("Exactly match the block data or not")
|
||||
|
||||
private boolean exact = false;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1)
|
||||
@Desc("Modifies the chance the block is replaced")
|
||||
|
||||
private float chance = 1;
|
||||
|
||||
private final transient AtomicCache<CNG> replaceGen = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<BlockData>> findData = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<BlockData>> replaceData = new AtomicCache<>();
|
||||
|
||||
public KList<BlockData> getFind(IrisDataManager rdata) {
|
||||
return findData.aquire(() ->
|
||||
{
|
||||
KList<BlockData> b = new KList<>();
|
||||
|
||||
for (IrisBlockData i : find) {
|
||||
BlockData bx = i.getBlockData(rdata);
|
||||
|
||||
if (bx != null) {
|
||||
b.add(bx);
|
||||
}
|
||||
}
|
||||
|
||||
return b;
|
||||
});
|
||||
}
|
||||
|
||||
public BlockData getReplace(RNG seed, double x, double y, double z, IrisDataManager rdata) {
|
||||
return getReplace().get(seed, x, y, z, rdata);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.KList;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.Axis;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.*;
|
||||
import org.bukkit.util.BlockVector;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Configures rotation for iris")
|
||||
@Data
|
||||
public class IrisObjectRotation {
|
||||
|
||||
@Desc("If this rotator is enabled or not")
|
||||
private boolean enabled = true;
|
||||
|
||||
|
||||
@Desc("The x axis rotation")
|
||||
private IrisAxisRotationClamp xAxis = new IrisAxisRotationClamp();
|
||||
|
||||
|
||||
@Desc("The y axis rotation")
|
||||
private IrisAxisRotationClamp yAxis = new IrisAxisRotationClamp(true, false, 0, 0, 90);
|
||||
|
||||
|
||||
@Desc("The z axis rotation")
|
||||
private IrisAxisRotationClamp zAxis = new IrisAxisRotationClamp();
|
||||
|
||||
public double getYRotation(int spin) {
|
||||
return getRotation(spin, yAxis);
|
||||
}
|
||||
|
||||
public double getXRotation(int spin) {
|
||||
return getRotation(spin, xAxis);
|
||||
}
|
||||
|
||||
public double getZRotation(int spin) {
|
||||
return getRotation(spin, zAxis);
|
||||
}
|
||||
|
||||
public IrisObject rotateCopy(IrisObject e) {
|
||||
return e.rotateCopy(this);
|
||||
}
|
||||
|
||||
public IrisJigsawPiece rotateCopy(IrisJigsawPiece v) {
|
||||
IrisJigsawPiece piece = v.copy();
|
||||
for (IrisJigsawPieceConnector i : piece.getConnectors()) {
|
||||
i.setPosition(rotate(i.getPosition()));
|
||||
i.setDirection(rotate(i.getDirection()));
|
||||
}
|
||||
|
||||
return piece;
|
||||
}
|
||||
|
||||
|
||||
public BlockVector rotate(BlockVector direction) {
|
||||
return rotate(direction, 0, 0, 0);
|
||||
}
|
||||
|
||||
public IrisDirection rotate(IrisDirection direction) {
|
||||
BlockVector v = rotate(direction.toVector().toBlockVector());
|
||||
return IrisDirection.closest(v);
|
||||
}
|
||||
|
||||
public static IrisObjectRotation of(double x, double y, double z) {
|
||||
IrisObjectRotation rt = new IrisObjectRotation();
|
||||
IrisAxisRotationClamp rtx = new IrisAxisRotationClamp();
|
||||
IrisAxisRotationClamp rty = new IrisAxisRotationClamp();
|
||||
IrisAxisRotationClamp rtz = new IrisAxisRotationClamp();
|
||||
rt.setEnabled(x != 0 || y != 0 || z != 0);
|
||||
rt.setXAxis(rtx);
|
||||
rt.setYAxis(rty);
|
||||
rt.setZAxis(rtz);
|
||||
rtx.setEnabled(x != 0);
|
||||
rty.setEnabled(y != 0);
|
||||
rtz.setEnabled(z != 0);
|
||||
rtx.setInterval(90);
|
||||
rty.setInterval(90);
|
||||
rtz.setInterval(90);
|
||||
rtx.minMax(x);
|
||||
rty.minMax(y);
|
||||
rtz.minMax(z);
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public double getRotation(int spin, IrisAxisRotationClamp clamp) {
|
||||
if (!enabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!clamp.isEnabled()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return clamp.getRadians(spin);
|
||||
}
|
||||
|
||||
public BlockFace getFace(BlockVector v) {
|
||||
int x = (int) Math.round(v.getX());
|
||||
int y = (int) Math.round(v.getY());
|
||||
int z = (int) Math.round(v.getZ());
|
||||
|
||||
if (x == 0 && z == -1) {
|
||||
return BlockFace.NORTH;
|
||||
}
|
||||
|
||||
if (x == 0 && z == 1) {
|
||||
return BlockFace.SOUTH;
|
||||
}
|
||||
|
||||
if (x == 1 && z == 0) {
|
||||
return BlockFace.EAST;
|
||||
}
|
||||
|
||||
if (x == -1 && z == 0) {
|
||||
return BlockFace.WEST;
|
||||
}
|
||||
|
||||
if (y > 0) {
|
||||
return BlockFace.UP;
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
return BlockFace.DOWN;
|
||||
}
|
||||
|
||||
return BlockFace.SOUTH;
|
||||
}
|
||||
|
||||
public BlockFace getHexFace(BlockVector v) {
|
||||
int x = v.getBlockX();
|
||||
int y = v.getBlockY();
|
||||
int z = v.getBlockZ();
|
||||
|
||||
if (x == 0 && z == -1) return BlockFace.NORTH;
|
||||
if (x == 1 && z == -2) return BlockFace.NORTH_NORTH_EAST;
|
||||
if (x == 1 && z == -1) return BlockFace.NORTH_EAST;
|
||||
if (x == 2 && z == -1) return BlockFace.EAST_NORTH_EAST;
|
||||
if (x == 1 && z == 0) return BlockFace.EAST;
|
||||
if (x == 2 && z == 1) return BlockFace.EAST_SOUTH_EAST;
|
||||
if (x == 1 && z == 1) return BlockFace.SOUTH_EAST;
|
||||
if (x == 1 && z == 2) return BlockFace.SOUTH_SOUTH_EAST;
|
||||
if (x == 0 && z == 1) return BlockFace.SOUTH;
|
||||
if (x == -1 && z == 2) return BlockFace.SOUTH_SOUTH_WEST;
|
||||
if (x == -1 && z == 1) return BlockFace.SOUTH_WEST;
|
||||
if (x == -2 && z == 1) return BlockFace.WEST_SOUTH_WEST;
|
||||
if (x == -1 && z == 0) return BlockFace.WEST;
|
||||
if (x == -2 && z == -1) return BlockFace.WEST_NORTH_WEST;
|
||||
if (x == -1 && z == -1) return BlockFace.NORTH_WEST;
|
||||
if (x == -1 && z == -2) return BlockFace.NORTH_NORTH_WEST;
|
||||
|
||||
if (y > 0) {
|
||||
return BlockFace.UP;
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
return BlockFace.DOWN;
|
||||
}
|
||||
|
||||
return BlockFace.SOUTH;
|
||||
}
|
||||
|
||||
public BlockFace faceForAxis(Axis axis) {
|
||||
return switch (axis) {
|
||||
case X -> BlockFace.EAST;
|
||||
case Y -> BlockFace.UP;
|
||||
case Z -> BlockFace.NORTH;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public Axis axisFor(BlockFace f) {
|
||||
return switch (f) {
|
||||
case NORTH, SOUTH -> Axis.Z;
|
||||
case EAST, WEST -> Axis.X;
|
||||
default -> Axis.Y;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public Axis axisFor2D(BlockFace f) {
|
||||
return switch (f) {
|
||||
case EAST, WEST, UP, DOWN -> Axis.X;
|
||||
default -> Axis.Z;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public BlockData rotate(BlockData dd, int spinxx, int spinyy, int spinzz) {
|
||||
BlockData d = dd;
|
||||
try {
|
||||
int spinx = (int) (90D * (Math.ceil(Math.abs((spinxx % 360D) / 90D))));
|
||||
int spiny = (int) (90D * (Math.ceil(Math.abs((spinyy % 360D) / 90D))));
|
||||
int spinz = (int) (90D * (Math.ceil(Math.abs((spinzz % 360D) / 90D))));
|
||||
|
||||
if (!canRotate()) {
|
||||
return d;
|
||||
}
|
||||
|
||||
if (d instanceof Directional g) {
|
||||
BlockFace f = g.getFacing();
|
||||
BlockVector bv = new BlockVector(f.getModX(), f.getModY(), f.getModZ());
|
||||
bv = rotate(bv.clone(), spinx, spiny, spinz);
|
||||
BlockFace t = getFace(bv);
|
||||
|
||||
if (g.getFaces().contains(t)) {
|
||||
g.setFacing(t);
|
||||
} else if (!g.getMaterial().isSolid()) {
|
||||
d = null;
|
||||
}
|
||||
} else if (d instanceof Rotatable g) {
|
||||
BlockFace f = g.getRotation();
|
||||
|
||||
BlockVector bv = new BlockVector(f.getModX(), 0, f.getModZ());
|
||||
bv = rotate(bv.clone(), spinx, spiny, spinz);
|
||||
BlockFace face = getHexFace(bv);
|
||||
|
||||
g.setRotation(face);
|
||||
|
||||
} else if (d instanceof Orientable) {
|
||||
BlockFace f = getFace(((Orientable) d).getAxis());
|
||||
BlockVector bv = new BlockVector(f.getModX(), f.getModY(), f.getModZ());
|
||||
bv = rotate(bv.clone(), spinx, spiny, spinz);
|
||||
Axis a = getAxis(bv);
|
||||
|
||||
if (!a.equals(((Orientable) d).getAxis()) && ((Orientable) d).getAxes().contains(a)) {
|
||||
((Orientable) d).setAxis(a);
|
||||
}
|
||||
} else if (d instanceof MultipleFacing g) {
|
||||
List<BlockFace> faces = new KList<>();
|
||||
|
||||
for (BlockFace i : g.getFaces()) {
|
||||
BlockVector bv = new BlockVector(i.getModX(), i.getModY(), i.getModZ());
|
||||
bv = rotate(bv.clone(), spinx, spiny, spinz);
|
||||
BlockFace r = getFace(bv);
|
||||
|
||||
if (g.getAllowedFaces().contains(r)) {
|
||||
faces.add(r);
|
||||
}
|
||||
}
|
||||
|
||||
for (BlockFace i : g.getFaces()) {
|
||||
g.setFace(i, false);
|
||||
}
|
||||
|
||||
for (BlockFace i : faces) {
|
||||
g.setFace(i, true);
|
||||
}
|
||||
} else if (d.getMaterial().equals(Material.NETHER_PORTAL) && d instanceof Orientable g) {
|
||||
//TODO: Fucks up logs
|
||||
BlockFace f = faceForAxis(g.getAxis());
|
||||
BlockVector bv = new BlockVector(f.getModX(), f.getModY(), f.getModZ());
|
||||
bv = rotate(bv.clone(), spinx, spiny, spinz);
|
||||
BlockFace t = getFace(bv);
|
||||
Axis a = !g.getAxes().contains(Axis.Y) ? axisFor(t) : axisFor2D(t);
|
||||
((Orientable) d).setAxis(a);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
public Axis getAxis(BlockVector v) {
|
||||
if (Math.abs(v.getBlockX()) > Math.max(Math.abs(v.getBlockY()), Math.abs(v.getBlockZ()))) {
|
||||
return Axis.X;
|
||||
}
|
||||
|
||||
if (Math.abs(v.getBlockY()) > Math.max(Math.abs(v.getBlockX()), Math.abs(v.getBlockZ()))) {
|
||||
return Axis.Y;
|
||||
}
|
||||
|
||||
if (Math.abs(v.getBlockZ()) > Math.max(Math.abs(v.getBlockX()), Math.abs(v.getBlockY()))) {
|
||||
return Axis.Z;
|
||||
}
|
||||
|
||||
return Axis.Y;
|
||||
}
|
||||
|
||||
private BlockFace getFace(Axis axis) {
|
||||
return switch (axis) {
|
||||
case X -> BlockFace.EAST;
|
||||
case Y -> BlockFace.UP;
|
||||
case Z -> BlockFace.SOUTH;
|
||||
};
|
||||
}
|
||||
|
||||
public IrisPosition rotate(IrisPosition b) {
|
||||
return rotate(b, 0, 0, 0);
|
||||
}
|
||||
|
||||
public IrisPosition rotate(IrisPosition b, int spinx, int spiny, int spinz) {
|
||||
return new IrisPosition(rotate(new BlockVector(b.getX(), b.getY(), b.getZ()), spinx, spiny, spinz));
|
||||
}
|
||||
|
||||
public BlockVector rotate(BlockVector b, int spinx, int spiny, int spinz) {
|
||||
if (!canRotate()) {
|
||||
return b;
|
||||
}
|
||||
|
||||
BlockVector v = b.clone();
|
||||
|
||||
if (canRotateX()) {
|
||||
if (getXAxis().isLocked()) {
|
||||
if (Math.abs(getXAxis().getMax()) % 360D == 180D) {
|
||||
v.setZ(-v.getZ());
|
||||
v.setY(-v.getY());
|
||||
} else if (getXAxis().getMax() % 360D == 90D || getXAxis().getMax() % 360D == -270D) {
|
||||
double z = v.getZ();
|
||||
v.setZ(v.getY());
|
||||
v.setY(-z);
|
||||
} else if (getXAxis().getMax() == -90D || getXAxis().getMax() % 360D == 270D) {
|
||||
double z = v.getZ();
|
||||
v.setZ(-v.getY());
|
||||
v.setY(z);
|
||||
} else {
|
||||
v.rotateAroundX(getXRotation(spinx));
|
||||
}
|
||||
} else {
|
||||
v.rotateAroundX(getXRotation(spinx));
|
||||
}
|
||||
}
|
||||
|
||||
if (canRotateZ()) {
|
||||
if (getZAxis().isLocked()) {
|
||||
if (Math.abs(getZAxis().getMax()) % 360D == 180D) {
|
||||
v.setY(-v.getY());
|
||||
v.setX(-v.getX());
|
||||
} else if (getZAxis().getMax() % 360D == 90D || getZAxis().getMax() % 360D == -270D) {
|
||||
double y = v.getY();
|
||||
v.setY(v.getX());
|
||||
v.setX(-y);
|
||||
} else if (getZAxis().getMax() == -90D || getZAxis().getMax() % 360D == 270D) {
|
||||
double y = v.getY();
|
||||
v.setY(-v.getX());
|
||||
v.setX(y);
|
||||
} else {
|
||||
v.rotateAroundZ(getZRotation(spinz));
|
||||
}
|
||||
} else {
|
||||
v.rotateAroundY(getZRotation(spinz));
|
||||
}
|
||||
}
|
||||
|
||||
if (canRotateY()) {
|
||||
if (getYAxis().isLocked()) {
|
||||
if (Math.abs(getYAxis().getMax()) % 360D == 180D) {
|
||||
v.setX(-v.getX());
|
||||
v.setZ(-v.getZ());
|
||||
} else if (getYAxis().getMax() % 360D == 90D || getYAxis().getMax() % 360D == -270D) {
|
||||
double x = v.getX();
|
||||
v.setX(v.getZ());
|
||||
v.setZ(-x);
|
||||
} else if (getYAxis().getMax() == -90D || getYAxis().getMax() % 360D == 270D) {
|
||||
double x = v.getX();
|
||||
v.setX(-v.getZ());
|
||||
v.setZ(x);
|
||||
} else {
|
||||
v.rotateAroundY(getYRotation(spiny));
|
||||
}
|
||||
} else {
|
||||
v.rotateAroundY(getYRotation(spiny));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public boolean canRotateX() {
|
||||
return enabled && xAxis.isEnabled();
|
||||
}
|
||||
|
||||
public boolean canRotateY() {
|
||||
return enabled && yAxis.isEnabled();
|
||||
}
|
||||
|
||||
public boolean canRotateZ() {
|
||||
return enabled && zAxis.isEnabled();
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean canRotate() {
|
||||
return canRotateX() || canRotateY() || canRotateZ();
|
||||
}
|
||||
}
|
||||
100
src/main/java/com/volmit/iris/engine/object/IrisObjectScale.java
Normal file
100
src/main/java/com/volmit/iris/engine/object/IrisObjectScale.java
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Scale objects")
|
||||
@Data
|
||||
public class IrisObjectScale {
|
||||
@MinNumber(1)
|
||||
@MaxNumber(32)
|
||||
@Desc("Iris Objects are scaled and cached to speed up placements. Because of this extra memory is used, so we evenly distribute variations across the defined scale range, then pick one randomly. If the differences is small, use a lower number. For more possibilities on the scale spectrum, increase this at the cost of memory.")
|
||||
private int variations = 7;
|
||||
|
||||
@MinNumber(0.01)
|
||||
@MaxNumber(50)
|
||||
@Desc("The minimum scale")
|
||||
private double minimumScale = 1;
|
||||
|
||||
@MinNumber(0.01)
|
||||
@MaxNumber(50)
|
||||
@Desc("The maximum height for placement (top of object)")
|
||||
private double maximumScale = 1;
|
||||
|
||||
|
||||
@Desc("If this object is scaled up beyond its origin size, specify a 3D interpolator")
|
||||
private IrisObjectPlacementScaleInterpolator interpolation = IrisObjectPlacementScaleInterpolator.NONE;
|
||||
|
||||
private final transient ConcurrentLinkedHashMap<IrisObject, KList<IrisObject>> cache
|
||||
= new ConcurrentLinkedHashMap.Builder<IrisObject, KList<IrisObject>>()
|
||||
.initialCapacity(64)
|
||||
.maximumWeightedCapacity(64)
|
||||
.concurrencyLevel(32)
|
||||
.build();
|
||||
|
||||
public boolean shouldScale() {
|
||||
return ((minimumScale == maximumScale) && maximumScale == 1) || variations <= 0;
|
||||
}
|
||||
|
||||
public int getMaxSizeFor(int indim) {
|
||||
return (int) (getMaxScale() * indim);
|
||||
}
|
||||
|
||||
public double getMaxScale() {
|
||||
double mx = 0;
|
||||
|
||||
for (double i = minimumScale; i < maximumScale; i += (maximumScale - minimumScale) / (double) (Math.min(variations, 32))) {
|
||||
mx = i;
|
||||
}
|
||||
|
||||
return mx;
|
||||
}
|
||||
|
||||
public IrisObject get(RNG rng, IrisObject origin) {
|
||||
if (shouldScale()) {
|
||||
return origin;
|
||||
}
|
||||
|
||||
return cache.compute(origin, (k, v) -> {
|
||||
if (v != null) {
|
||||
return v;
|
||||
}
|
||||
|
||||
KList<IrisObject> c = new KList<>();
|
||||
for (double i = minimumScale; i < maximumScale; i += (maximumScale - minimumScale) / (double) (Math.min(variations, 32))) {
|
||||
c.add(origin.scaled(i, getInterpolation()));
|
||||
}
|
||||
|
||||
return c;
|
||||
}).getRandom(rng);
|
||||
}
|
||||
|
||||
public boolean canScaleBeyond() {
|
||||
return shouldScale() && maximumScale > 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.MaxNumber;
|
||||
import com.volmit.iris.util.MinNumber;
|
||||
import com.volmit.iris.util.Required;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.util.BlockVector;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Translate objects")
|
||||
@Data
|
||||
public class IrisObjectTranslate {
|
||||
|
||||
@MinNumber(-128) // TODO: WARNING HEIGHT
|
||||
@MaxNumber(128) // TODO: WARNING HEIGHT
|
||||
|
||||
@Desc("The x shift in blocks")
|
||||
private int x = 0;
|
||||
|
||||
@Required
|
||||
@MinNumber(-256) // TODO: WARNING HEIGHT
|
||||
@MaxNumber(256) // TODO: WARNING HEIGHT
|
||||
|
||||
@Desc("The x shift in blocks")
|
||||
private int y = 0;
|
||||
|
||||
@MinNumber(-128) // TODO: WARNING HEIGHT
|
||||
@MaxNumber(128) // TODO: WARNING HEIGHT
|
||||
|
||||
@Desc("Adds an additional amount of height randomly (translateY + rand(0 - yRandom))")
|
||||
private int yRandom = 0;
|
||||
|
||||
@MinNumber(-128) // TODO: WARNING HEIGHT
|
||||
@MaxNumber(128) // TODO: WARNING HEIGHT
|
||||
|
||||
@Desc("The x shift in blocks")
|
||||
private int z = 0;
|
||||
|
||||
public boolean canTranslate() {
|
||||
return x != 0 || y != 0 || z != 0;
|
||||
}
|
||||
|
||||
public BlockVector translate(BlockVector i) {
|
||||
if (canTranslate()) {
|
||||
return (BlockVector) i.clone().add(new BlockVector(x, y, z));
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
public BlockVector translate(BlockVector clone, IrisObjectRotation rotation, int sx, int sy, int sz) {
|
||||
if (canTranslate()) {
|
||||
return (BlockVector) clone.clone().add(rotation.rotate(new BlockVector(x, y, z), sx, sy, sz));
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.BlockVector;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents a position")
|
||||
@Data
|
||||
public class IrisPosition {
|
||||
|
||||
@Desc("The x position")
|
||||
private int x = 0;
|
||||
|
||||
|
||||
@Desc("The y position")
|
||||
private int y = 0;
|
||||
|
||||
|
||||
@Desc("The z position")
|
||||
private int z = 0;
|
||||
|
||||
public IrisPosition(BlockVector bv) {
|
||||
this(bv.getBlockX(), bv.getBlockY(), bv.getBlockZ());
|
||||
}
|
||||
|
||||
public IrisPosition(Location l) {
|
||||
this(l.getBlockX(), l.getBlockY(), l.getBlockZ());
|
||||
}
|
||||
|
||||
public IrisPosition(Vector v) {
|
||||
this(v.getBlockX(), v.getBlockY(), v.getBlockZ());
|
||||
}
|
||||
|
||||
public IrisPosition add(IrisPosition relativePosition) {
|
||||
return new IrisPosition(relativePosition.x + x, relativePosition.y + y, relativePosition.z + z);
|
||||
}
|
||||
|
||||
public IrisPosition sub(IrisPosition relativePosition) {
|
||||
return new IrisPosition(x - relativePosition.x, y - relativePosition.y, z - relativePosition.z);
|
||||
}
|
||||
|
||||
public Location toLocation(World world) {
|
||||
return new Location(world, x, y, z);
|
||||
}
|
||||
|
||||
public IrisPosition copy() {
|
||||
return new IrisPosition(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + getX() + "," + getY() + "," + getZ() + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents a position")
|
||||
@Data
|
||||
public class IrisPosition2D {
|
||||
|
||||
@Desc("The x position")
|
||||
private int x = 0;
|
||||
|
||||
|
||||
@Desc("The z position")
|
||||
private int z = 0;
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.MaxNumber;
|
||||
import com.volmit.iris.util.MinNumber;
|
||||
import com.volmit.iris.util.Required;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
|
||||
@Desc("An iris potion effect")
|
||||
@Data
|
||||
public class IrisPotionEffect {
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The potion effect to apply in this area")
|
||||
private String potionEffect = "";
|
||||
|
||||
@Required
|
||||
@MinNumber(-1)
|
||||
@MaxNumber(1024)
|
||||
@Desc("The Potion Strength or -1 to disable")
|
||||
private int strength = -1;
|
||||
|
||||
@Required
|
||||
@MinNumber(1)
|
||||
@Desc("The time the potion will last for")
|
||||
private int ticks = 200;
|
||||
|
||||
|
||||
@Desc("Is the effect ambient")
|
||||
private boolean ambient = false;
|
||||
|
||||
|
||||
@Desc("Is the effect showing particles")
|
||||
private boolean particles = true;
|
||||
|
||||
private final transient AtomicCache<PotionEffectType> pt = new AtomicCache<>();
|
||||
|
||||
public PotionEffectType getRealType() {
|
||||
return pt.aquire(() ->
|
||||
{
|
||||
PotionEffectType t = PotionEffectType.LUCK;
|
||||
|
||||
if (getPotionEffect().isEmpty()) {
|
||||
return t;
|
||||
}
|
||||
|
||||
try {
|
||||
for (PotionEffectType i : PotionEffectType.values()) {
|
||||
if (i.getName().toUpperCase().replaceAll("\\Q \\E", "_").equals(getPotionEffect())) {
|
||||
t = i;
|
||||
|
||||
return t;
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {Iris.reportError(e);
|
||||
|
||||
}
|
||||
|
||||
Iris.warn("Unknown Potion Effect Type: " + getPotionEffect());
|
||||
|
||||
return t;
|
||||
});
|
||||
}
|
||||
|
||||
public void apply(LivingEntity p) {
|
||||
if (strength > -1) {
|
||||
if (p.hasPotionEffect(getRealType())) {
|
||||
PotionEffect e = p.getPotionEffect(getRealType());
|
||||
if (e.getAmplifier() > strength) {
|
||||
return;
|
||||
}
|
||||
|
||||
p.removePotionEffect(getRealType());
|
||||
}
|
||||
|
||||
p.addPotionEffect(new PotionEffect(getRealType(), ticks, strength, ambient, particles, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
49
src/main/java/com/volmit/iris/engine/object/IrisRange.java
Normal file
49
src/main/java/com/volmit/iris/engine/object/IrisRange.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.RNG;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents a range")
|
||||
@Data
|
||||
public class IrisRange {
|
||||
|
||||
@Desc("The minimum value")
|
||||
private double min = 16;
|
||||
|
||||
|
||||
@Desc("The maximum value")
|
||||
private double max = 32;
|
||||
|
||||
public double get(RNG rng) {
|
||||
if (min == max) {
|
||||
return min;
|
||||
}
|
||||
|
||||
return rng.d(min, max);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.MinNumber;
|
||||
import com.volmit.iris.util.RegistryListObject;
|
||||
import com.volmit.iris.util.Required;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@SuppressWarnings("DefaultAnnotationParam")
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
|
||||
@Desc("Represents a structure tile")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisRareObject {
|
||||
|
||||
@Required
|
||||
@MinNumber(1)
|
||||
@Desc("The rarity is 1 in X")
|
||||
|
||||
private int rarity = 1;
|
||||
|
||||
@RegistryListObject
|
||||
@Required
|
||||
@Desc("The object to place if rarity check passed")
|
||||
|
||||
private String object = "";
|
||||
}
|
||||
557
src/main/java/com/volmit/iris/engine/object/IrisRegion.java
Normal file
557
src/main/java/com/volmit/iris/engine/object/IrisRegion.java
Normal file
@@ -0,0 +1,557 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.noise.CNG;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.core.gui.RenderType;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.data.DataProvider;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import java.awt.Color;
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
@SuppressWarnings("DefaultAnnotationParam")
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Represents an iris region")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisRegion extends IrisRegistrant implements IRare {
|
||||
@MinNumber(2)
|
||||
@Required
|
||||
|
||||
@Desc("The name of the region")
|
||||
private String name = "A Region";
|
||||
|
||||
@ArrayType(min = 1, type = IrisJigsawStructurePlacement.class)
|
||||
@Desc("Jigsaw structures")
|
||||
private KList<IrisJigsawStructurePlacement> jigsawStructures = new KList<>();
|
||||
|
||||
|
||||
@Desc("Add random chances for terrain features")
|
||||
@ArrayType(min = 1, type = IrisFeaturePotential.class)
|
||||
private KList<IrisFeaturePotential> features = new KList<>();
|
||||
|
||||
@ArrayType(min = 1, type = IrisEffect.class)
|
||||
@Desc("Effects are ambient effects such as potion effects, random sounds, or even particles around each player. All of these effects are played via packets so two players won't see/hear each others effects.\nDue to performance reasons, effects will play arround the player even if where the effect was played is no longer in the biome the player is in.")
|
||||
private KList<IrisEffect> effects = new KList<>();
|
||||
|
||||
|
||||
@Desc("Entity spawns to override or add to this region")
|
||||
@ArrayType(min = 1, type = IrisEntitySpawnOverride.class)
|
||||
private KList<IrisEntitySpawnOverride> entitySpawnOverrides = new KList<>();
|
||||
|
||||
|
||||
@Desc("Entity spawns during generation")
|
||||
@ArrayType(min = 1, type = IrisEntityInitialSpawn.class)
|
||||
private KList<IrisEntityInitialSpawn> entityInitialSpawns = new KList<>();
|
||||
|
||||
@MinNumber(1)
|
||||
@MaxNumber(128)
|
||||
@Desc("The rarity of the region")
|
||||
private int rarity = 1;
|
||||
|
||||
@ArrayType(min = 1, type = IrisBlockDrops.class)
|
||||
@Desc("Define custom block drops for this region")
|
||||
private KList<IrisBlockDrops> blockDrops = new KList<>();
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@MaxNumber(1)
|
||||
@Desc("The shore ration (How much percent of land should be a shore)")
|
||||
private double shoreRatio = 0.13;
|
||||
|
||||
@ArrayType(min = 1, type = IrisObjectPlacement.class)
|
||||
@Desc("Objects define what schematics (iob files) iris will place in this region")
|
||||
private KList<IrisObjectPlacement> objects = new KList<>();
|
||||
|
||||
@MinNumber(0)
|
||||
@Desc("The min shore height")
|
||||
private double shoreHeightMin = 1.2;
|
||||
|
||||
|
||||
@Desc("Reference loot tables in this area")
|
||||
private IrisLootReference loot = new IrisLootReference();
|
||||
|
||||
@MinNumber(0)
|
||||
@Desc("The the max shore height")
|
||||
private double shoreHeightMax = 3.2;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@Desc("The varience of the shore height")
|
||||
private double shoreHeightZoom = 3.14;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@Desc("How large land biomes are in this region")
|
||||
private double landBiomeZoom = 1;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@Desc("How large shore biomes are in this region")
|
||||
private double shoreBiomeZoom = 1;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@Desc("How large lake biomes are in this region")
|
||||
private double lakeBiomeZoom = 1;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@Desc("How large river biomes are in this region")
|
||||
private double riverBiomeZoom = 1;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@Desc("How large sea biomes are in this region")
|
||||
private double seaBiomeZoom = 1;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@Desc("How large cave biomes are in this region")
|
||||
private double caveBiomeZoom = 1;
|
||||
|
||||
@MinNumber(0.0001)
|
||||
@MaxNumber(1)
|
||||
@Desc("The biome implosion ratio, how much to implode biomes into children (chance)")
|
||||
private double biomeImplosionRatio = 0.4;
|
||||
|
||||
@RegistryListBiome
|
||||
@Required
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
@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> landBiomes = new KList<>();
|
||||
|
||||
@RegistryListBiome
|
||||
@Required
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
@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> seaBiomes = new KList<>();
|
||||
|
||||
@RegistryListBiome
|
||||
@Required
|
||||
@ArrayType(min = 1, type = String.class)
|
||||
@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)
|
||||
@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)
|
||||
@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)
|
||||
@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> caveBiomes = new KList<>();
|
||||
|
||||
@ArrayType(min = 1, type = IrisRegionRidge.class)
|
||||
@Desc("Ridge biomes create a vein-like network like rivers through this region")
|
||||
private KList<IrisRegionRidge> ridgeBiomes = new KList<>();
|
||||
|
||||
@ArrayType(min = 1, type = IrisRegionSpot.class)
|
||||
@Desc("Spot biomes splotch themselves across this region like lakes")
|
||||
private KList<IrisRegionSpot> spotBiomes = new KList<>();
|
||||
|
||||
@ArrayType(min = 1, type = IrisDepositGenerator.class)
|
||||
@Desc("Define regional deposit generators that add onto the global deposit generators")
|
||||
private KList<IrisDepositGenerator> deposits = new KList<>();
|
||||
|
||||
|
||||
@Desc("The style of rivers")
|
||||
private IrisGeneratorStyle riverStyle = NoiseStyle.VASCULAR_THIN.style().zoomed(7.77);
|
||||
|
||||
|
||||
@Desc("The style of lakes")
|
||||
private IrisGeneratorStyle lakeStyle = NoiseStyle.CELLULAR_IRIS_THICK.style();
|
||||
|
||||
|
||||
@Desc("The style of river chances")
|
||||
private IrisGeneratorStyle riverChanceStyle = NoiseStyle.SIMPLEX.style().zoomed(4);
|
||||
|
||||
|
||||
@Desc("Generate lakes in this region")
|
||||
private boolean lakes = true;
|
||||
|
||||
|
||||
@Desc("Generate rivers in this region")
|
||||
private boolean rivers = true;
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("Generate lakes in this region")
|
||||
private int lakeRarity = 22;
|
||||
|
||||
@MinNumber(1)
|
||||
@Desc("Generate rivers in this region")
|
||||
private int riverRarity = 3;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1)
|
||||
@Desc("Generate rivers in this region")
|
||||
private double riverThickness = 0.1;
|
||||
|
||||
|
||||
@Desc("A color for visualizing this region with a color. I.e. #F13AF5. This will show up on the map.")
|
||||
private String color = null;
|
||||
|
||||
private final transient AtomicCache<KList<IrisObjectPlacement>> surfaceObjectsCache = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<IrisObjectPlacement>> carveObjectsCache = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<String>> cacheRidge = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<String>> cacheSpot = new AtomicCache<>();
|
||||
private final transient AtomicCache<CNG> shoreHeightGenerator = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<IrisBiome>> realLandBiomes = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<IrisBiome>> realLakeBiomes = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<IrisBiome>> realRiverBiomes = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<IrisBiome>> realSeaBiomes = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<IrisBiome>> realShoreBiomes = new AtomicCache<>();
|
||||
private final transient AtomicCache<KList<IrisBiome>> realCaveBiomes = new AtomicCache<>();
|
||||
private final transient AtomicCache<CNG> lakeGen = new AtomicCache<>();
|
||||
private final transient AtomicCache<CNG> riverGen = new AtomicCache<>();
|
||||
private final transient AtomicCache<CNG> riverChanceGen = new AtomicCache<>();
|
||||
private final transient AtomicCache<Color> cacheColor = new AtomicCache<>();
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public KList<IrisObjectPlacement> getSurfaceObjects() {
|
||||
return getSurfaceObjectsCache().aquire(() ->
|
||||
{
|
||||
KList<IrisObjectPlacement> o = getObjects().copy();
|
||||
|
||||
for (IrisObjectPlacement i : o.copy()) {
|
||||
if (!i.getCarvingSupport().supportsSurface()) {
|
||||
o.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
return o;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<IrisObjectPlacement> getCarvingObjects() {
|
||||
return getCarveObjectsCache().aquire(() ->
|
||||
{
|
||||
KList<IrisObjectPlacement> o = getObjects().copy();
|
||||
|
||||
for (IrisObjectPlacement i : o.copy()) {
|
||||
if (!i.getCarvingSupport().supportsCarving()) {
|
||||
o.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
return o;
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return getRiverGen().aquire(() -> getRiverStyle().create(rng)).fitDouble(0, 1, x, z) < getRiverThickness();
|
||||
}
|
||||
|
||||
public boolean isLake(RNG rng, double x, double z) {
|
||||
if (!isLakes()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getLakeBiomes().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getLakeGen().aquire(() -> getLakeStyle().create(rng)).fit(1, getLakeRarity(), x, z) == 1;
|
||||
}
|
||||
|
||||
public double getBiomeZoom(InferredType t) {
|
||||
switch (t) {
|
||||
case CAVE:
|
||||
return caveBiomeZoom;
|
||||
case LAKE:
|
||||
return lakeBiomeZoom;
|
||||
case RIVER:
|
||||
return riverBiomeZoom;
|
||||
case LAND:
|
||||
return landBiomeZoom;
|
||||
case SEA:
|
||||
return seaBiomeZoom;
|
||||
case SHORE:
|
||||
return shoreBiomeZoom;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public KList<String> getRidgeBiomeKeys() {
|
||||
return cacheRidge.aquire(() ->
|
||||
{
|
||||
KList<String> cacheRidge = new KList<>();
|
||||
ridgeBiomes.forEach((i) -> cacheRidge.add(i.getBiome()));
|
||||
|
||||
return cacheRidge;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<String> getSpotBiomeKeys() {
|
||||
return cacheSpot.aquire(() ->
|
||||
{
|
||||
KList<String> cacheSpot = new KList<>();
|
||||
spotBiomes.forEach((i) -> cacheSpot.add(i.getBiome()));
|
||||
return cacheSpot;
|
||||
});
|
||||
}
|
||||
|
||||
public CNG getShoreHeightGenerator() {
|
||||
return shoreHeightGenerator.aquire(() ->
|
||||
CNG.signature(new RNG((long) (getName().length() + getLandBiomeZoom() + getLandBiomes().size() + 3458612))));
|
||||
}
|
||||
|
||||
public double getShoreHeight(double x, double z) {
|
||||
return getShoreHeightGenerator().fitDouble(shoreHeightMin, shoreHeightMax, x / shoreHeightZoom, z / shoreHeightZoom);
|
||||
}
|
||||
|
||||
public KSet<String> getAllBiomeIds() {
|
||||
KSet<String> names = new KSet<>();
|
||||
names.addAll(landBiomes);
|
||||
names.addAll(caveBiomes);
|
||||
names.addAll(seaBiomes);
|
||||
names.addAll(shoreBiomes);
|
||||
names.addAll(riverBiomes);
|
||||
names.addAll(lakeBiomes);
|
||||
spotBiomes.forEach((i) -> names.add(i.getBiome()));
|
||||
ridgeBiomes.forEach((i) -> names.add(i.getBiome()));
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getAllBiomes(DataProvider g) {
|
||||
KMap<String, IrisBiome> b = new KMap<>();
|
||||
KSet<String> names = getAllBiomeIds();
|
||||
|
||||
while (!names.isEmpty()) {
|
||||
for (String i : new KList<>(names)) {
|
||||
if (b.containsKey(i)) {
|
||||
names.remove(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
IrisBiome biome = g.getData().getBiomeLoader().load(i);
|
||||
|
||||
names.remove(i);
|
||||
if (biome == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
names.add(biome.getCarvingBiome());
|
||||
b.put(biome.getLoadKey(), biome);
|
||||
names.addAll(biome.getChildren());
|
||||
}
|
||||
}
|
||||
|
||||
return b.v();
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getBiomes(DataProvider g, InferredType type) {
|
||||
if (type.equals(InferredType.LAND)) {
|
||||
return getRealLandBiomes(g);
|
||||
} else if (type.equals(InferredType.SEA)) {
|
||||
return getRealSeaBiomes(g);
|
||||
} else if (type.equals(InferredType.SHORE)) {
|
||||
return getRealShoreBiomes(g);
|
||||
} else if (type.equals(InferredType.CAVE)) {
|
||||
return getRealCaveBiomes(g);
|
||||
} else if (type.equals(InferredType.LAKE)) {
|
||||
return getRealLakeBiomes(g);
|
||||
} else if (type.equals(InferredType.RIVER)) {
|
||||
return getRealRiverBiomes(g);
|
||||
}
|
||||
|
||||
return new KList<>();
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getRealCaveBiomes(DataProvider g) {
|
||||
return realCaveBiomes.aquire(() ->
|
||||
{
|
||||
KList<IrisBiome> realCaveBiomes = new KList<>();
|
||||
|
||||
for (String i : getCaveBiomes()) {
|
||||
realCaveBiomes.add(g.getData().getBiomeLoader().load(i));
|
||||
}
|
||||
|
||||
return realCaveBiomes;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getRealLakeBiomes(DataProvider g) {
|
||||
return realLakeBiomes.aquire(() ->
|
||||
{
|
||||
KList<IrisBiome> realLakeBiomes = new KList<>();
|
||||
|
||||
for (String i : getLakeBiomes()) {
|
||||
realLakeBiomes.add(g.getData().getBiomeLoader().load(i));
|
||||
}
|
||||
|
||||
return realLakeBiomes;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getRealRiverBiomes(DataProvider g) {
|
||||
return realRiverBiomes.aquire(() ->
|
||||
{
|
||||
KList<IrisBiome> realRiverBiomes = new KList<>();
|
||||
|
||||
for (String i : getRiverBiomes()) {
|
||||
realRiverBiomes.add(g.getData().getBiomeLoader().load(i));
|
||||
}
|
||||
|
||||
return realRiverBiomes;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getRealShoreBiomes(DataProvider g) {
|
||||
return realShoreBiomes.aquire(() ->
|
||||
{
|
||||
KList<IrisBiome> realShoreBiomes = new KList<>();
|
||||
|
||||
for (String i : getShoreBiomes()) {
|
||||
realShoreBiomes.add(g.getData().getBiomeLoader().load(i));
|
||||
}
|
||||
|
||||
return realShoreBiomes;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getRealSeaBiomes(DataProvider g) {
|
||||
return realSeaBiomes.aquire(() ->
|
||||
{
|
||||
KList<IrisBiome> realSeaBiomes = new KList<>();
|
||||
|
||||
for (String i : getSeaBiomes()) {
|
||||
realSeaBiomes.add(g.getData().getBiomeLoader().load(i));
|
||||
}
|
||||
|
||||
return realSeaBiomes;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getRealLandBiomes(DataProvider g) {
|
||||
return realLandBiomes.aquire(() ->
|
||||
{
|
||||
KList<IrisBiome> realLandBiomes = new KList<>();
|
||||
|
||||
for (String i : getLandBiomes()) {
|
||||
realLandBiomes.add(g.getData().getBiomeLoader().load(i));
|
||||
}
|
||||
|
||||
return realLandBiomes;
|
||||
});
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getAllAnyBiomes() {
|
||||
KMap<String, IrisBiome> b = new KMap<>();
|
||||
KSet<String> names = new KSet<>();
|
||||
names.addAll(landBiomes);
|
||||
names.addAll(caveBiomes);
|
||||
names.addAll(seaBiomes);
|
||||
names.addAll(shoreBiomes);
|
||||
names.addAll(riverBiomes);
|
||||
names.addAll(lakeBiomes);
|
||||
spotBiomes.forEach((i) -> names.add(i.getBiome()));
|
||||
ridgeBiomes.forEach((i) -> names.add(i.getBiome()));
|
||||
|
||||
while (!names.isEmpty()) {
|
||||
for (String i : new KList<>(names)) {
|
||||
if (b.containsKey(i)) {
|
||||
names.remove(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
IrisBiome biome = IrisDataManager.loadAnyBiome(i);
|
||||
|
||||
names.remove(i);
|
||||
if (biome == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
names.add(biome.getCarvingBiome());
|
||||
b.put(biome.getLoadKey(), biome);
|
||||
names.addAll(biome.getChildren());
|
||||
}
|
||||
}
|
||||
|
||||
return b.v();
|
||||
}
|
||||
|
||||
public Color getColor(DataProvider dataProvider, RenderType type) {
|
||||
return this.cacheColor.aquire(() -> {
|
||||
if (this.color == null) {
|
||||
Random rand = new Random(getName().hashCode() + getAllBiomeIds().hashCode());
|
||||
RandomColor randomColor = new RandomColor(rand);
|
||||
|
||||
KList<IrisBiome> biomes = getRealLandBiomes(dataProvider);
|
||||
|
||||
while (biomes.size() > 0) {
|
||||
int index = rand.nextInt(biomes.size());
|
||||
IrisBiome biome = biomes.get(index);
|
||||
|
||||
if (biome.getVanillaDerivative() != null) {
|
||||
RandomColor.Color col = VanillaBiomeMap.getColorType(biome.getVanillaDerivative());
|
||||
RandomColor.Luminosity lum = VanillaBiomeMap.getColorLuminosity(biome.getVanillaDerivative());
|
||||
RandomColor.SaturationType sat = VanillaBiomeMap.getColorSaturatiom(biome.getVanillaDerivative());
|
||||
int newColorI = randomColor.randomColor(col, col == RandomColor.Color.MONOCHROME ? RandomColor.SaturationType.MONOCHROME : sat, lum);
|
||||
return new Color(newColorI);
|
||||
}
|
||||
|
||||
biomes.remove(index);
|
||||
}
|
||||
|
||||
Iris.warn("Couldn't find a suitable color for region " + getName());
|
||||
return new Color(new RandomColor(rand).randomColor());
|
||||
}
|
||||
|
||||
try {
|
||||
return Color.decode(this.color);
|
||||
} catch (NumberFormatException e) {
|
||||
Iris.warn("Could not parse color \"" + this.color + "\" for region " + getName());
|
||||
return Color.WHITE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void pickRandomColor(DataProvider data) {
|
||||
|
||||
}
|
||||
}
|
||||
132
src/main/java/com/volmit/iris/engine/object/IrisRegionRidge.java
Normal file
132
src/main/java/com/volmit/iris/engine/object/IrisRegionRidge.java
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.noise.CellGenerator;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("A ridge config")
|
||||
@Data
|
||||
public class IrisRegionRidge {
|
||||
|
||||
@RegistryListBiome
|
||||
@Required
|
||||
|
||||
@Desc("The biome name")
|
||||
private String biome = "";
|
||||
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("The type this biome should override (land sea or shore)")
|
||||
private InferredType type = InferredType.LAND;
|
||||
|
||||
|
||||
@Desc("What type this spot is (i.e. target SEA but as LAND) like an island. Default matches the target type")
|
||||
private InferredType as = InferredType.DEFER;
|
||||
|
||||
|
||||
@Desc("Use the distance from cell value to add or remove noise value. (Forces depth or height)")
|
||||
private double noiseMultiplier = 0;
|
||||
|
||||
|
||||
@Required
|
||||
@MinNumber(0)
|
||||
@MaxNumber(1)
|
||||
@Desc("The chance this biome will be placed in a given spot")
|
||||
private double chance = 0.75;
|
||||
|
||||
|
||||
@MinNumber(0)
|
||||
@Desc("The scale of the biome ridge. Higher values = wider veins & bigger connected cells")
|
||||
private double scale = 5;
|
||||
|
||||
|
||||
@Desc("The chance scale (cell chances)")
|
||||
private double chanceScale = 4;
|
||||
|
||||
|
||||
@MinNumber(0)
|
||||
@Desc("The shuffle, how 'natural' this looks. Compared to pure polygons")
|
||||
private double shuffle = 16;
|
||||
|
||||
|
||||
@MinNumber(0)
|
||||
@Desc("The chance shuffle (polygon cell chances)")
|
||||
private double chanceShuffle = 128;
|
||||
|
||||
|
||||
@MinNumber(0)
|
||||
@Desc("The thickness of the vein")
|
||||
private double thickness = 0.125;
|
||||
|
||||
|
||||
@Desc("If the noise multiplier is below zero, what should the air be filled with?")
|
||||
private IrisBiomePaletteLayer air = new IrisBiomePaletteLayer().zero();
|
||||
|
||||
private final transient AtomicCache<CellGenerator> spot = new AtomicCache<>();
|
||||
private final transient AtomicCache<CellGenerator> ridge = new AtomicCache<>();
|
||||
|
||||
|
||||
public CellGenerator getSpotGenerator(RNG rng) {
|
||||
return spot.aquire(() ->
|
||||
{
|
||||
CellGenerator spot = new CellGenerator(rng.nextParallelRNG((int) (198523 * getChance())));
|
||||
spot.setCellScale(chanceScale);
|
||||
spot.setShuffle(shuffle);
|
||||
return spot;
|
||||
});
|
||||
}
|
||||
|
||||
public CellGenerator getRidgeGenerator(RNG rng) {
|
||||
return spot.aquire(() ->
|
||||
{
|
||||
CellGenerator ridge = new CellGenerator(rng.nextParallelRNG((int) (465583 * getChance())));
|
||||
ridge.setCellScale(scale);
|
||||
ridge.setShuffle(shuffle);
|
||||
return ridge;
|
||||
});
|
||||
}
|
||||
|
||||
public double getRidgeHeight(RNG rng, double x, double z) {
|
||||
if (getNoiseMultiplier() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return getSpotGenerator(rng).getDistance(x, z) * getRidgeGenerator(rng).getDistance(x, z) * getNoiseMultiplier();
|
||||
}
|
||||
|
||||
public boolean isRidge(RNG rng, double x, double z) {
|
||||
if (chance < 1) {
|
||||
if (getSpotGenerator(rng).getIndex(x, z, 1000) > chance * 1000) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return getRidgeGenerator(rng).getDistance(x, z) <= thickness;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.noise.CellGenerator;
|
||||
import com.volmit.iris.engine.cache.AtomicCache;
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("A spot config")
|
||||
@Data
|
||||
public class IrisRegionSpot {
|
||||
|
||||
@RegistryListBiome
|
||||
@Required
|
||||
|
||||
@Desc("The biome to be placed")
|
||||
private String biome = "";
|
||||
|
||||
@Required
|
||||
|
||||
@Desc("Where this spot overrides. Land sea or shore")
|
||||
private InferredType type = InferredType.LAND;
|
||||
|
||||
|
||||
@Desc("What type this spot is (i.e. target SEA but as LAND) like an island. Default matches the target type")
|
||||
private InferredType as = InferredType.DEFER;
|
||||
|
||||
|
||||
@Desc("Use the distance from cell value to add or remove noise value. (Forces depth or height)")
|
||||
private double noiseMultiplier = 0;
|
||||
|
||||
@MinNumber(0)
|
||||
@Desc("The scale of splotches")
|
||||
private double scale = 1;
|
||||
|
||||
@Required
|
||||
@MinNumber(1)
|
||||
@Desc("Rarity is how often this splotch appears. higher = less often")
|
||||
private double rarity = 1;
|
||||
|
||||
@MinNumber(0)
|
||||
@Desc("The shuffle or how natural the splotch looks like (anti-polygon)")
|
||||
private double shuffle = 128;
|
||||
|
||||
|
||||
@Desc("If the noise multiplier is below zero, what should the air be filled with?")
|
||||
private IrisBiomePaletteLayer air = new IrisBiomePaletteLayer().zero();
|
||||
|
||||
private final transient AtomicCache<CellGenerator> spot = new AtomicCache<>();
|
||||
|
||||
public CellGenerator getSpotGenerator(RNG rng) {
|
||||
return spot.aquire(() ->
|
||||
{
|
||||
CellGenerator spot = new CellGenerator(rng.nextParallelRNG((int) (168583 * (shuffle + 102) + rarity + (scale * 10465) + biome.length() + type.ordinal() + as.ordinal())));
|
||||
spot.setCellScale(scale);
|
||||
spot.setShuffle(shuffle);
|
||||
return spot;
|
||||
});
|
||||
}
|
||||
|
||||
public double getSpotHeight(RNG rng, double x, double z) {
|
||||
if (getNoiseMultiplier() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return getSpotGenerator(rng).getDistance(x, z) * getNoiseMultiplier();
|
||||
}
|
||||
|
||||
public boolean isSpot(RNG rng, double x, double z) {
|
||||
return getSpotGenerator(rng).getIndex(x, z, (int) (Math.round(rarity) + 8)) == (int) ((Math.round(rarity) + 8) / 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import lombok.Data;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
|
||||
@Data
|
||||
public class IrisRegistrant {
|
||||
private transient IrisDataManager loader;
|
||||
|
||||
private transient String loadKey;
|
||||
|
||||
private transient File loadFile;
|
||||
|
||||
public File openInVSCode()
|
||||
{
|
||||
try {
|
||||
Desktop.getDesktop().open(getLoadFile());
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
return getLoadFile();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("This represents a generator with a min and max height")
|
||||
@Data
|
||||
public class IrisShapedGeneratorStyle {
|
||||
@Required
|
||||
|
||||
@Desc("The generator id")
|
||||
|
||||
private IrisGeneratorStyle generator = new IrisGeneratorStyle(NoiseStyle.IRIS);
|
||||
|
||||
@Required
|
||||
@MinNumber(-256) // TODO: WARNING HEIGHT
|
||||
@MaxNumber(256) // TODO: WARNING HEIGHT
|
||||
|
||||
|
||||
@Desc("The min block value")
|
||||
private int min = 0;
|
||||
|
||||
@Required
|
||||
@MinNumber(-256) // TODO: WARNING HEIGHT
|
||||
@MaxNumber(256) // TODO: WARNING HEIGHT
|
||||
|
||||
@Desc("The max block value")
|
||||
private int max = 0;
|
||||
|
||||
public double get(RNG rng, double... dim) {
|
||||
return generator.create(rng).fitDouble(min, max, dim);
|
||||
}
|
||||
|
||||
public IrisShapedGeneratorStyle(NoiseStyle style, int min, int max) {
|
||||
this(style);
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public IrisShapedGeneratorStyle(NoiseStyle style) {
|
||||
this.generator = new IrisGeneratorStyle(style);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.MaxNumber;
|
||||
import com.volmit.iris.util.MinNumber;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Translate objects")
|
||||
@Data
|
||||
public class IrisSlopeClip {
|
||||
@MinNumber(0)
|
||||
@MaxNumber(255)
|
||||
@Desc("The minimum slope for placement")
|
||||
private double minimumSlope = 0;
|
||||
|
||||
@MinNumber(0)
|
||||
@MaxNumber(255)
|
||||
@Desc("The maximum slope for placement")
|
||||
private double maximumSlope = 10;
|
||||
|
||||
public boolean isDefault() {
|
||||
return minimumSlope <= 0 && maximumSlope >= 10;
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean isValid(double slope) {
|
||||
if (isDefault()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !(minimumSlope > slope) && !(maximumSlope < slope);
|
||||
}
|
||||
}
|
||||
36
src/main/java/com/volmit/iris/engine/object/LootMode.java
Normal file
36
src/main/java/com/volmit/iris/engine/object/LootMode.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
|
||||
@Desc("A loot mode is used to descrive what to do with the existing loot layers before adding this loot. Using ADD will simply add this table to the building list of tables (i.e. add dimension tables, region tables then biome tables). By using clear or replace, you remove the parent tables before and add just your tables.")
|
||||
public enum LootMode {
|
||||
@Desc("Add to the existing parent loot tables")
|
||||
|
||||
ADD,
|
||||
|
||||
@Desc("Clear all loot tables then add this table")
|
||||
|
||||
CLEAR,
|
||||
|
||||
@Desc("Replace all loot tables with this table (same as clear)")
|
||||
|
||||
REPLACE
|
||||
}
|
||||
474
src/main/java/com/volmit/iris/engine/object/NoiseStyle.java
Normal file
474
src/main/java/com/volmit/iris/engine/object/NoiseStyle.java
Normal file
@@ -0,0 +1,474 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.noise.CNG;
|
||||
import com.volmit.iris.engine.noise.CNGFactory;
|
||||
import com.volmit.iris.engine.noise.NoiseType;
|
||||
import com.volmit.iris.engine.stream.ProceduralStream;
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.RNG;
|
||||
|
||||
@Desc("Styles of noise")
|
||||
|
||||
public enum NoiseStyle {
|
||||
@Desc("White Noise is like static. Useful for block scattering but not terrain.")
|
||||
|
||||
STATIC(rng -> new CNG(rng, NoiseType.WHITE, 1D, 1)),
|
||||
|
||||
@Desc("Wispy Perlin-looking simplex noise. The 'iris' style noise.")
|
||||
|
||||
IRIS(rng -> CNG.signature(rng).scale(1)),
|
||||
|
||||
@Desc("Classic German Engineering")
|
||||
|
||||
NOWHERE(rng -> CNG.signaturePerlin(rng).scale(0.776).bake()),
|
||||
|
||||
@Desc("Classic German Engineering")
|
||||
|
||||
NOWHERE_CELLULAR(rng -> CNG.signaturePerlin(rng, NoiseType.CELLULAR).scale(1).bake()),
|
||||
|
||||
@Desc("Classic German Engineering")
|
||||
|
||||
NOWHERE_SIMPLEX(rng -> CNG.signaturePerlin(rng, NoiseType.SIMPLEX).scale(1).bake()),
|
||||
|
||||
@Desc("Classic German Engineering")
|
||||
|
||||
NOWHERE_GLOB(rng -> CNG.signaturePerlin(rng, NoiseType.GLOB).scale(1).bake()),
|
||||
|
||||
@Desc("Classic German Engineering")
|
||||
|
||||
NOWHERE_VASCULAR(rng -> CNG.signaturePerlin(rng, NoiseType.VASCULAR).scale(1).bake()),
|
||||
|
||||
@Desc("Classic German Engineering")
|
||||
|
||||
NOWHERE_CUBIC(rng -> CNG.signaturePerlin(rng, NoiseType.CUBIC).scale(1).bake()),
|
||||
|
||||
@Desc("Classic German Engineering")
|
||||
|
||||
NOWHERE_SUPERFRACTAL(rng -> CNG.signaturePerlin(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX).scale(1).bake()),
|
||||
|
||||
@Desc("Classic German Engineering")
|
||||
|
||||
NOWHERE_FRACTAL(rng -> CNG.signaturePerlin(rng, NoiseType.FRACTAL_BILLOW_PERLIN).scale(1).bake()),
|
||||
|
||||
@Desc("Wispy Perlin-looking simplex noise. The 'iris' style noise.")
|
||||
|
||||
IRIS_DOUBLE(rng -> CNG.signatureDouble(rng).scale(1)),
|
||||
|
||||
@Desc("Wispy Perlin-looking simplex noise. The 'iris' style noise.")
|
||||
|
||||
IRIS_THICK(rng -> CNG.signatureThick(rng).scale(1)),
|
||||
|
||||
@Desc("Wispy Perlin-looking simplex noise. The 'iris' style noise.")
|
||||
|
||||
IRIS_HALF(rng -> CNG.signatureHalf(rng).scale(1)),
|
||||
|
||||
@Desc("Basic, Smooth & Fast Simplex noise.")
|
||||
|
||||
SIMPLEX(rng -> new CNG(rng, 1D, 1).scale(1)),
|
||||
|
||||
@Desc("Very Detailed smoke using simplex fractured with fractal billow simplex at high octaves.")
|
||||
|
||||
FRACTAL_SMOKE(rng -> new CNG(rng, 1D, 1).fractureWith(new CNG(rng.nextParallelRNG(1), NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 8).scale(0.2), 1000).scale(0.34)),
|
||||
|
||||
@Desc("Thinner Veins.")
|
||||
|
||||
VASCULAR_THIN(rng -> new CNG(rng.nextParallelRNG(1), NoiseType.VASCULAR, 1D, 1).scale(1).pow(0.65)),
|
||||
|
||||
@Desc("Cells of simplex noise")
|
||||
|
||||
SIMPLEX_CELLS(rng -> new CNG(rng.nextParallelRNG(1), NoiseType.SIMPLEX, 1D, 1).scale(1).fractureWith(new CNG(rng.nextParallelRNG(8), NoiseType.CELLULAR, 1D, 1).scale(1), 200)),
|
||||
|
||||
@Desc("Veins of simplex noise")
|
||||
|
||||
SIMPLEX_VASCULAR(rng -> new CNG(rng.nextParallelRNG(1), NoiseType.SIMPLEX, 1D, 1).scale(1).fractureWith(new CNG(rng.nextParallelRNG(8), NoiseType.VASCULAR, 1D, 1).scale(1), 200)),
|
||||
|
||||
@Desc("Very Detailed fluid using simplex fractured with fractal billow simplex at high octaves.")
|
||||
|
||||
FRACTAL_WATER(rng -> new CNG(rng, 1D, 1).fractureWith(new CNG(rng.nextParallelRNG(1), NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 9).scale(0.03), 9900).scale(1.14)),
|
||||
|
||||
@Desc("Perlin. Like simplex but more natural")
|
||||
|
||||
PERLIN(rng -> new CNG(rng, NoiseType.PERLIN, 1D, 1).scale(1.15)),
|
||||
|
||||
@Desc("Perlin. Like simplex but more natural")
|
||||
|
||||
PERLIN_IRIS(rng -> CNG.signature(rng, NoiseType.PERLIN).scale(1.47)),
|
||||
|
||||
@Desc("Perlin. Like simplex but more natural")
|
||||
|
||||
PERLIN_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.PERLIN).scale(1.47)),
|
||||
|
||||
@Desc("Perlin. Like simplex but more natural")
|
||||
|
||||
PERLIN_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.PERLIN).scale(1.47)),
|
||||
|
||||
@Desc("Perlin. Like simplex but more natural")
|
||||
|
||||
PERLIN_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.PERLIN).scale(1.47)),
|
||||
|
||||
@Desc("Billow Fractal Perlin Noise.")
|
||||
|
||||
FRACTAL_BILLOW_PERLIN(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_PERLIN, 1D, 1).scale(1.47)),
|
||||
|
||||
@Desc("Billow Fractal Perlin Noise. 2 Octaves")
|
||||
|
||||
BIOCTAVE_FRACTAL_BILLOW_PERLIN(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_PERLIN, 1D, 2).scale(1.17)),
|
||||
|
||||
@Desc("Billow Fractal Simplex Noise. Single octave.")
|
||||
|
||||
FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 1)),
|
||||
|
||||
@Desc("FBM Fractal Simplex Noise. Single octave.")
|
||||
|
||||
FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 1)),
|
||||
|
||||
@Desc("Billow Fractal Iris Noise. Single octave.")
|
||||
|
||||
FRACTAL_BILLOW_IRIS(rng -> CNG.signature(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX)),
|
||||
|
||||
@Desc("FBM Fractal Iris Noise. Single octave.")
|
||||
|
||||
FRACTAL_FBM_IRIS(rng -> CNG.signature(rng, NoiseType.FRACTAL_FBM_SIMPLEX)),
|
||||
|
||||
@Desc("Billow Fractal Iris Noise. Single octave.")
|
||||
|
||||
FRACTAL_BILLOW_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX)),
|
||||
|
||||
@Desc("FBM Fractal Iris Noise. Single octave.")
|
||||
|
||||
FRACTAL_FBM_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.FRACTAL_FBM_SIMPLEX)),
|
||||
|
||||
@Desc("Billow Fractal Iris Noise. Single octave.")
|
||||
|
||||
FRACTAL_BILLOW_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX)),
|
||||
|
||||
@Desc("FBM Fractal Iris Noise. Single octave.")
|
||||
|
||||
FRACTAL_FBM_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.FRACTAL_FBM_SIMPLEX)),
|
||||
|
||||
@Desc("Rigid Multi Fractal Simplex Noise. Single octave.")
|
||||
|
||||
FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 1)),
|
||||
|
||||
@Desc("Billow Fractal Simplex Noise. 2 octaves.")
|
||||
|
||||
BIOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 2)),
|
||||
|
||||
@Desc("FBM Fractal Simplex Noise. 2 octaves.")
|
||||
|
||||
BIOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 2)),
|
||||
|
||||
@Desc("Rigid Multi Fractal Simplex Noise. 2 octaves.")
|
||||
|
||||
BIOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 2)),
|
||||
|
||||
@Desc("Rigid Multi Fractal Simplex Noise. 3 octaves.")
|
||||
|
||||
TRIOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 3)),
|
||||
|
||||
@Desc("Billow Fractal Simplex Noise. 3 octaves.")
|
||||
|
||||
TRIOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 3)),
|
||||
|
||||
@Desc("FBM Fractal Simplex Noise. 3 octaves.")
|
||||
|
||||
TRIOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 3)),
|
||||
|
||||
@Desc("Rigid Multi Fractal Simplex Noise. 4 octaves.")
|
||||
|
||||
QUADOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 4)),
|
||||
|
||||
@Desc("Billow Fractal Simplex Noise. 4 octaves.")
|
||||
|
||||
QUADOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 4)),
|
||||
|
||||
@Desc("FBM Fractal Simplex Noise. 4 octaves.")
|
||||
|
||||
QUADOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 4)),
|
||||
|
||||
@Desc("Rigid Multi Fractal Simplex Noise. 5 octaves.")
|
||||
|
||||
QUINTOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 5)),
|
||||
|
||||
@Desc("Billow Fractal Simplex Noise. 5 octaves.")
|
||||
|
||||
QUINTOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 5)),
|
||||
|
||||
@Desc("FBM Fractal Simplex Noise. 5 octaves.")
|
||||
|
||||
QUINTOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 5)),
|
||||
|
||||
@Desc("Rigid Multi Fractal Simplex Noise. 6 octaves.")
|
||||
|
||||
SEXOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 6)),
|
||||
|
||||
@Desc("Billow Fractal Simplex Noise. 6 octaves.")
|
||||
|
||||
SEXOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 6)),
|
||||
|
||||
@Desc("FBM Fractal Simplex Noise. 6 octaves.")
|
||||
|
||||
SEXOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 6)),
|
||||
|
||||
@Desc("Rigid Multi Fractal Simplex Noise. 7 octaves.")
|
||||
|
||||
SEPTOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 7)),
|
||||
|
||||
@Desc("Billow Fractal Simplex Noise. 7 octaves.")
|
||||
|
||||
SEPTOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 7)),
|
||||
|
||||
@Desc("FBM Fractal Simplex Noise. 7 octaves.")
|
||||
|
||||
SEPTOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 7)),
|
||||
|
||||
@Desc("Rigid Multi Fractal Simplex Noise. 8 octaves.")
|
||||
|
||||
OCTOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 8)),
|
||||
|
||||
@Desc("Billow Fractal Simplex Noise. 8 octaves.")
|
||||
|
||||
OCTOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 8)),
|
||||
|
||||
@Desc("FBM Fractal Simplex Noise. 8 octaves.")
|
||||
|
||||
OCTOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 8)),
|
||||
|
||||
@Desc("Rigid Multi Fractal Simplex Noise. 9 octaves.")
|
||||
|
||||
NONOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 9)),
|
||||
|
||||
@Desc("Billow Fractal Simplex Noise. 9 octaves.")
|
||||
|
||||
NONOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 9)),
|
||||
|
||||
@Desc("FBM Fractal Simplex Noise. 9 octaves.")
|
||||
|
||||
NONOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 9)),
|
||||
|
||||
@Desc("Rigid Multi Fractal Simplex Noise. 10 octaves.")
|
||||
|
||||
VIGOCTAVE_FRACTAL_RM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_RIGID_MULTI_SIMPLEX, 1D, 10)),
|
||||
|
||||
@Desc("Billow Fractal Simplex Noise. 10 octaves.")
|
||||
|
||||
VIGOCTAVE_FRACTAL_BILLOW_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_BILLOW_SIMPLEX, 1D, 10)),
|
||||
|
||||
@Desc("FBM Fractal Simplex Noise. 10 octaves.")
|
||||
|
||||
VIGOCTAVE_FRACTAL_FBM_SIMPLEX(rng -> new CNG(rng, NoiseType.FRACTAL_FBM_SIMPLEX, 1D, 10)),
|
||||
|
||||
@Desc("Basic, Smooth & Fast Simplex noise. Uses 2 octaves")
|
||||
|
||||
BIOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 2).scale(1D / 2D)),
|
||||
|
||||
@Desc("Basic, Smooth & Fast Simplex noise. Uses 3 octaves")
|
||||
|
||||
TRIOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 3).scale(1D / 3D)),
|
||||
|
||||
@Desc("Basic, Smooth & Fast Simplex noise. Uses 4 octaves")
|
||||
|
||||
QUADOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 4).scale(1D / 4D)),
|
||||
|
||||
@Desc("Basic, Smooth & Fast Simplex noise. Uses 5 octaves")
|
||||
|
||||
QUINTOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 5).scale(1D / 5D)),
|
||||
|
||||
@Desc("Basic, Smooth & Fast Simplex noise. Uses 6 octaves")
|
||||
|
||||
SEXOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 6).scale(1D / 6D)),
|
||||
|
||||
@Desc("Basic, Smooth & Fast Simplex noise. Uses 7 octaves")
|
||||
|
||||
SEPTOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 7).scale(1D / 12D)),
|
||||
|
||||
@Desc("Basic, Smooth & Fast Simplex noise. Uses 8 octaves")
|
||||
|
||||
OCTOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 8).scale(1D / 25D)),
|
||||
|
||||
@Desc("Basic, Smooth & Fast Simplex noise. Uses 9 octaves")
|
||||
|
||||
NONOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 9).scale(1D / 50D)),
|
||||
|
||||
@Desc("Basic, Smooth & Fast Simplex noise. Uses 10 octaves")
|
||||
|
||||
VIGOCTAVE_SIMPLEX(rng -> new CNG(rng, 1D, 10).scale(1D / 100D)),
|
||||
|
||||
@Desc("Glob noise is like cellular, but with globs...")
|
||||
|
||||
GLOB(rng -> new CNG(rng, NoiseType.GLOB, 1D, 1)),
|
||||
|
||||
@Desc("Glob noise is like cellular, but with globs...")
|
||||
|
||||
GLOB_IRIS(rng -> CNG.signature(rng, NoiseType.GLOB)),
|
||||
|
||||
@Desc("Glob noise is like cellular, but with globs...")
|
||||
|
||||
GLOB_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.GLOB)),
|
||||
|
||||
@Desc("Glob noise is like cellular, but with globs...")
|
||||
|
||||
GLOB_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.GLOB)),
|
||||
|
||||
@Desc("Glob noise is like cellular, but with globs...")
|
||||
|
||||
GLOB_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.GLOB)),
|
||||
|
||||
@Desc("Cubic Noise")
|
||||
|
||||
CUBIC(rng -> new CNG(rng, NoiseType.CUBIC, 1D, 1).scale(256)),
|
||||
|
||||
@Desc("Fractal Cubic Noise")
|
||||
|
||||
FRACTAL_CUBIC(rng -> new CNG(rng, NoiseType.FRACTAL_CUBIC, 1D, 1).scale(2)),
|
||||
|
||||
@Desc("Fractal Cubic Noise With Iris Swirls")
|
||||
|
||||
FRACTAL_CUBIC_IRIS(rng -> CNG.signature(rng, NoiseType.FRACTAL_CUBIC).scale(2)),
|
||||
|
||||
@Desc("Fractal Cubic Noise With Iris Swirls")
|
||||
|
||||
FRACTAL_CUBIC_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.FRACTAL_CUBIC).scale(2)),
|
||||
|
||||
@Desc("Fractal Cubic Noise With Iris Swirls")
|
||||
|
||||
FRACTAL_CUBIC_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.FRACTAL_CUBIC).scale(2)),
|
||||
|
||||
@Desc("Fractal Cubic Noise With Iris Swirls")
|
||||
|
||||
FRACTAL_CUBIC_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.FRACTAL_CUBIC).scale(2)),
|
||||
|
||||
@Desc("Fractal Cubic Noise, 2 Octaves")
|
||||
|
||||
BIOCTAVE_FRACTAL_CUBIC(rng -> new CNG(rng, NoiseType.FRACTAL_CUBIC, 1D, 2).scale(2)),
|
||||
|
||||
@Desc("Fractal Cubic Noise, 3 Octaves")
|
||||
|
||||
TRIOCTAVE_FRACTAL_CUBIC(rng -> new CNG(rng, NoiseType.FRACTAL_CUBIC, 1D, 3).scale(1.5)),
|
||||
|
||||
@Desc("Fractal Cubic Noise, 4 Octaves")
|
||||
|
||||
QUADOCTAVE_FRACTAL_CUBIC(rng -> new CNG(rng, NoiseType.FRACTAL_CUBIC, 1D, 4).scale(1)),
|
||||
|
||||
@Desc("Cubic Noise")
|
||||
|
||||
CUBIC_IRIS(rng -> CNG.signature(rng, NoiseType.CUBIC).scale(256)),
|
||||
|
||||
@Desc("Cubic Noise")
|
||||
|
||||
CUBIC_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.CUBIC).scale(256)),
|
||||
|
||||
@Desc("Cubic Noise")
|
||||
|
||||
CUBIC_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.CUBIC).scale(256)),
|
||||
|
||||
@Desc("Cubic Noise")
|
||||
|
||||
CUBIC_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.CUBIC).scale(256)),
|
||||
|
||||
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders.")
|
||||
|
||||
CELLULAR(rng -> new CNG(rng, NoiseType.CELLULAR, 1D, 1)),
|
||||
|
||||
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders. Cells are distorted using Iris styled wispy noise.")
|
||||
|
||||
CELLULAR_IRIS(rng -> CNG.signature(rng, NoiseType.CELLULAR)),
|
||||
|
||||
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders. Cells are distorted using Iris styled wispy noise.")
|
||||
|
||||
CELLULAR_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.CELLULAR)),
|
||||
|
||||
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders. Cells are distorted using Iris styled wispy noise.")
|
||||
|
||||
CELLULAR_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.CELLULAR)),
|
||||
|
||||
@Desc("Cellular noise creates the same noise level for cells, changes noise level on cell borders. Cells are distorted using Iris styled wispy noise.")
|
||||
|
||||
CELLULAR_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.CELLULAR)),
|
||||
|
||||
@Desc("Inverse of vascular, height gets to 1.0 as it approaches the center of a cell")
|
||||
|
||||
CELLULAR_HEIGHT(rng -> new CNG(rng, NoiseType.CELLULAR_HEIGHT, 1D, 1)),
|
||||
|
||||
@Desc("Inverse of vascular, height gets to 1.0 as it approaches the center of a cell, using the iris style.")
|
||||
|
||||
CELLULAR_HEIGHT_IRIS(rng -> CNG.signature(rng, NoiseType.CELLULAR_HEIGHT)),
|
||||
|
||||
@Desc("Inverse of vascular, height gets to 1.0 as it approaches the center of a cell, using the iris style.")
|
||||
|
||||
CELLULAR_HEIGHT_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.CELLULAR_HEIGHT)),
|
||||
|
||||
@Desc("Inverse of vascular, height gets to 1.0 as it approaches the center of a cell, using the iris style.")
|
||||
|
||||
CELLULAR_HEIGHT_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.CELLULAR_HEIGHT)),
|
||||
|
||||
@Desc("Inverse of vascular, height gets to 1.0 as it approaches the center of a cell, using the iris style.")
|
||||
|
||||
CELLULAR_HEIGHT_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.CELLULAR_HEIGHT)),
|
||||
|
||||
@Desc("Vascular noise gets higher as the position nears a cell border.")
|
||||
|
||||
VASCULAR(rng -> new CNG(rng, NoiseType.VASCULAR, 1D, 1)),
|
||||
|
||||
@Desc("It always returns 0.5")
|
||||
|
||||
FLAT(rng -> new CNG(rng, NoiseType.FLAT, 1D, 1)),
|
||||
|
||||
@Desc("Vascular noise gets higher as the position nears a cell border. Cells are distorted using Iris styled wispy noise.")
|
||||
|
||||
VASCULAR_IRIS(rng -> CNG.signature(rng, NoiseType.VASCULAR)),
|
||||
|
||||
@Desc("Vascular noise gets higher as the position nears a cell border. Cells are distorted using Iris styled wispy noise.")
|
||||
|
||||
VASCULAR_IRIS_DOUBLE(rng -> CNG.signatureDouble(rng, NoiseType.VASCULAR)),
|
||||
|
||||
@Desc("Vascular noise gets higher as the position nears a cell border. Cells are distorted using Iris styled wispy noise.")
|
||||
|
||||
VASCULAR_IRIS_THICK(rng -> CNG.signatureThick(rng, NoiseType.VASCULAR)),
|
||||
|
||||
@Desc("Vascular noise gets higher as the position nears a cell border. Cells are distorted using Iris styled wispy noise.")
|
||||
|
||||
VASCULAR_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.VASCULAR)),
|
||||
|
||||
;
|
||||
|
||||
private final CNGFactory f;
|
||||
|
||||
NoiseStyle(CNGFactory f) {
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
public ProceduralStream<Double> stream(RNG seed) {
|
||||
return create(seed).stream();
|
||||
}
|
||||
|
||||
public ProceduralStream<Double> stream(long seed) {
|
||||
return create(new RNG(seed)).stream();
|
||||
}
|
||||
|
||||
public CNG create(RNG seed) {
|
||||
return f.create(seed).bake();
|
||||
}
|
||||
|
||||
public IrisGeneratorStyle style() {
|
||||
return new IrisGeneratorStyle(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.util.Desc;
|
||||
|
||||
@Desc("Object Place modes are useful for positioning objects just right. The default value is CENTER_HEIGHT.")
|
||||
public enum ObjectPlaceMode {
|
||||
@Desc("The default place mode. This mode picks a center point (where the center of the object will be) and takes the height. That height is used for the whole object.")
|
||||
|
||||
CENTER_HEIGHT,
|
||||
|
||||
@Desc("Samples a lot of points where the object will cover (horizontally) and picks the highest height, that height is then used to place the object. This mode is useful for preventing any part of your object from being buried though it will float off of cliffs.")
|
||||
|
||||
MAX_HEIGHT,
|
||||
|
||||
@Desc("Samples only 4 points where the object will cover (horizontally) and picks the highest height, that height is then used to place the object. This mode is useful for preventing any part of your object from being buried though it will float off of cliffs.\"")
|
||||
|
||||
FAST_MAX_HEIGHT,
|
||||
|
||||
@Desc("Samples a lot of points where the object will cover (horizontally) and picks the lowest height, that height is then used to place the object. This mode is useful for preventing any part of your object from overhanging a cliff though it gets buried a lot")
|
||||
|
||||
MIN_HEIGHT,
|
||||
|
||||
@Desc("Samples only 4 points where the object will cover (horizontally) and picks the lowest height, that height is then used to place the object. This mode is useful for preventing any part of your object from overhanging a cliff though it gets buried a lot")
|
||||
|
||||
FAST_MIN_HEIGHT,
|
||||
|
||||
@Desc("Stilting is MAX_HEIGHT but it repeats the bottom most block of your object until it hits the surface. This is expensive because it has to first sample every height value for each x,z position of your object. Avoid using this unless its structures for performance reasons.")
|
||||
|
||||
STILT,
|
||||
|
||||
@Desc("Just like stilting but very inaccurate. Useful for stilting a lot of objects without too much care on accuracy (you can use the over-stilt value to force stilts under ground further)")
|
||||
|
||||
FAST_STILT,
|
||||
|
||||
@Desc("Samples the height of the terrain at every x,z position of your object and pushes it down to the surface. It's pretty much like a melt function over the terrain.")
|
||||
|
||||
PAINT,
|
||||
|
||||
@Desc("Applies multiple terrain features into the parallax layer before this object places to distort the height, essentially vacuuming the terrain's heightmap closer to the bottom of this object. Uses MAX_HEIGHT to place")
|
||||
|
||||
VACUUM
|
||||
}
|
||||
118
src/main/java/com/volmit/iris/engine/object/tile/TileBanner.java
Normal file
118
src/main/java/com/volmit/iris/engine/object/tile/TileBanner.java
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object.tile;
|
||||
|
||||
import com.volmit.iris.engine.data.nbt.tag.CompoundTag;
|
||||
import com.volmit.iris.engine.data.nbt.tag.ListTag;
|
||||
import lombok.Data;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Banner;
|
||||
import org.bukkit.block.banner.Pattern;
|
||||
import org.bukkit.block.banner.PatternType;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class TileBanner implements TileData<Banner> {
|
||||
public static final int id = 2;
|
||||
|
||||
private List<Pattern> patterns = new ArrayList<>();
|
||||
private DyeColor baseColor;
|
||||
|
||||
@Override
|
||||
public String getTileId() {
|
||||
return "minecraft:banner";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(BlockData data) {
|
||||
return isBanner(data.getMaterial());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBukkit(Banner banner) {
|
||||
banner.setPatterns(patterns);
|
||||
banner.setBaseColor(baseColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBukkit(Banner banner) {
|
||||
this.patterns = banner.getPatterns();
|
||||
this.baseColor = banner.getBaseColor();
|
||||
}
|
||||
|
||||
@SuppressWarnings("MethodDoesntCallSuperMethod")
|
||||
@Override
|
||||
public TileBanner clone() {
|
||||
TileBanner ts = new TileBanner();
|
||||
ts.setBaseColor(getBaseColor());
|
||||
ts.setPatterns(getPatterns());
|
||||
return ts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBinary(DataOutputStream out) throws IOException {
|
||||
out.writeShort(id);
|
||||
out.writeByte(baseColor.ordinal());
|
||||
out.writeByte(patterns.size());
|
||||
for (Pattern p : patterns) {
|
||||
out.writeByte(p.getColor().ordinal());
|
||||
out.writeByte(p.getPattern().ordinal());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBinary(DataInputStream in) throws IOException {
|
||||
baseColor = DyeColor.values()[in.readByte()];
|
||||
int listSize = in.readByte();
|
||||
patterns = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < listSize; i++) {
|
||||
DyeColor color = DyeColor.values()[in.readByte()];
|
||||
PatternType type = PatternType.values()[in.readByte()];
|
||||
patterns.add(new Pattern(color, type));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void toNBT(CompoundTag tag) {
|
||||
@SuppressWarnings("unchecked") ListTag<CompoundTag> listTag = (ListTag<CompoundTag>) ListTag.createUnchecked(CompoundTag.class);
|
||||
for (Pattern p : patterns) {
|
||||
CompoundTag pattern = new CompoundTag();
|
||||
pattern.putString("Pattern", p.getPattern().getIdentifier());
|
||||
pattern.putByte("Color", p.getColor().getDyeData());
|
||||
listTag.add(pattern);
|
||||
}
|
||||
tag.put("Patterns", listTag);
|
||||
}
|
||||
|
||||
public boolean isBanner(Material material) {
|
||||
return switch (material) {
|
||||
case RED_BANNER, RED_WALL_BANNER, ORANGE_BANNER, ORANGE_WALL_BANNER, YELLOW_BANNER, YELLOW_WALL_BANNER, LIME_BANNER, LIME_WALL_BANNER, GREEN_BANNER, GREEN_WALL_BANNER, CYAN_BANNER, CYAN_WALL_BANNER, LIGHT_BLUE_BANNER, LIGHT_BLUE_WALL_BANNER, BLUE_BANNER, BLUE_WALL_BANNER, PURPLE_BANNER, PURPLE_WALL_BANNER, MAGENTA_BANNER, MAGENTA_WALL_BANNER, PINK_BANNER, PINK_WALL_BANNER, WHITE_BANNER, WHITE_WALL_BANNER, LIGHT_GRAY_BANNER, LIGHT_GRAY_WALL_BANNER, GRAY_BANNER, GRAY_WALL_BANNER, BLACK_BANNER, BLACK_WALL_BANNER, BROWN_BANNER, BROWN_WALL_BANNER -> true;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
}
|
||||
119
src/main/java/com/volmit/iris/engine/object/tile/TileData.java
Normal file
119
src/main/java/com/volmit/iris/engine/object/tile/TileData.java
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object.tile;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.data.nbt.tag.CompoundTag;
|
||||
import com.volmit.iris.util.KList;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.TileState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
public interface TileData<T extends TileState> extends Cloneable {
|
||||
|
||||
KList<TileData<? extends TileState>> registry = setup();
|
||||
|
||||
static KList<TileData<? extends TileState>> setup() {
|
||||
KList<TileData<? extends TileState>> registry = new KList<>();
|
||||
|
||||
registry.add(new TileSign());
|
||||
registry.add(new TileSpawner());
|
||||
registry.add(new TileBanner());
|
||||
|
||||
return registry;
|
||||
}
|
||||
|
||||
static TileData<? extends TileState> read(DataInputStream s) throws Throwable {
|
||||
int id = s.readShort();
|
||||
@SuppressWarnings("unchecked") TileData<? extends TileState> d = registry.get(id).getClass().getConstructor().newInstance();
|
||||
d.fromBinary(s);
|
||||
return d;
|
||||
}
|
||||
|
||||
static void setTileState(Block block, TileData<? extends TileState> data) {
|
||||
if (data.isApplicable(block.getBlockData())) {
|
||||
data.toBukkitTry(block.getState());
|
||||
}
|
||||
}
|
||||
|
||||
static TileData<? extends TileState> getTileState(Block block) {
|
||||
for (TileData<? extends TileState> i : registry) {
|
||||
BlockData data = block.getBlockData();
|
||||
|
||||
if (i.isApplicable(data)) {
|
||||
try {
|
||||
@SuppressWarnings("unchecked") TileData<? extends TileState> s = i.getClass().getConstructor().newInstance();
|
||||
s.fromBukkitTry(block.getState());
|
||||
return s;
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
String getTileId();
|
||||
|
||||
boolean isApplicable(BlockData data);
|
||||
|
||||
void toBukkit(T t);
|
||||
|
||||
void fromBukkit(T t);
|
||||
|
||||
default boolean toBukkitTry(BlockState t) {
|
||||
try {
|
||||
//noinspection unchecked
|
||||
toBukkit((T) t);
|
||||
return true;
|
||||
} catch (Throwable e) {Iris.reportError(e);
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean fromBukkitTry(BlockState t) {
|
||||
try {
|
||||
//noinspection unchecked
|
||||
fromBukkit((T) t);
|
||||
return true;
|
||||
} catch (Throwable e) {Iris.reportError(e);
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TileData<T> clone();
|
||||
|
||||
void toBinary(DataOutputStream out) throws IOException;
|
||||
|
||||
void toNBT(CompoundTag tag);
|
||||
|
||||
void fromBinary(DataInputStream in) throws IOException;
|
||||
}
|
||||
108
src/main/java/com/volmit/iris/engine/object/tile/TileSign.java
Normal file
108
src/main/java/com/volmit/iris/engine/object/tile/TileSign.java
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object.tile;
|
||||
|
||||
import com.volmit.iris.engine.data.nbt.tag.CompoundTag;
|
||||
import lombok.Data;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.type.WallSign;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
@Data
|
||||
public class TileSign implements TileData<Sign> {
|
||||
public static final int id = 0;
|
||||
private String line1;
|
||||
private String line2;
|
||||
private String line3;
|
||||
private String line4;
|
||||
private DyeColor dyeColor;
|
||||
|
||||
@Override
|
||||
public String getTileId() {
|
||||
return "minecraft:sign";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(BlockData data) {
|
||||
return data instanceof org.bukkit.block.data.type.Sign || data instanceof WallSign;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBukkit(Sign t) {
|
||||
t.setLine(0, line1);
|
||||
t.setLine(1, line2);
|
||||
t.setLine(2, line3);
|
||||
t.setLine(3, line4);
|
||||
t.setColor(dyeColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBukkit(Sign sign) {
|
||||
line1 = sign.getLine(0);
|
||||
line2 = sign.getLine(1);
|
||||
line3 = sign.getLine(2);
|
||||
line4 = sign.getLine(3);
|
||||
dyeColor = sign.getColor();
|
||||
}
|
||||
|
||||
@SuppressWarnings("MethodDoesntCallSuperMethod")
|
||||
@Override
|
||||
public TileSign clone() {
|
||||
TileSign ts = new TileSign();
|
||||
ts.setDyeColor(getDyeColor());
|
||||
ts.setLine1(getLine1());
|
||||
ts.setLine2(getLine2());
|
||||
ts.setLine3(getLine3());
|
||||
ts.setLine4(getLine4());
|
||||
return ts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBinary(DataOutputStream out) throws IOException {
|
||||
out.writeShort(id);
|
||||
out.writeUTF(line1);
|
||||
out.writeUTF(line2);
|
||||
out.writeUTF(line3);
|
||||
out.writeUTF(line4);
|
||||
out.writeByte(dyeColor.ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBinary(DataInputStream in) throws IOException {
|
||||
line1 = in.readUTF();
|
||||
line2 = in.readUTF();
|
||||
line3 = in.readUTF();
|
||||
line4 = in.readUTF();
|
||||
dyeColor = DyeColor.values()[in.readByte()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toNBT(CompoundTag tag) {
|
||||
tag.putString("Text1", line1);
|
||||
tag.putString("Text2", line2);
|
||||
tag.putString("Text3", line3);
|
||||
tag.putString("Text4", line4);
|
||||
tag.putString("Color", dyeColor.name().toLowerCase());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.object.tile;
|
||||
|
||||
import com.volmit.iris.engine.data.nbt.tag.CompoundTag;
|
||||
import com.volmit.iris.engine.data.nbt.tag.ListTag;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
@Data
|
||||
public class TileSpawner implements TileData<CreatureSpawner> {
|
||||
public static final int id = 1;
|
||||
private EntityType entityType;
|
||||
|
||||
@Override
|
||||
public String getTileId() {
|
||||
return "minecraft:spawner";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(BlockData data) {
|
||||
return data.getMaterial() == Material.SPAWNER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBukkit(CreatureSpawner t) {
|
||||
t.setSpawnedType(entityType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBukkit(CreatureSpawner sign) {
|
||||
entityType = sign.getSpawnedType();
|
||||
}
|
||||
|
||||
@SuppressWarnings("MethodDoesntCallSuperMethod")
|
||||
@Override
|
||||
public TileSpawner clone() {
|
||||
TileSpawner ts = new TileSpawner();
|
||||
ts.setEntityType(getEntityType());
|
||||
return ts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBinary(DataOutputStream out) throws IOException {
|
||||
out.writeShort(id);
|
||||
out.writeShort(entityType.ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBinary(DataInputStream in) throws IOException {
|
||||
entityType = EntityType.values()[in.readShort()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toNBT(CompoundTag tag) {
|
||||
@SuppressWarnings("unchecked") ListTag<CompoundTag> potentials = (ListTag<CompoundTag>) ListTag.createUnchecked(CompoundTag.class);
|
||||
CompoundTag t = new CompoundTag();
|
||||
CompoundTag ent = new CompoundTag();
|
||||
ent.putString("id", entityType.getKey().toString());
|
||||
t.put("Entity", ent);
|
||||
t.putInt("Weight", 1);
|
||||
potentials.add(t);
|
||||
tag.put("SpawnPotentials", potentials);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user