SDF, Noise, Blocks Helper, Spline Helper, Translation Helper
This commit is contained in:
parent
6a5584deae
commit
017d663af6
37 changed files with 4315 additions and 0 deletions
171
src/main/java/ru/bclib/util/BlocksHelper.java
Normal file
171
src/main/java/ru/bclib/util/BlocksHelper.java
Normal file
|
@ -0,0 +1,171 @@
|
|||
package ru.bclib.util;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import com.google.common.collect.Maps;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
|
||||
public class BlocksHelper {
|
||||
public static final BooleanProperty ROOTS = BooleanProperty.create("roots");
|
||||
private static final Map<Block, Integer> COLOR_BY_BLOCK = Maps.newHashMap();
|
||||
|
||||
public static final int FLAG_UPDATE_BLOCK = 1;
|
||||
public static final int FLAG_SEND_CLIENT_CHANGES = 2;
|
||||
public static final int FLAG_NO_RERENDER = 4;
|
||||
public static final int FORSE_RERENDER = 8;
|
||||
public static final int FLAG_IGNORE_OBSERVERS = 16;
|
||||
|
||||
public static final int SET_SILENT = FLAG_UPDATE_BLOCK | FLAG_IGNORE_OBSERVERS | FLAG_SEND_CLIENT_CHANGES;
|
||||
public static final int SET_OBSERV = FLAG_UPDATE_BLOCK | FLAG_SEND_CLIENT_CHANGES;
|
||||
public static final Direction[] HORIZONTAL = makeHorizontal();
|
||||
public static final Direction[] DIRECTIONS = Direction.values();
|
||||
|
||||
private static final MutableBlockPos POS = new MutableBlockPos();
|
||||
protected static final BlockState AIR = Blocks.AIR.defaultBlockState();
|
||||
protected static final BlockState WATER = Blocks.WATER.defaultBlockState();
|
||||
|
||||
private static final Vec3i[] OFFSETS = new Vec3i[] {
|
||||
new Vec3i(-1, -1, -1), new Vec3i(-1, -1, 0), new Vec3i(-1, -1, 1),
|
||||
new Vec3i(-1, 0, -1), new Vec3i(-1, 0, 0), new Vec3i(-1, 0, 1),
|
||||
new Vec3i(-1, 1, -1), new Vec3i(-1, 1, 0), new Vec3i(-1, 1, 1),
|
||||
|
||||
new Vec3i(0, -1, -1), new Vec3i(0, -1, 0), new Vec3i(0, -1, 1),
|
||||
new Vec3i(0, 0, -1), new Vec3i(0, 0, 0), new Vec3i(0, 0, 1),
|
||||
new Vec3i(0, 1, -1), new Vec3i(0, 1, 0), new Vec3i(0, 1, 1),
|
||||
|
||||
new Vec3i(1, -1, -1), new Vec3i(1, -1, 0), new Vec3i(1, -1, 1),
|
||||
new Vec3i(1, 0, -1), new Vec3i(1, 0, 0), new Vec3i(1, 0, 1),
|
||||
new Vec3i(1, 1, -1), new Vec3i(1, 1, 0), new Vec3i(1, 1, 1)
|
||||
};
|
||||
|
||||
public static void addBlockColor(Block block, int color) {
|
||||
COLOR_BY_BLOCK.put(block, color);
|
||||
}
|
||||
|
||||
public static int getBlockColor(Block block) {
|
||||
return COLOR_BY_BLOCK.getOrDefault(block, 0xFF000000);
|
||||
}
|
||||
|
||||
public static void setWithoutUpdate(LevelAccessor world, BlockPos pos, BlockState state) {
|
||||
world.setBlock(pos, state, SET_SILENT);
|
||||
}
|
||||
|
||||
public static void setWithoutUpdate(LevelAccessor world, BlockPos pos, Block block) {
|
||||
world.setBlock(pos, block.defaultBlockState(), SET_SILENT);
|
||||
}
|
||||
|
||||
public static void setWithUpdate(LevelAccessor world, BlockPos pos, BlockState state) {
|
||||
world.setBlock(pos, state, SET_OBSERV);
|
||||
}
|
||||
|
||||
public static void setWithUpdate(LevelAccessor world, BlockPos pos, Block block) {
|
||||
world.setBlock(pos, block.defaultBlockState(), SET_OBSERV);
|
||||
}
|
||||
|
||||
public static int upRay(LevelAccessor world, BlockPos pos, int maxDist) {
|
||||
int length = 0;
|
||||
for (int j = 1; j < maxDist && (world.isEmptyBlock(pos.above(j))); j++) {
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
public static int downRay(LevelAccessor world, BlockPos pos, int maxDist) {
|
||||
int length = 0;
|
||||
for (int j = 1; j < maxDist && (world.isEmptyBlock(pos.below(j))); j++) {
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
public static int downRayRep(LevelAccessor world, BlockPos pos, int maxDist) {
|
||||
POS.set(pos);
|
||||
for (int j = 1; j < maxDist && (world.getBlockState(POS)).getMaterial().isReplaceable(); j++) {
|
||||
POS.setY(POS.getY() - 1);
|
||||
}
|
||||
return pos.getY() - POS.getY();
|
||||
}
|
||||
|
||||
public static int raycastSqr(LevelAccessor world, BlockPos pos, int dx, int dy, int dz, int maxDist) {
|
||||
POS.set(pos);
|
||||
for (int j = 1; j < maxDist && (world.getBlockState(POS)).getMaterial().isReplaceable(); j++) {
|
||||
POS.move(dx, dy, dz);
|
||||
}
|
||||
return (int) pos.distSqr(POS);
|
||||
}
|
||||
|
||||
public static BlockState rotateHorizontal(BlockState state, Rotation rotation, Property<Direction> facing) {
|
||||
return state.setValue(facing, rotation.rotate(state.getValue(facing)));
|
||||
}
|
||||
|
||||
public static BlockState mirrorHorizontal(BlockState state, Mirror mirror, Property<Direction> facing) {
|
||||
return state.rotate(mirror.getRotation(state.getValue(facing)));
|
||||
}
|
||||
|
||||
public static int getLengthDown(LevelAccessor world, BlockPos pos, Block block) {
|
||||
int count = 1;
|
||||
while (world.getBlockState(pos.below(count)).getBlock() == block) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public static void cover(LevelAccessor world, BlockPos center, Block ground, BlockState cover, int radius, Random random) {
|
||||
HashSet<BlockPos> points = new HashSet<BlockPos>();
|
||||
HashSet<BlockPos> points2 = new HashSet<BlockPos>();
|
||||
if (world.getBlockState(center).getBlock() == ground) {
|
||||
points.add(center);
|
||||
points2.add(center);
|
||||
for (int i = 0; i < radius; i++) {
|
||||
Iterator<BlockPos> iterator = points.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
BlockPos pos = iterator.next();
|
||||
for (Vec3i offset : OFFSETS) {
|
||||
if (random.nextBoolean()) {
|
||||
BlockPos pos2 = pos.offset(offset);
|
||||
if (random.nextBoolean() && world.getBlockState(pos2).getBlock() == ground
|
||||
&& !points.contains(pos2))
|
||||
points2.add(pos2);
|
||||
}
|
||||
}
|
||||
}
|
||||
points.addAll(points2);
|
||||
points2.clear();
|
||||
}
|
||||
Iterator<BlockPos> iterator = points.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
BlockPos pos = iterator.next();
|
||||
BlocksHelper.setWithoutUpdate(world, pos, cover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Direction[] makeHorizontal() {
|
||||
return new Direction[] { Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST };
|
||||
}
|
||||
|
||||
public static Direction randomHorizontal(Random random) {
|
||||
return HORIZONTAL[random.nextInt(4)];
|
||||
}
|
||||
|
||||
public static Direction randomDirection(Random random) {
|
||||
return DIRECTIONS[random.nextInt(6)];
|
||||
}
|
||||
|
||||
public static boolean isFluid(BlockState blockState) {
|
||||
return !blockState.getFluidState().isEmpty();
|
||||
}
|
||||
}
|
344
src/main/java/ru/bclib/util/SplineHelper.java
Normal file
344
src/main/java/ru/bclib/util/SplineHelper.java
Normal file
|
@ -0,0 +1,344 @@
|
|||
package ru.bclib.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mojang.math.Vector3f;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import ru.bclib.sdf.SDF;
|
||||
import ru.bclib.sdf.operator.SDFUnion;
|
||||
import ru.bclib.sdf.primitive.SDFLine;
|
||||
|
||||
public class SplineHelper {
|
||||
public static List<Vector3f> makeSpline(float x1, float y1, float z1, float x2, float y2, float z2, int points) {
|
||||
List<Vector3f> spline = Lists.newArrayList();
|
||||
spline.add(new Vector3f(x1, y1, z1));
|
||||
int count = points - 1;
|
||||
for (int i = 1; i < count; i++) {
|
||||
float delta = (float) i / (float) count;
|
||||
float x = Mth.lerp(delta, x1, x2);
|
||||
float y = Mth.lerp(delta, y1, y2);
|
||||
float z = Mth.lerp(delta, z1, z2);
|
||||
spline.add(new Vector3f(x, y, z));
|
||||
}
|
||||
spline.add(new Vector3f(x2, y2, z2));
|
||||
return spline;
|
||||
}
|
||||
|
||||
public static List<Vector3f> smoothSpline(List<Vector3f> spline, int segmentPoints) {
|
||||
List<Vector3f> result = Lists.newArrayList();
|
||||
Vector3f start = spline.get(0);
|
||||
for (int i = 1; i < spline.size(); i++) {
|
||||
Vector3f end = spline.get(i);
|
||||
for (int j = 0; j < segmentPoints; j++) {
|
||||
float delta = (float) j / segmentPoints;
|
||||
delta = 0.5F - 0.5F * Mth.cos(delta * 3.14159F);
|
||||
result.add(lerp(start, end, delta));
|
||||
}
|
||||
start = end;
|
||||
}
|
||||
result.add(start);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Vector3f lerp(Vector3f start, Vector3f end, float delta) {
|
||||
float x = Mth.lerp(delta, start.x(), end.x());
|
||||
float y = Mth.lerp(delta, start.y(), end.y());
|
||||
float z = Mth.lerp(delta, start.z(), end.z());
|
||||
return new Vector3f(x, y, z);
|
||||
}
|
||||
|
||||
public static void offsetParts(List<Vector3f> spline, Random random, float dx, float dy, float dz) {
|
||||
int count = spline.size();
|
||||
for (int i = 1; i < count; i++) {
|
||||
Vector3f pos = spline.get(i);
|
||||
float x = pos.x() + (float) random.nextGaussian() * dx;
|
||||
float y = pos.y() + (float) random.nextGaussian() * dy;
|
||||
float z = pos.z() + (float) random.nextGaussian() * dz;
|
||||
pos.set(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
public static void powerOffset(List<Vector3f> spline, float distance, float power) {
|
||||
int count = spline.size();
|
||||
float max = count + 1;
|
||||
for (int i = 1; i < count; i++) {
|
||||
Vector3f pos = spline.get(i);
|
||||
float x = (float) i / max;
|
||||
float y = pos.y() + (float) Math.pow(x, power) * distance;
|
||||
pos.set(pos.x(), y, pos.z());
|
||||
}
|
||||
}
|
||||
|
||||
public static SDF buildSDF(List<Vector3f> spline, float radius1, float radius2, Function<BlockPos, BlockState> placerFunction) {
|
||||
int count = spline.size();
|
||||
float max = count - 2;
|
||||
SDF result = null;
|
||||
Vector3f start = spline.get(0);
|
||||
for (int i = 1; i < count; i++) {
|
||||
Vector3f pos = spline.get(i);
|
||||
float delta = (float) (i - 1) / max;
|
||||
SDF line = new SDFLine()
|
||||
.setRadius(Mth.lerp(delta, radius1, radius2))
|
||||
.setStart(start.x(), start.y(), start.z())
|
||||
.setEnd(pos.x(), pos.y(), pos.z())
|
||||
.setBlock(placerFunction);
|
||||
result = result == null ? line : new SDFUnion().setSourceA(result).setSourceB(line);
|
||||
start = pos;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static SDF buildSDF(List<Vector3f> spline, Function<Float, Float> radiusFunction, Function<BlockPos, BlockState> placerFunction) {
|
||||
int count = spline.size();
|
||||
float max = count - 2;
|
||||
SDF result = null;
|
||||
Vector3f start = spline.get(0);
|
||||
for (int i = 1; i < count; i++) {
|
||||
Vector3f pos = spline.get(i);
|
||||
float delta = (float) (i - 1) / max;
|
||||
SDF line = new SDFLine()
|
||||
.setRadius(radiusFunction.apply(delta))
|
||||
.setStart(start.x(), start.y(), start.z())
|
||||
.setEnd(pos.x(), pos.y(), pos.z())
|
||||
.setBlock(placerFunction);
|
||||
result = result == null ? line : new SDFUnion().setSourceA(result).setSourceB(line);
|
||||
start = pos;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean fillSpline(List<Vector3f> spline, WorldGenLevel world, BlockState state, BlockPos pos, Function<BlockState, Boolean> replace) {
|
||||
Vector3f startPos = spline.get(0);
|
||||
for (int i = 1; i < spline.size(); i++) {
|
||||
Vector3f endPos = spline.get(i);
|
||||
if (!(fillLine(startPos, endPos, world, state, pos, replace))) {
|
||||
return false;
|
||||
}
|
||||
startPos = endPos;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void fillSplineForce(List<Vector3f> spline, WorldGenLevel world, BlockState state, BlockPos pos, Function<BlockState, Boolean> replace) {
|
||||
Vector3f startPos = spline.get(0);
|
||||
for (int i = 1; i < spline.size(); i++) {
|
||||
Vector3f endPos = spline.get(i);
|
||||
fillLineForce(startPos, endPos, world, state, pos, replace);
|
||||
startPos = endPos;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean fillLine(Vector3f start, Vector3f end, WorldGenLevel world, BlockState state, BlockPos pos, Function<BlockState, Boolean> replace) {
|
||||
float dx = end.x() - start.x();
|
||||
float dy = end.y() - start.y();
|
||||
float dz = end.z() - start.z();
|
||||
float max = MHelper.max(Math.abs(dx), Math.abs(dy), Math.abs(dz));
|
||||
int count = MHelper.floor(max + 1);
|
||||
dx /= max;
|
||||
dy /= max;
|
||||
dz /= max;
|
||||
float x = start.x();
|
||||
float y = start.y();
|
||||
float z = start.z();
|
||||
boolean down = Math.abs(dy) > 0.2;
|
||||
|
||||
BlockState bState;
|
||||
MutableBlockPos bPos = new MutableBlockPos();
|
||||
for (int i = 0; i < count; i++) {
|
||||
bPos.set(x + pos.getX(), y + pos.getY(), z + pos.getZ());
|
||||
bState = world.getBlockState(bPos);
|
||||
if (bState.equals(state) || replace.apply(bState)) {
|
||||
BlocksHelper.setWithoutUpdate(world, bPos, state);
|
||||
bPos.setY(bPos.getY() - 1);
|
||||
bState = world.getBlockState(bPos);
|
||||
if (down && bState.equals(state) || replace.apply(bState)) {
|
||||
BlocksHelper.setWithoutUpdate(world, bPos, state);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
x += dx;
|
||||
y += dy;
|
||||
z += dz;
|
||||
}
|
||||
bPos.set(end.x() + pos.getX(), end.y() + pos.getY(), end.z() + pos.getZ());
|
||||
bState = world.getBlockState(bPos);
|
||||
if (bState.equals(state) || replace.apply(bState)) {
|
||||
BlocksHelper.setWithoutUpdate(world, bPos, state);
|
||||
bPos.setY(bPos.getY() - 1);
|
||||
bState = world.getBlockState(bPos);
|
||||
if (down && bState.equals(state) || replace.apply(bState)) {
|
||||
BlocksHelper.setWithoutUpdate(world, bPos, state);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void fillLineForce(Vector3f start, Vector3f end, WorldGenLevel world, BlockState state, BlockPos pos, Function<BlockState, Boolean> replace) {
|
||||
float dx = end.x() - start.x();
|
||||
float dy = end.y() - start.y();
|
||||
float dz = end.z() - start.z();
|
||||
float max = MHelper.max(Math.abs(dx), Math.abs(dy), Math.abs(dz));
|
||||
int count = MHelper.floor(max + 1);
|
||||
dx /= max;
|
||||
dy /= max;
|
||||
dz /= max;
|
||||
float x = start.x();
|
||||
float y = start.y();
|
||||
float z = start.z();
|
||||
boolean down = Math.abs(dy) > 0.2;
|
||||
|
||||
BlockState bState;
|
||||
MutableBlockPos bPos = new MutableBlockPos();
|
||||
for (int i = 0; i < count; i++) {
|
||||
bPos.set(x + pos.getX(), y + pos.getY(), z + pos.getZ());
|
||||
bState = world.getBlockState(bPos);
|
||||
if (replace.apply(bState)) {
|
||||
BlocksHelper.setWithoutUpdate(world, bPos, state);
|
||||
bPos.setY(bPos.getY() - 1);
|
||||
bState = world.getBlockState(bPos);
|
||||
if (down && replace.apply(bState)) {
|
||||
BlocksHelper.setWithoutUpdate(world, bPos, state);
|
||||
}
|
||||
}
|
||||
x += dx;
|
||||
y += dy;
|
||||
z += dz;
|
||||
}
|
||||
bPos.set(end.x() + pos.getX(), end.y() + pos.getY(), end.z() + pos.getZ());
|
||||
bState = world.getBlockState(bPos);
|
||||
if (replace.apply(bState)) {
|
||||
BlocksHelper.setWithoutUpdate(world, bPos, state);
|
||||
bPos.setY(bPos.getY() - 1);
|
||||
bState = world.getBlockState(bPos);
|
||||
if (down && replace.apply(bState)) {
|
||||
BlocksHelper.setWithoutUpdate(world, bPos, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean canGenerate(List<Vector3f> spline, float scale, BlockPos start, WorldGenLevel world, Function<BlockState, Boolean> canReplace) {
|
||||
int count = spline.size();
|
||||
Vector3f vec = spline.get(0);
|
||||
MutableBlockPos mut = new MutableBlockPos();
|
||||
float x1 = start.getX() + vec.x() * scale;
|
||||
float y1 = start.getY() + vec.y() * scale;
|
||||
float z1 = start.getZ() + vec.z() * scale;
|
||||
for (int i = 1; i < count; i++) {
|
||||
vec = spline.get(i);
|
||||
float x2 = start.getX() + vec.x() * scale;
|
||||
float y2 = start.getY() + vec.y() * scale;
|
||||
float z2 = start.getZ() + vec.z() * scale;
|
||||
|
||||
for (float py = y1; py < y2; py += 3) {
|
||||
if (py - start.getY() < 10) continue;
|
||||
float lerp = (py - y1) / (y2 - y1);
|
||||
float x = Mth.lerp(lerp, x1, x2);
|
||||
float z = Mth.lerp(lerp, z1, z2);
|
||||
mut.set(x, py, z);
|
||||
if (!canReplace.apply(world.getBlockState(mut))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
z1 = z2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean canGenerate(List<Vector3f> spline, BlockPos start, WorldGenLevel world, Function<BlockState, Boolean> canReplace) {
|
||||
int count = spline.size();
|
||||
Vector3f vec = spline.get(0);
|
||||
MutableBlockPos mut = new MutableBlockPos();
|
||||
float x1 = start.getX() + vec.x();
|
||||
float y1 = start.getY() + vec.y();
|
||||
float z1 = start.getZ() + vec.z();
|
||||
for (int i = 1; i < count; i++) {
|
||||
vec = spline.get(i);
|
||||
float x2 = start.getX() + vec.x();
|
||||
float y2 = start.getY() + vec.y();
|
||||
float z2 = start.getZ() + vec.z();
|
||||
|
||||
for (float py = y1; py < y2; py += 3) {
|
||||
if (py - start.getY() < 10) continue;
|
||||
float lerp = (py - y1) / (y2 - y1);
|
||||
float x = Mth.lerp(lerp, x1, x2);
|
||||
float z = Mth.lerp(lerp, z1, z2);
|
||||
mut.set(x, py, z);
|
||||
if (!canReplace.apply(world.getBlockState(mut))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
z1 = z2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Vector3f getPos(List<Vector3f> spline, float index) {
|
||||
int i = (int) index;
|
||||
int last = spline.size() - 1;
|
||||
if (i >= last) {
|
||||
return spline.get(last);
|
||||
}
|
||||
float delta = index - i;
|
||||
Vector3f p1 = spline.get(i);
|
||||
Vector3f p2 = spline.get(i + 1);
|
||||
float x = Mth.lerp(delta, p1.x(), p2.x());
|
||||
float y = Mth.lerp(delta, p1.y(), p2.y());
|
||||
float z = Mth.lerp(delta, p1.z(), p2.z());
|
||||
return new Vector3f(x, y, z);
|
||||
}
|
||||
|
||||
public static void rotateSpline(List<Vector3f> spline, float angle) {
|
||||
for (Vector3f v: spline) {
|
||||
float sin = (float) Math.sin(angle);
|
||||
float cos = (float) Math.cos(angle);
|
||||
float x = v.x() * cos + v.z() * sin;
|
||||
float z = v.x() * sin + v.z() * cos;
|
||||
v.set(x, v.y(), z);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Vector3f> copySpline(List<Vector3f> spline) {
|
||||
List<Vector3f> result = new ArrayList<Vector3f>(spline.size());
|
||||
for (Vector3f v: spline) {
|
||||
result.add(new Vector3f(v.x(), v.y(), v.z()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void scale(List<Vector3f> spline, float scale) {
|
||||
scale(spline, scale, scale, scale);
|
||||
}
|
||||
|
||||
public static void scale(List<Vector3f> spline, float x, float y, float z) {
|
||||
for (Vector3f v: spline) {
|
||||
v.set(v.x() * x, v.y() * y, v.z() * z);
|
||||
}
|
||||
}
|
||||
|
||||
public static void offset(List<Vector3f> spline, Vector3f offset) {
|
||||
for (Vector3f v: spline) {
|
||||
v.set(offset.x() + v.x(), offset.y() + v.y(), offset.z() + v.z());
|
||||
}
|
||||
}
|
||||
}
|
73
src/main/java/ru/bclib/util/TagHelper.java
Normal file
73
src/main/java/ru/bclib/util/TagHelper.java
Normal file
|
@ -0,0 +1,73 @@
|
|||
package ru.bclib.util;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.Tag;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
public class TagHelper {
|
||||
private static final Map<ResourceLocation, Set<ResourceLocation>> TAGS_BLOCK = Maps.newConcurrentMap();
|
||||
private static final Map<ResourceLocation, Set<ResourceLocation>> TAGS_ITEM = Maps.newConcurrentMap();
|
||||
|
||||
public static void addTag(Tag.Named<Block> tag, Block... blocks) {
|
||||
ResourceLocation tagID = tag.getName();
|
||||
Set<ResourceLocation> set = TAGS_BLOCK.computeIfAbsent(tagID, k -> Sets.newHashSet());
|
||||
for (Block block: blocks) {
|
||||
ResourceLocation id = Registry.BLOCK.getKey(block);
|
||||
if (id != Registry.BLOCK.getDefaultKey()) {
|
||||
set.add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void addTag(Tag.Named<Item> tag, ItemLike... items) {
|
||||
ResourceLocation tagID = tag.getName();
|
||||
Set<ResourceLocation> set = TAGS_ITEM.computeIfAbsent(tagID, k -> Sets.newHashSet());
|
||||
for (ItemLike item: items) {
|
||||
ResourceLocation id = Registry.ITEM.getKey(item.asItem());
|
||||
if (id != Registry.ITEM.getDefaultKey()) {
|
||||
set.add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static void addTags(ItemLike item, Tag.Named<Item>... tags) {
|
||||
for (Tag.Named<Item> tag: tags) {
|
||||
addTag(tag, item);
|
||||
}
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static void addTags(Block block, Tag.Named<Block>... tags) {
|
||||
for (Tag.Named<Block> tag: tags) {
|
||||
addTag(tag, block);
|
||||
}
|
||||
}
|
||||
|
||||
public static Tag.Builder apply(Tag.Builder builder, Set<ResourceLocation> ids) {
|
||||
ids.forEach(value -> builder.addElement(value, "Better End Code"));
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static Map<ResourceLocation, Tag.Builder> apply(String entry, Map<ResourceLocation, Tag.Builder> tagsMap) {
|
||||
Map<ResourceLocation, Set<ResourceLocation>> endTags = null;
|
||||
if (entry.equals("block")) {
|
||||
endTags = TAGS_BLOCK;
|
||||
} else if (entry.equals("item")) {
|
||||
endTags = TAGS_ITEM;
|
||||
}
|
||||
if (endTags != null) {
|
||||
endTags.forEach((id, ids) -> apply(tagsMap.computeIfAbsent(id, key -> Tag.Builder.tag()), ids));
|
||||
}
|
||||
return tagsMap;
|
||||
}
|
||||
}
|
119
src/main/java/ru/bclib/util/TranslationHelper.java
Normal file
119
src/main/java/ru/bclib/util/TranslationHelper.java
Normal file
|
@ -0,0 +1,119 @@
|
|||
package ru.bclib.util;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.data.BuiltinRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class TranslationHelper {
|
||||
public static void printMissingNames(String modID) {
|
||||
List<String> missingNamesEn = Lists.newArrayList();
|
||||
List<String> missingNamesRu = Lists.newArrayList();
|
||||
|
||||
Gson gson = new Gson();
|
||||
InputStream streamEn = TranslationHelper.class.getResourceAsStream("/assets/" + modID + "/lang/en_us.json");
|
||||
InputStream streamRu = TranslationHelper.class.getResourceAsStream("/assets/" + modID + "/lang/ru_ru.json");
|
||||
JsonObject translationEn = gson.fromJson(new InputStreamReader(streamEn), JsonObject.class);
|
||||
JsonObject translationRu = gson.fromJson(new InputStreamReader(streamRu), JsonObject.class);
|
||||
|
||||
Registry.BLOCK.forEach(block -> {
|
||||
if (Registry.BLOCK.getKey(block).getNamespace().equals(modID)) {
|
||||
String name = block.getName().getString();
|
||||
if (!translationEn.has(name)) {
|
||||
missingNamesEn.add(name);
|
||||
}
|
||||
if (!translationRu.has(name)) {
|
||||
missingNamesRu.add(name);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Registry.ITEM.forEach(item -> {
|
||||
if (Registry.ITEM.getKey(item).getNamespace().equals(modID)) {
|
||||
String name = item.getDescription().getString();
|
||||
if (!translationEn.has(name)) {
|
||||
missingNamesEn.add(name);
|
||||
}
|
||||
if (!translationRu.has(name)) {
|
||||
missingNamesRu.add(name);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
BuiltinRegistries.BIOME.forEach(biome -> {
|
||||
ResourceLocation id = BuiltinRegistries.BIOME.getKey(biome);
|
||||
if (id.getNamespace().equals(modID)) {
|
||||
String name = "biome." + modID + "." + id.getPath();
|
||||
if (!translationEn.has(name)) {
|
||||
missingNamesEn.add(name);
|
||||
}
|
||||
if (!translationRu.has(name)) {
|
||||
missingNamesRu.add(name);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Registry.ENTITY_TYPE.forEach((entity) -> {
|
||||
ResourceLocation id = Registry.ENTITY_TYPE.getKey(entity);
|
||||
if (id.getNamespace().equals(modID)) {
|
||||
String name = "entity." + modID + "." + id.getPath();
|
||||
if (!translationEn.has(name)) {
|
||||
missingNamesEn.add(name);
|
||||
}
|
||||
if (!translationRu.has(name)) {
|
||||
missingNamesRu.add(name);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!missingNamesEn.isEmpty() || !missingNamesRu.isEmpty()) {
|
||||
|
||||
System.out.println("========================================");
|
||||
System.out.println(" MISSING NAMES LIST");
|
||||
|
||||
if (!missingNamesEn.isEmpty()) {
|
||||
Collections.sort(missingNamesEn);
|
||||
System.out.println("========================================");
|
||||
System.out.println(" ENGLISH");
|
||||
System.out.println("========================================");
|
||||
missingNamesEn.forEach((name) -> {
|
||||
System.out.println(" \"" + name + "\": \"" + fastTranslateEn(name) + "\",");
|
||||
});
|
||||
}
|
||||
|
||||
if (!missingNamesRu.isEmpty()) {
|
||||
Collections.sort(missingNamesRu);
|
||||
System.out.println("========================================");
|
||||
System.out.println(" RUSSIAN");
|
||||
System.out.println("========================================");
|
||||
missingNamesRu.forEach((name) -> {
|
||||
System.out.println(" \"" + name + "\": \"\",");
|
||||
});
|
||||
}
|
||||
|
||||
System.out.println("========================================");
|
||||
}
|
||||
}
|
||||
|
||||
public static String fastTranslateEn(String text) {
|
||||
String[] words = text.substring(text.lastIndexOf('.') + 1).split("_");
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < words.length; i++) {
|
||||
String word = words[i];
|
||||
builder.append(Character.toUpperCase(word.charAt(0)));
|
||||
builder.append(word, 1, word.length());
|
||||
if (i < words.length - 1) {
|
||||
builder.append(' ');
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue