Compare commits
10 Commits
save-world
...
v0.3.0
Author | SHA1 | Date | |
---|---|---|---|
eb5aa59941
|
|||
409bbdb680
|
|||
a85fc27f8b
|
|||
711e4a2bb4
|
|||
f74c731a3d
|
|||
98c383bf7d
|
|||
dd80df2cf2
|
|||
1727a2a4a1
|
|||
20fb8f0597
|
|||
1d28f32865
|
@ -42,3 +42,16 @@ Run configurations are used by Intellij IDEA to specify how a project must be ru
|
|||||||
9. Click 'Apply' to save changes.
|
9. Click 'Apply' to save changes.
|
||||||
|
|
||||||
Step 8 is required to specify that the game must run in some directory other than the project root, which is the default in Intellij IDEA.
|
Step 8 is required to specify that the game must run in some directory other than the project root, which is the default in Intellij IDEA.
|
||||||
|
|
||||||
|
### Applying formatting templates
|
||||||
|
|
||||||
|
Windcorp's Progressia repository is formatted with a style defined for Eclipse IDE (sic) in
|
||||||
|
`templates_and_presets/eclipse_ide`.
|
||||||
|
Please apply these templates to the project to automatically format the source in a similar fashion.
|
||||||
|
|
||||||
|
1. In project context menu, click 'File->Properties'. (`Ctrl+Alt+S`)
|
||||||
|
2. In 'Editor' > 'Code Style' > 'Java', press gear icon, then click 'Import Scheme' > 'Eclipse code style'
|
||||||
|
3. In Scheme select 'Project'
|
||||||
|
4. Open the file `templates_and_presets/eclipse_ide/FormatterProfile.xml` in 'Select Path'.
|
||||||
|
5. Inside 'Import Scheme' widow click 'Current Scheme' check box after press OK
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package ru.windcorp.progressia.client.graphics.backend;
|
package ru.windcorp.progressia.client.graphics.backend;
|
||||||
|
|
||||||
import glm.vec._2.i.Vec2i;
|
import glm.vec._2.i.Vec2i;
|
||||||
|
|
||||||
import org.lwjgl.glfw.GLFWVidMode;
|
import org.lwjgl.glfw.GLFWVidMode;
|
||||||
|
|
||||||
import static org.lwjgl.glfw.GLFW.*;
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
@ -43,6 +44,13 @@ public class GraphicsBackend {
|
|||||||
private static boolean isGLFWInitialized = false;
|
private static boolean isGLFWInitialized = false;
|
||||||
private static boolean isOpenGLInitialized = false;
|
private static boolean isOpenGLInitialized = false;
|
||||||
|
|
||||||
|
private static boolean allowDisablingCursor;
|
||||||
|
static {
|
||||||
|
String key = GraphicsBackend.class.getName() + ".allowDisablingCursor";
|
||||||
|
allowDisablingCursor = Boolean.parseBoolean(System.getProperty(key, "true"));
|
||||||
|
}
|
||||||
|
private static boolean forceCursorToCenter = false;
|
||||||
|
|
||||||
private GraphicsBackend() {
|
private GraphicsBackend() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +122,10 @@ public class GraphicsBackend {
|
|||||||
frameLength = now - frameStart;
|
frameLength = now - frameStart;
|
||||||
frameStart = now;
|
frameStart = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (forceCursorToCenter) {
|
||||||
|
glfwSetCursorPos(windowHandle, FRAME_SIZE.x / 2.0, FRAME_SIZE.y / 2.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void endFrame() {
|
static void endFrame() {
|
||||||
@ -194,10 +206,18 @@ public class GraphicsBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isMouseCaptured() {
|
public static boolean isMouseCaptured() {
|
||||||
|
if (!allowDisablingCursor) {
|
||||||
|
return forceCursorToCenter;
|
||||||
|
}
|
||||||
return glfwGetInputMode(windowHandle, GLFW_CURSOR) == GLFW_CURSOR_DISABLED;
|
return glfwGetInputMode(windowHandle, GLFW_CURSOR) == GLFW_CURSOR_DISABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setMouseCaptured(boolean capture) {
|
public static void setMouseCaptured(boolean capture) {
|
||||||
|
if (!allowDisablingCursor) {
|
||||||
|
forceCursorToCenter = capture;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int mode = capture ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL;
|
int mode = capture ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL;
|
||||||
glfwSetInputMode(windowHandle, GLFW_CURSOR, mode);
|
glfwSetInputMode(windowHandle, GLFW_CURSOR, mode);
|
||||||
|
|
||||||
|
@ -124,6 +124,7 @@ public abstract class BasicButton extends Component {
|
|||||||
public void setPressed(boolean isPressed) {
|
public void setPressed(boolean isPressed) {
|
||||||
if (this.isPressed != isPressed) {
|
if (this.isPressed != isPressed) {
|
||||||
this.isPressed = isPressed;
|
this.isPressed = isPressed;
|
||||||
|
requestReassembly();
|
||||||
|
|
||||||
if (isPressed) {
|
if (isPressed) {
|
||||||
takeFocus();
|
takeFocus();
|
||||||
|
@ -807,7 +807,7 @@ public class Component extends Named {
|
|||||||
for (ARTrigger trigger : triggers) {
|
for (ARTrigger trigger : triggers) {
|
||||||
if (!autoReassemblyTriggerObjects.containsKey(trigger)) {
|
if (!autoReassemblyTriggerObjects.containsKey(trigger)) {
|
||||||
Object triggerObject = createTriggerObject(trigger);
|
Object triggerObject = createTriggerObject(trigger);
|
||||||
addListener(trigger);
|
addListener(triggerObject);
|
||||||
autoReassemblyTriggerObjects.put(trigger, triggerObject);
|
autoReassemblyTriggerObjects.put(trigger, triggerObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,6 @@ public class Label extends Component {
|
|||||||
|
|
||||||
public void setFont(Font font) {
|
public void setFont(Font font) {
|
||||||
this.font = font;
|
this.font = font;
|
||||||
requestReassembly();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCurrentText() {
|
public String getCurrentText() {
|
||||||
|
@ -20,10 +20,12 @@ package ru.windcorp.progressia.client.graphics.model;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import glm.mat._4.Mat4;
|
||||||
import glm.vec._3.Vec3;
|
import glm.vec._3.Vec3;
|
||||||
import glm.vec._4.Vec4;
|
import glm.vec._4.Vec4;
|
||||||
import ru.windcorp.progressia.client.graphics.backend.Usage;
|
import ru.windcorp.progressia.client.graphics.backend.Usage;
|
||||||
import ru.windcorp.progressia.client.graphics.texture.Texture;
|
import ru.windcorp.progressia.client.graphics.texture.Texture;
|
||||||
|
import ru.windcorp.progressia.common.util.VectorUtil;
|
||||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
|
|
||||||
public class Shapes {
|
public class Shapes {
|
||||||
@ -260,6 +262,34 @@ public class Shapes {
|
|||||||
return this.setSize(size, size, size);
|
return this.setSize(size, size, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PppBuilder centerAt(float x, float y, float z) {
|
||||||
|
origin.set(x, y, z);
|
||||||
|
|
||||||
|
origin.mul(2);
|
||||||
|
origin.sub(width);
|
||||||
|
origin.sub(height);
|
||||||
|
origin.sub(depth);
|
||||||
|
origin.div(2);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder apply(Mat4 transform) {
|
||||||
|
VectorUtil.applyMat4(origin, transform);
|
||||||
|
VectorUtil.rotateOnly(width, transform);
|
||||||
|
VectorUtil.rotateOnly(height, transform);
|
||||||
|
VectorUtil.rotateOnly(depth, transform);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PppBuilder scale(float factor) {
|
||||||
|
origin.mul(factor);
|
||||||
|
width.mul(factor);
|
||||||
|
height.mul(factor);
|
||||||
|
depth.mul(factor);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public PppBuilder flip() {
|
public PppBuilder flip() {
|
||||||
this.flip = true;
|
this.flip = true;
|
||||||
return this;
|
return this;
|
||||||
|
@ -29,6 +29,20 @@ public abstract class AbstractStatefulObjectLayout
|
|||||||
super(objectId);
|
super(objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StateStorage createStorage() {
|
||||||
|
StateStorage storage = instantiateStorage();
|
||||||
|
|
||||||
|
int fieldCount = getFieldCount();
|
||||||
|
for (int i = 0; i < fieldCount; ++i) {
|
||||||
|
getField(i).setDefault(storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract StateStorage instantiateStorage();
|
||||||
|
|
||||||
protected abstract int getFieldCount();
|
protected abstract int getFieldCount();
|
||||||
|
|
||||||
protected abstract StateField getField(int fieldIndex);
|
protected abstract StateField getField(int fieldIndex);
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.common.state;
|
||||||
|
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.DataOutput;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public interface Encodable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the state of this object according to the binary representation read
|
||||||
|
* from {@code input}. If {@code context == COMMS}, the state of local
|
||||||
|
* fields is unspecified after this operation.
|
||||||
|
*
|
||||||
|
* @param input a {@link DataInput} that a state can be read from
|
||||||
|
* @param context the context
|
||||||
|
* @throws IOException if the state is encoded poorly or an error occurs
|
||||||
|
* in {@code input}
|
||||||
|
*/
|
||||||
|
void read(DataInput input, IOContext context) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the binary representation of the state of this object to the
|
||||||
|
* {@code output}.
|
||||||
|
*
|
||||||
|
* @param output a {@link DataOutput} that a state can be written to
|
||||||
|
* @param context the context
|
||||||
|
* @throws IOException if an error occurs in {@code output}
|
||||||
|
*/
|
||||||
|
void write(DataOutput output, IOContext context) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns {@code destination} into a deep copy of this object.
|
||||||
|
* <p>
|
||||||
|
* Changes the provided object so that:
|
||||||
|
* <ul>
|
||||||
|
* <li>the provided object equals this object; and</li>
|
||||||
|
* <li>the provided object is independent of this object, meaning no change
|
||||||
|
* to {@code destination} can affect this object.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param destination the object to copy this object into. Runtime class
|
||||||
|
* must match this class
|
||||||
|
* @return {@code destination}
|
||||||
|
*/
|
||||||
|
void copy(Encodable destination);
|
||||||
|
|
||||||
|
}
|
@ -19,11 +19,14 @@
|
|||||||
package ru.windcorp.progressia.common.state;
|
package ru.windcorp.progressia.common.state;
|
||||||
|
|
||||||
import gnu.trove.map.TIntIntMap;
|
import gnu.trove.map.TIntIntMap;
|
||||||
|
import gnu.trove.map.TIntObjectMap;
|
||||||
import gnu.trove.map.hash.TIntIntHashMap;
|
import gnu.trove.map.hash.TIntIntHashMap;
|
||||||
|
import gnu.trove.map.hash.TIntObjectHashMap;
|
||||||
|
|
||||||
public class HashMapStateStorage extends StateStorage {
|
public class HashMapStateStorage extends StateStorage {
|
||||||
|
|
||||||
private final TIntIntMap ints = new TIntIntHashMap();
|
private final TIntIntMap ints = new TIntIntHashMap();
|
||||||
|
private final TIntObjectMap<Object> objects = new TIntObjectHashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getInt(int index) {
|
public int getInt(int index) {
|
||||||
@ -35,4 +38,14 @@ public class HashMapStateStorage extends StateStorage {
|
|||||||
ints.put(index, value);
|
ints.put(index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject(int index) {
|
||||||
|
return objects.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setObject(int index, Object object) {
|
||||||
|
objects.put(index, object);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,9 @@ package ru.windcorp.progressia.common.state;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.state.codec.ObjectCodec;
|
||||||
|
|
||||||
public class InspectingStatefulObjectLayout
|
public class InspectingStatefulObjectLayout
|
||||||
extends AbstractStatefulObjectLayout {
|
extends AbstractStatefulObjectLayout {
|
||||||
@ -33,7 +36,7 @@ public class InspectingStatefulObjectLayout
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StateStorage createStorage() {
|
public StateStorage instantiateStorage() {
|
||||||
return new HashMapStateStorage();
|
return new HashMapStateStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +85,31 @@ public class InspectingStatefulObjectLayout
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class Obj<T> implements StateFieldBuilder.Obj<T> {
|
||||||
|
|
||||||
|
private final ObjectCodec<T> codec;
|
||||||
|
private final Supplier<T> defaultValue;
|
||||||
|
|
||||||
|
public Obj(ObjectCodec<T> codec, Supplier<T> defaultValue) {
|
||||||
|
this.codec = codec;
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectStateField<T> build() {
|
||||||
|
return registerField(
|
||||||
|
new ObjectStateField<T>(
|
||||||
|
id,
|
||||||
|
isLocal,
|
||||||
|
fieldIndexCounters.getObjectsThenIncrement(),
|
||||||
|
codec,
|
||||||
|
defaultValue
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private final String id;
|
private final String id;
|
||||||
|
|
||||||
private boolean isLocal = true;
|
private boolean isLocal = true;
|
||||||
@ -95,6 +123,11 @@ public class InspectingStatefulObjectLayout
|
|||||||
return new Int();
|
return new Int();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Obj<T> of(ObjectCodec<T> codec, Supplier<T> defaultValue) {
|
||||||
|
return new Obj<T>(codec, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StateFieldBuilder setLocal(boolean isLocal) {
|
public StateFieldBuilder setLocal(boolean isLocal) {
|
||||||
this.isLocal = isLocal;
|
this.isLocal = isLocal;
|
||||||
|
@ -79,4 +79,9 @@ public class IntStateField extends StateField {
|
|||||||
return get(a) == get(b);
|
return get(a) == get(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDefault(StateStorage storage) {
|
||||||
|
storage.setInt(getIndex(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.common.state;
|
||||||
|
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.DataOutput;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.state.codec.ObjectCodec;
|
||||||
|
|
||||||
|
public class ObjectStateField<T> extends StateField {
|
||||||
|
|
||||||
|
private final ObjectCodec<T> codec;
|
||||||
|
private final Supplier<T> defaultValue;
|
||||||
|
|
||||||
|
public ObjectStateField(
|
||||||
|
String id,
|
||||||
|
boolean isLocal,
|
||||||
|
int index,
|
||||||
|
ObjectCodec<T> codec,
|
||||||
|
Supplier<T> defaultValue
|
||||||
|
) {
|
||||||
|
super(id, isLocal, index);
|
||||||
|
|
||||||
|
this.codec = codec;
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectCodec<T> getCodec() {
|
||||||
|
return codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T get(StatefulObject object) {
|
||||||
|
return (T) object.getStorage().getObject(getIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNow(StatefulObject object, T value) {
|
||||||
|
object.getStorage().setObject(getIndex(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(StateChanger changer, T value) {
|
||||||
|
changer.setObject(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(
|
||||||
|
StatefulObject object,
|
||||||
|
DataInput input,
|
||||||
|
IOContext context
|
||||||
|
)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
T previous = get(object);
|
||||||
|
T result = codec.read(previous, input, context);
|
||||||
|
object.getStorage().setObject(getIndex(), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(
|
||||||
|
StatefulObject object,
|
||||||
|
DataOutput output,
|
||||||
|
IOContext context
|
||||||
|
)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
codec.write(object.getStorage().getObject(getIndex()), output, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copy(StatefulObject from, StatefulObject to) {
|
||||||
|
setNow(to, get(from));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int computeHashCode(StatefulObject object) {
|
||||||
|
return codec.computeHashCode(get(object));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areEqual(StatefulObject a, StatefulObject b) {
|
||||||
|
return codec.areEqual(get(a), get(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDefault(StateStorage storage) {
|
||||||
|
storage.setObject(getIndex(), defaultValue.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -21,9 +21,11 @@ package ru.windcorp.progressia.common.state;
|
|||||||
public class OptimizedStateStorage extends StateStorage {
|
public class OptimizedStateStorage extends StateStorage {
|
||||||
|
|
||||||
private final int[] ints;
|
private final int[] ints;
|
||||||
|
private final Object[] objects;
|
||||||
|
|
||||||
public OptimizedStateStorage(PrimitiveCounters sizes) {
|
public OptimizedStateStorage(PrimitiveCounters sizes) {
|
||||||
this.ints = new int[sizes.getInts()];
|
this.ints = new int[sizes.getInts()];
|
||||||
|
this.objects = new Object[sizes.getObjects()];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -36,4 +38,14 @@ public class OptimizedStateStorage extends StateStorage {
|
|||||||
ints[index] = value;
|
ints[index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject(int index) {
|
||||||
|
return objects[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setObject(int index, Object object) {
|
||||||
|
objects[index] = object;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,12 @@
|
|||||||
package ru.windcorp.progressia.common.state;
|
package ru.windcorp.progressia.common.state;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.state.codec.ObjectCodec;
|
||||||
|
|
||||||
public class OptimizedStatefulObjectLayout
|
public class OptimizedStatefulObjectLayout
|
||||||
extends AbstractStatefulObjectLayout {
|
extends AbstractStatefulObjectLayout {
|
||||||
|
|
||||||
@ -49,7 +52,7 @@ public class OptimizedStatefulObjectLayout
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StateStorage createStorage() {
|
public StateStorage instantiateStorage() {
|
||||||
return new OptimizedStateStorage(sizes);
|
return new OptimizedStateStorage(sizes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,6 +75,17 @@ public class OptimizedStatefulObjectLayout
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Obj<T> of(ObjectCodec<T> codec, Supplier<T> defaultValue) {
|
||||||
|
return new Obj<T>() {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public ObjectStateField<T> build() {
|
||||||
|
return (ObjectStateField<T>) result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StateFieldBuilder setLocal(boolean isLocal) {
|
public StateFieldBuilder setLocal(boolean isLocal) {
|
||||||
return this;
|
return this;
|
||||||
|
@ -21,12 +21,14 @@ package ru.windcorp.progressia.common.state;
|
|||||||
class PrimitiveCounters {
|
class PrimitiveCounters {
|
||||||
|
|
||||||
private int ints = 0;
|
private int ints = 0;
|
||||||
|
private int objects = 0;
|
||||||
|
|
||||||
public PrimitiveCounters() {
|
public PrimitiveCounters() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public PrimitiveCounters(PrimitiveCounters copyFrom) {
|
public PrimitiveCounters(PrimitiveCounters copyFrom) {
|
||||||
this.ints = copyFrom.ints;
|
this.ints = copyFrom.ints;
|
||||||
|
this.objects = copyFrom.objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getInts() {
|
public int getInts() {
|
||||||
@ -37,4 +39,12 @@ class PrimitiveCounters {
|
|||||||
return this.ints++;
|
return this.ints++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getObjects() {
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getObjectsThenIncrement() {
|
||||||
|
return this.objects++;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,6 @@ package ru.windcorp.progressia.common.state;
|
|||||||
public interface StateChanger {
|
public interface StateChanger {
|
||||||
|
|
||||||
void setInt(IntStateField field, int value);
|
void setInt(IntStateField field, int value);
|
||||||
|
<T> void setObject(ObjectStateField<T> field, T value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -67,4 +67,6 @@ public abstract class StateField extends Namespaced {
|
|||||||
|
|
||||||
public abstract boolean areEqual(StatefulObject a, StatefulObject b);
|
public abstract boolean areEqual(StatefulObject a, StatefulObject b);
|
||||||
|
|
||||||
|
public abstract void setDefault(StateStorage storage);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,59 @@
|
|||||||
|
|
||||||
package ru.windcorp.progressia.common.state;
|
package ru.windcorp.progressia.common.state;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.state.codec.ObjectCodec;
|
||||||
|
import ru.windcorp.progressia.common.state.codec.ObjectCodecRegistry;
|
||||||
|
|
||||||
public interface StateFieldBuilder {
|
public interface StateFieldBuilder {
|
||||||
|
|
||||||
public static interface Int {
|
public static interface Int {
|
||||||
IntStateField build();
|
IntStateField build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static interface Obj<T> {
|
||||||
|
ObjectStateField<T> build();
|
||||||
|
}
|
||||||
|
|
||||||
Int ofInt();
|
Int ofInt();
|
||||||
|
|
||||||
|
<T> Obj<T> of(ObjectCodec<T> codec, Supplier<T> defaultValue);
|
||||||
|
|
||||||
|
default <T> Obj<T> of(Class<T> clazz, Supplier<T> defaultValue) {
|
||||||
|
ObjectCodec<T> codec = ObjectCodecRegistry.get(clazz);
|
||||||
|
return of(codec, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> Obj<T> of(ObjectCodec<T> codec, T defaultValue) {
|
||||||
|
return of(codec, (Supplier<T>) () -> codec.copy(defaultValue, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> Obj<T> of(Class<T> clazz, T defaultValue) {
|
||||||
|
ObjectCodec<T> codec = ObjectCodecRegistry.get(clazz);
|
||||||
|
return of(codec, (Supplier<T>) () -> codec.copy(defaultValue, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> Obj<T> of(ObjectCodec<T> codec) {
|
||||||
|
return of(codec, (Supplier<T>) () -> null);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> Obj<T> of(Class<T> clazz) {
|
||||||
|
ObjectCodec<T> codec = ObjectCodecRegistry.get(clazz);
|
||||||
|
return of(codec, (Supplier<T>) () -> null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
default <T> Obj<T> def(Supplier<T> defaultValue) {
|
||||||
|
Class<T> clazz = (Class<T>) defaultValue.get().getClass();
|
||||||
|
return of(clazz, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
default <T> Obj<T> def(T defaultValue) {
|
||||||
|
return of((Class<T>) defaultValue.getClass(), defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
StateFieldBuilder setLocal(boolean isLocal);
|
StateFieldBuilder setLocal(boolean isLocal);
|
||||||
|
|
||||||
default StateFieldBuilder setLocal() {
|
default StateFieldBuilder setLocal() {
|
||||||
|
@ -24,4 +24,8 @@ public abstract class StateStorage {
|
|||||||
|
|
||||||
public abstract void setInt(int index, int value);
|
public abstract void setInt(int index, int value);
|
||||||
|
|
||||||
|
public abstract Object getObject(int index);
|
||||||
|
|
||||||
|
public abstract void setObject(int index, Object object);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ import ru.windcorp.progressia.common.util.namespaces.Namespaced;
|
|||||||
* type.</li>
|
* type.</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public abstract class StatefulObject extends Namespaced {
|
public abstract class StatefulObject extends Namespaced implements Encodable {
|
||||||
|
|
||||||
private final StatefulObjectLayout layout;
|
private final StatefulObjectLayout layout;
|
||||||
|
|
||||||
@ -133,6 +133,7 @@ public abstract class StatefulObject extends Namespaced {
|
|||||||
* @throws IOException if the state is encoded poorly or an error occurs
|
* @throws IOException if the state is encoded poorly or an error occurs
|
||||||
* in {@code input}
|
* in {@code input}
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void read(DataInput input, IOContext context) throws IOException {
|
public void read(DataInput input, IOContext context) throws IOException {
|
||||||
getLayout().read(this, input, context);
|
getLayout().read(this, input, context);
|
||||||
}
|
}
|
||||||
@ -145,6 +146,7 @@ public abstract class StatefulObject extends Namespaced {
|
|||||||
* @param context the context
|
* @param context the context
|
||||||
* @throws IOException if an error occurs in {@code output}
|
* @throws IOException if an error occurs in {@code output}
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void write(DataOutput output, IOContext context) throws IOException {
|
public void write(DataOutput output, IOContext context) throws IOException {
|
||||||
getLayout().write(this, output, context);
|
getLayout().write(this, output, context);
|
||||||
}
|
}
|
||||||
@ -166,7 +168,8 @@ public abstract class StatefulObject extends Namespaced {
|
|||||||
*
|
*
|
||||||
* @param destination the object to copy this object into.
|
* @param destination the object to copy this object into.
|
||||||
*/
|
*/
|
||||||
public StatefulObject copy(StatefulObject destination) {
|
@Override
|
||||||
|
public void copy(Encodable destination) {
|
||||||
Objects.requireNonNull(destination, "destination");
|
Objects.requireNonNull(destination, "destination");
|
||||||
|
|
||||||
if (destination == this) {
|
if (destination == this) {
|
||||||
@ -182,8 +185,7 @@ public abstract class StatefulObject extends Namespaced {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLayout().copy(this, destination);
|
getLayout().copy(this, (StatefulObject) destination);
|
||||||
return destination;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.common.state.codec;
|
||||||
|
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.DataOutput;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.state.Encodable;
|
||||||
|
import ru.windcorp.progressia.common.state.IOContext;
|
||||||
|
|
||||||
|
public class EncodableCodec extends ReusableObjectCodec<Encodable> {
|
||||||
|
|
||||||
|
public EncodableCodec() {
|
||||||
|
super(Encodable.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Encodable doRead(Encodable previous, DataInput input, IOContext context) throws IOException {
|
||||||
|
previous.read(input, context);
|
||||||
|
return previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doWrite(Encodable obj, DataOutput output, IOContext context) throws IOException {
|
||||||
|
obj.write(output, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Encodable doCopy(Encodable object, Encodable previous) {
|
||||||
|
Objects.requireNonNull(previous, "previous");
|
||||||
|
object.copy(previous);
|
||||||
|
return previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.common.state.codec;
|
||||||
|
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.state.IOContext;
|
||||||
|
|
||||||
|
public abstract class ImmutableObjectCodec<T> extends ObjectCodec<T> {
|
||||||
|
|
||||||
|
public ImmutableObjectCodec(Class<T> clazz) {
|
||||||
|
super(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final T copy(T object, T previous) {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final T doRead(T previous, DataInput input, IOContext context) throws IOException {
|
||||||
|
return doRead(input, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract T doRead(DataInput input, IOContext context) throws IOException;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.common.state.codec;
|
||||||
|
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.DataOutput;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.state.IOContext;
|
||||||
|
|
||||||
|
public abstract class ObjectCodec<T> {
|
||||||
|
|
||||||
|
private final Class<T> clazz;
|
||||||
|
|
||||||
|
public ObjectCodec(Class<T> clazz) {
|
||||||
|
this.clazz = clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<T> getDataType() {
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public final T read(Object previous, DataInput input, IOContext context) throws IOException {
|
||||||
|
assert previous == null || clazz.isInstance(previous)
|
||||||
|
: "Cannot use codec " + this + " on object of type " + previous.getClass();
|
||||||
|
|
||||||
|
T result = doRead((T) previous, input, context);
|
||||||
|
|
||||||
|
assert result == null || clazz.isInstance(previous)
|
||||||
|
: "Codec " + this + " read object of type " + previous.getClass();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract T doRead(T previous, DataInput input, IOContext context) throws IOException;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public final void write(Object value, DataOutput output, IOContext context) throws IOException {
|
||||||
|
assert value == null || clazz.isInstance(value)
|
||||||
|
: "Cannot use codec " + this + " on object of type " + value.getClass();
|
||||||
|
|
||||||
|
doWrite((T) value, output, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void doWrite(T obj, DataOutput output, IOContext context) throws IOException;
|
||||||
|
|
||||||
|
public abstract T copy(T object, T previous);
|
||||||
|
|
||||||
|
public int computeHashCode(T object) {
|
||||||
|
return Objects.hashCode(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean areEqual(T a, T b) {
|
||||||
|
return Objects.equals(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.common.state.codec;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.state.Encodable;
|
||||||
|
|
||||||
|
public class ObjectCodecRegistry {
|
||||||
|
|
||||||
|
private static final Map<Class<?>, ObjectCodec<?>> CODECS = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
private static final EncodableCodec ENCODABLE_FALLBACK = new EncodableCodec();
|
||||||
|
|
||||||
|
public static void register(ObjectCodec<?> codec) {
|
||||||
|
CODECS.put(codec.getDataType(), codec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> ObjectCodec<T> get(Class<T> clazz) {
|
||||||
|
ObjectCodec<?> codec = CODECS.get(clazz);
|
||||||
|
if (codec != null) {
|
||||||
|
return (ObjectCodec<T>) codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Encodable.class.isAssignableFrom(clazz)) {
|
||||||
|
return (ObjectCodec<T>) ENCODABLE_FALLBACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException("No codec registered for class " + clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.common.state.codec;
|
||||||
|
|
||||||
|
public abstract class ReusableObjectCodec<T> extends ObjectCodec<T> {
|
||||||
|
|
||||||
|
public ReusableObjectCodec(Class<T> clazz) {
|
||||||
|
super(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final T copy(T object, T previous) {
|
||||||
|
if (object == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
T result = doCopy(object, previous);
|
||||||
|
|
||||||
|
assert result != null : "copy() returned null";
|
||||||
|
assert areEqual(object, result) : "copy() does not equal original: " + result + " != " + object;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract T doCopy(T object, T previous);
|
||||||
|
|
||||||
|
}
|
@ -199,6 +199,63 @@ public class VectorUtil {
|
|||||||
return rotateOnly(inOut, mat, inOut);
|
return rotateOnly(inOut, mat, inOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Mat4 lookAt(Mat4 applyTo, Vec3 target, Vec3 up, Mat4 output) {
|
||||||
|
if (output == null) {
|
||||||
|
output = new Mat4();
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat4 lookAtTransform = Matrices.grab4();
|
||||||
|
|
||||||
|
// Adapted from Glm.lookAt - we use Z as up
|
||||||
|
|
||||||
|
// f(normalize(target))
|
||||||
|
float fX = target.x;
|
||||||
|
float fY = target.y;
|
||||||
|
float fZ = target.z;
|
||||||
|
float inverseSqrt = 1f / (float) Math.sqrt(fX * fX + fY * fY + fZ * fZ);
|
||||||
|
fX *= inverseSqrt;
|
||||||
|
fY *= inverseSqrt;
|
||||||
|
fZ *= inverseSqrt;
|
||||||
|
// s(normalize(cross(up, f)))
|
||||||
|
float sX = up.y * fZ - up.z * fY;
|
||||||
|
float sY = up.z * fX - up.x * fZ;
|
||||||
|
float sZ = up.x * fY - up.y * fX;
|
||||||
|
inverseSqrt = 1.0f / (float) Math.sqrt(sX * sX + sY * sY + sZ * sZ);
|
||||||
|
sX *= inverseSqrt;
|
||||||
|
sY *= inverseSqrt;
|
||||||
|
sZ *= inverseSqrt;
|
||||||
|
// u(cross(f, s))
|
||||||
|
float uX = fY * sZ - fZ * sY;
|
||||||
|
float uY = fZ * sX - fX * sZ;
|
||||||
|
float uZ = fX * sY - fY * sX;
|
||||||
|
|
||||||
|
lookAtTransform.m00 = fX;
|
||||||
|
lookAtTransform.m01 = fY;
|
||||||
|
lookAtTransform.m02 = fZ;
|
||||||
|
lookAtTransform.m03 = 0f;
|
||||||
|
lookAtTransform.m10 = sX;
|
||||||
|
lookAtTransform.m11 = sY;
|
||||||
|
lookAtTransform.m12 = sZ;
|
||||||
|
lookAtTransform.m13 = 0f;
|
||||||
|
lookAtTransform.m20 = uX;
|
||||||
|
lookAtTransform.m21 = uY;
|
||||||
|
lookAtTransform.m22 = uZ;
|
||||||
|
lookAtTransform.m23 = 0f;
|
||||||
|
lookAtTransform.m30 = 0;
|
||||||
|
lookAtTransform.m31 = 0;
|
||||||
|
lookAtTransform.m32 = 0;
|
||||||
|
lookAtTransform.m33 = 1f;
|
||||||
|
|
||||||
|
applyTo.mul(lookAtTransform, output);
|
||||||
|
Matrices.release(lookAtTransform);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Mat4 lookAt(Vec3 center, Vec3 up, Mat4 inOut) {
|
||||||
|
return lookAt(inOut, center, up, inOut);
|
||||||
|
}
|
||||||
|
|
||||||
public static Vec3 rotate(Vec3 in, Vec3 axis, float angle, Vec3 out) {
|
public static Vec3 rotate(Vec3 in, Vec3 axis, float angle, Vec3 out) {
|
||||||
if (out == null) {
|
if (out == null) {
|
||||||
out = new Vec3();
|
out = new Vec3();
|
||||||
@ -270,6 +327,20 @@ public class VectorUtil {
|
|||||||
return projectOnVector(inOut, vector);
|
return projectOnVector(inOut, vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static float distanceSq(Vec3 a, Vec3 b) {
|
||||||
|
float x = a.x - b.x;
|
||||||
|
float y = a.y - b.y;
|
||||||
|
float z = a.z - b.z;
|
||||||
|
return x * x + y * y + z * z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float distance(Vec3 a, Vec3 b) {
|
||||||
|
float x = a.x - b.x;
|
||||||
|
float y = a.y - b.y;
|
||||||
|
float z = a.z - b.z;
|
||||||
|
return (float) Math.sqrt(x * x + y * y + z * z);
|
||||||
|
}
|
||||||
|
|
||||||
public static Vec3 linearCombination(
|
public static Vec3 linearCombination(
|
||||||
Vec3 va,
|
Vec3 va,
|
||||||
float ka,
|
float ka,
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.common.util.math;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface FloatFunction {
|
||||||
|
|
||||||
|
float apply(float x);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.common.util.math;
|
||||||
|
|
||||||
|
public interface FloatFunction2D {
|
||||||
|
|
||||||
|
float apply(float x, float y);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.common.util.math;
|
||||||
|
|
||||||
|
public interface FloatFunction3D {
|
||||||
|
|
||||||
|
float apply(float x, float y, float z);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.common.util.math;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import glm.vec._2.Vec2;
|
||||||
|
|
||||||
|
public class PiecewiseLinearFunction implements FloatFunction {
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
private final List<Vec2> points = new ArrayList<>();
|
||||||
|
private float slopeAtNegInf = 0;
|
||||||
|
private float slopeAtPosInf = 0;
|
||||||
|
|
||||||
|
public Builder add(float x, float y) {
|
||||||
|
points.add(new Vec2(x, y));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setNegativeSlope(float slope) {
|
||||||
|
slopeAtNegInf = slope;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setPositiveSlope(float slope) {
|
||||||
|
slopeAtPosInf = slope;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setDefaultUndefined() {
|
||||||
|
slopeAtPosInf = Float.NaN;
|
||||||
|
slopeAtNegInf = Float.NaN;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PiecewiseLinearFunction build() {
|
||||||
|
float[] pointXs = new float[points.size()];
|
||||||
|
float[] pointYs = new float[points.size()];
|
||||||
|
|
||||||
|
points.sort(Comparator.comparingDouble(v -> v.x));
|
||||||
|
for (int i = 0; i < points.size(); ++i) {
|
||||||
|
pointXs[i] = points.get(i).x;
|
||||||
|
pointYs[i] = points.get(i).y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PiecewiseLinearFunction(pointXs, pointYs, slopeAtNegInf, slopeAtPosInf);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The set of the X coordinates of all defining points, sorted in increasing order
|
||||||
|
*/
|
||||||
|
private final float[] pointXs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The set of the Y coordinates of all defining points, sorted to match the order of {@link #pointXs}
|
||||||
|
*/
|
||||||
|
private final float[] pointYs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slope of the segment (-inf; x[0]), or NaN to exclude the segment from the function
|
||||||
|
*/
|
||||||
|
private final float slopeAtNegInf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slope of the segment (x[x.length - 1]; +inf), or NaN to exclude the segment from the function
|
||||||
|
*/
|
||||||
|
private final float slopeAtPosInf;
|
||||||
|
|
||||||
|
protected PiecewiseLinearFunction(float[] pointXs, float[] pointYs, float slopeAtNegInf, float slopeAtPosInf) {
|
||||||
|
this.pointXs = pointXs;
|
||||||
|
this.pointYs = pointYs;
|
||||||
|
this.slopeAtNegInf = slopeAtNegInf;
|
||||||
|
this.slopeAtPosInf = slopeAtPosInf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float apply(float x) {
|
||||||
|
int index = Arrays.binarySearch(pointXs, x);
|
||||||
|
|
||||||
|
if (index >= 0) {
|
||||||
|
// Wow, exact match, me surprised
|
||||||
|
return pointYs[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
int bigger = -index - 1;
|
||||||
|
int smaller = bigger - 1;
|
||||||
|
|
||||||
|
if (smaller == -1) {
|
||||||
|
return pointYs[bigger] + (x - pointXs[bigger]) * slopeAtNegInf;
|
||||||
|
} else if (bigger == pointXs.length) {
|
||||||
|
return pointYs[smaller] + (x - pointXs[smaller]) * slopeAtPosInf;
|
||||||
|
} else {
|
||||||
|
float t = (x - pointXs[smaller]) / (pointXs[bigger] - pointXs[smaller]);
|
||||||
|
return pointYs[smaller] * (1 - t) + pointYs[bigger] * t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,8 +19,11 @@ package ru.windcorp.progressia.common.world.generic.context;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import glm.vec._3.Vec3;
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.progressia.common.util.VectorUtil;
|
||||||
import ru.windcorp.progressia.common.world.context.Context;
|
import ru.windcorp.progressia.common.world.context.Context;
|
||||||
import ru.windcorp.progressia.common.world.generic.*;
|
import ru.windcorp.progressia.common.world.generic.*;
|
||||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
@ -141,6 +144,42 @@ public interface WorldGenericContextRO<
|
|||||||
*/
|
*/
|
||||||
E getEntity(long entityId);
|
E getEntity(long entityId);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convenience methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
default void forEachEntity(Consumer<E> action) {
|
||||||
|
getEntities().forEach(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
default E findClosestEntity(Vec3 location, Predicate<E> filter, float maxDistance) {
|
||||||
|
if (maxDistance <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
E result = getEntities().stream().filter(filter).min((a, b) -> {
|
||||||
|
float aDistance = VectorUtil.distanceSq(location, a.getPosition());
|
||||||
|
float bDistance = VectorUtil.distanceSq(location, b.getPosition());
|
||||||
|
return Float.compare(aDistance, bDistance);
|
||||||
|
}).orElse(null);
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (Float.isInfinite(maxDistance)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (VectorUtil.distanceSq(location, result.getPosition()) > maxDistance * maxDistance) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
default E findClosestEntity(Vec3 location, float maxDistance) {
|
||||||
|
return findClosestEntity(location, e -> true, maxDistance);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Subcontexting
|
* Subcontexting
|
||||||
*/
|
*/
|
||||||
|
@ -21,8 +21,6 @@ package ru.windcorp.progressia.server;
|
|||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
|
|
||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
@ -353,7 +351,6 @@ public class Server {
|
|||||||
* reason
|
* reason
|
||||||
*/
|
*/
|
||||||
public void shutdown(String message) {
|
public void shutdown(String message) {
|
||||||
LogManager.getLogger().warn("Server.shutdown() is not yet implemented");
|
|
||||||
serverThread.stop();
|
serverThread.stop();
|
||||||
getWorld().getContainer().close();
|
getWorld().getContainer().close();
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ public class ClientManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void processPackets() {
|
public void processPackets() {
|
||||||
getClients().forEach(CommsChannel::processPackets);
|
clients.forEach(CommsChannel::processPackets);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -146,7 +146,7 @@ public class ClientManager {
|
|||||||
return;
|
return;
|
||||||
if (!(c instanceof ClientPlayer))
|
if (!(c instanceof ClientPlayer))
|
||||||
return;
|
return;
|
||||||
if (!((ClientPlayer) c).isChunkVisible(entityId))
|
if (!((ClientPlayer) c).isEntityVisible(entityId))
|
||||||
return;
|
return;
|
||||||
c.sendPacket(packet);
|
c.sendPacket(packet);
|
||||||
});
|
});
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
package ru.windcorp.progressia.server.comms;
|
package ru.windcorp.progressia.server.comms;
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import gnu.trove.TCollections;
|
||||||
|
import gnu.trove.set.TLongSet;
|
||||||
|
import gnu.trove.set.hash.TLongHashSet;
|
||||||
import ru.windcorp.progressia.common.world.generic.ChunkSet;
|
import ru.windcorp.progressia.common.world.generic.ChunkSet;
|
||||||
import ru.windcorp.progressia.common.world.generic.ChunkSets;
|
import ru.windcorp.progressia.common.world.generic.ChunkSets;
|
||||||
import ru.windcorp.progressia.server.Player;
|
import ru.windcorp.progressia.server.Player;
|
||||||
@ -53,8 +56,19 @@ public abstract class ClientPlayer extends ClientChat {
|
|||||||
return player.getServer().getLoadManager().getVisionManager().getVisibleChunks(player);
|
return player.getServer().getLoadManager().getVisionManager().getVisibleChunks(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isChunkVisible(long entityId) {
|
public boolean isEntityVisible(long entityId) {
|
||||||
return true;
|
if (player == null)
|
||||||
|
return false;
|
||||||
|
return player.getServer().getLoadManager().getVisionManager().isEntityVisible(entityId, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final TLongSet EMPTY_TLONGSET = TCollections.unmodifiableSet(new TLongHashSet(0));
|
||||||
|
|
||||||
|
public TLongSet getVisibleEntities(Player player) {
|
||||||
|
if (player == null) {
|
||||||
|
return EMPTY_TLONGSET;
|
||||||
|
}
|
||||||
|
return player.getServer().getLoadManager().getVisionManager().getVisibleEntities(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,14 @@
|
|||||||
*/
|
*/
|
||||||
package ru.windcorp.progressia.server.management.load;
|
package ru.windcorp.progressia.server.management.load;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
||||||
import ru.windcorp.progressia.common.world.PacketRevokeChunk;
|
import ru.windcorp.progressia.common.world.PacketRevokeChunk;
|
||||||
import ru.windcorp.progressia.common.world.PacketSendChunk;
|
import ru.windcorp.progressia.common.world.PacketSendChunk;
|
||||||
|
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||||
import ru.windcorp.progressia.common.world.DefaultWorldData;
|
import ru.windcorp.progressia.common.world.DefaultWorldData;
|
||||||
import ru.windcorp.progressia.server.Player;
|
import ru.windcorp.progressia.server.Player;
|
||||||
import ru.windcorp.progressia.server.Server;
|
import ru.windcorp.progressia.server.Server;
|
||||||
@ -144,6 +148,11 @@ public class ChunkManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO allow entities to be saved first
|
||||||
|
Set<EntityData> entitiesToRemove = new HashSet<>();
|
||||||
|
world.forEachEntityInChunk(chunkPos, entitiesToRemove::add);
|
||||||
|
entitiesToRemove.forEach(world::removeEntity);
|
||||||
|
|
||||||
world.removeChunk(chunk);
|
world.removeChunk(chunk);
|
||||||
getContainer().save(chunk, getServer().getWorld().getData(), getServer());
|
getContainer().save(chunk, getServer().getWorld().getData(), getServer());
|
||||||
|
|
||||||
|
@ -25,6 +25,9 @@ import java.util.function.Consumer;
|
|||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import gnu.trove.TCollections;
|
||||||
|
import gnu.trove.set.TLongSet;
|
||||||
|
import gnu.trove.set.hash.TLongHashSet;
|
||||||
import ru.windcorp.progressia.common.world.generic.ChunkSet;
|
import ru.windcorp.progressia.common.world.generic.ChunkSet;
|
||||||
import ru.windcorp.progressia.common.world.generic.ChunkSets;
|
import ru.windcorp.progressia.common.world.generic.ChunkSets;
|
||||||
import ru.windcorp.progressia.server.Player;
|
import ru.windcorp.progressia.server.Player;
|
||||||
@ -85,6 +88,28 @@ public class VisionManager {
|
|||||||
return vision.getVisibleChunks();
|
return vision.getVisibleChunks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEntityVisible(long entityId, Player player) {
|
||||||
|
PlayerVision vision = getVision(player, false);
|
||||||
|
|
||||||
|
if (vision == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vision.isEntityVisible(entityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final TLongSet EMPTY_TLONGSET = TCollections.unmodifiableSet(new TLongHashSet(0));
|
||||||
|
|
||||||
|
public TLongSet getVisibleEntities(Player player) {
|
||||||
|
PlayerVision vision = getVision(player, false);
|
||||||
|
|
||||||
|
if (vision == null) {
|
||||||
|
return EMPTY_TLONGSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vision.getVisibleEntities();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the loadManager
|
* @return the loadManager
|
||||||
*/
|
*/
|
||||||
|
@ -21,6 +21,7 @@ package ru.windcorp.progressia.server.world;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import glm.Glm;
|
import glm.Glm;
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
@ -93,6 +94,27 @@ public class DefaultWorldLogic implements WorldLogic {
|
|||||||
return getData().getEntity(entityId);
|
return getData().getEntity(entityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void spawnEntity(EntityData entity) {
|
||||||
|
Objects.requireNonNull(entity, "entity");
|
||||||
|
if (entity.getEntityId() != EntityData.NULL_ENTITY_ID) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Entity ID of entity " + entity
|
||||||
|
+ " is not unassigned; use WorldData.addEntity to add entity with assigned entity ID"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
long entityId;
|
||||||
|
|
||||||
|
// TODO this should be synchronized on the entity set
|
||||||
|
do {
|
||||||
|
entityId = server.getAdHocRandom().nextLong();
|
||||||
|
} while (entityId == EntityData.NULL_ENTITY_ID || getEntity(entityId) != null);
|
||||||
|
|
||||||
|
entity.setEntityId(entityId);
|
||||||
|
getData().addEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
public Evaluation getTickEntitiesTask() {
|
public Evaluation getTickEntitiesTask() {
|
||||||
return tickEntitiesTask;
|
return tickEntitiesTask;
|
||||||
}
|
}
|
||||||
@ -118,31 +140,49 @@ public class DefaultWorldLogic implements WorldLogic {
|
|||||||
DefaultChunkData chunk = getGenerator().generate(chunkPos);
|
DefaultChunkData chunk = getGenerator().generate(chunkPos);
|
||||||
|
|
||||||
if (!Glm.equals(chunkPos, chunk.getPosition())) {
|
if (!Glm.equals(chunkPos, chunk.getPosition())) {
|
||||||
throw CrashReports.report(null, "Generator %s has generated a chunk at (%d; %d; %d) when requested to generate a chunk at (%d; %d; %d)",
|
throw CrashReports.report(
|
||||||
|
null,
|
||||||
|
"Generator %s has generated a chunk at (%d; %d; %d) when requested to generate a chunk at (%d; %d; %d)",
|
||||||
getGenerator(),
|
getGenerator(),
|
||||||
chunk.getX(), chunk.getY(), chunk.getZ(),
|
chunk.getX(),
|
||||||
chunkPos.x, chunkPos.y, chunkPos.z
|
chunk.getY(),
|
||||||
|
chunk.getZ(),
|
||||||
|
chunkPos.x,
|
||||||
|
chunkPos.y,
|
||||||
|
chunkPos.z
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getData().getChunk(chunk.getPosition()) != chunk) {
|
if (getData().getChunk(chunk.getPosition()) != chunk) {
|
||||||
if (isChunkLoaded(chunkPos)) {
|
if (isChunkLoaded(chunkPos)) {
|
||||||
throw CrashReports.report(null, "Generator %s has returned a chunk different to the chunk that is located at (%d; %d; %d)",
|
throw CrashReports.report(
|
||||||
|
null,
|
||||||
|
"Generator %s has returned a chunk different to the chunk that is located at (%d; %d; %d)",
|
||||||
getGenerator(),
|
getGenerator(),
|
||||||
chunkPos.x, chunkPos.y, chunkPos.z
|
chunkPos.x,
|
||||||
|
chunkPos.y,
|
||||||
|
chunkPos.z
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
throw CrashReports.report(null, "Generator %s has returned a chunk that is not loaded when requested to generate a chunk at (%d; %d; %d)",
|
throw CrashReports.report(
|
||||||
|
null,
|
||||||
|
"Generator %s has returned a chunk that is not loaded when requested to generate a chunk at (%d; %d; %d)",
|
||||||
getGenerator(),
|
getGenerator(),
|
||||||
chunkPos.x, chunkPos.y, chunkPos.z
|
chunkPos.x,
|
||||||
|
chunkPos.y,
|
||||||
|
chunkPos.z
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!getChunk(chunk).isReady()) {
|
if (!getChunk(chunk).isReady()) {
|
||||||
throw CrashReports.report(null, "Generator %s has returned a chunk that is not ready when requested to generate a chunk at (%d; %d; %d)",
|
throw CrashReports.report(
|
||||||
|
null,
|
||||||
|
"Generator %s has returned a chunk that is not ready when requested to generate a chunk at (%d; %d; %d)",
|
||||||
getGenerator(),
|
getGenerator(),
|
||||||
chunkPos.x, chunkPos.y, chunkPos.z
|
chunkPos.x,
|
||||||
|
chunkPos.y,
|
||||||
|
chunkPos.z
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,10 +21,13 @@ import java.util.Collection;
|
|||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.world.WorldData;
|
import ru.windcorp.progressia.common.world.WorldData;
|
||||||
|
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||||
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
||||||
|
|
||||||
public interface WorldLogic extends WorldLogicRO {
|
public interface WorldLogic extends WorldLogicRO {
|
||||||
|
|
||||||
|
void spawnEntity(EntityData entity);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Override return types
|
* Override return types
|
||||||
*/
|
*/
|
||||||
|
@ -24,7 +24,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import glm.vec._3.Vec3;
|
import glm.vec._3.Vec3;
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.util.FloatRangeMap;
|
|
||||||
import ru.windcorp.progressia.common.util.VectorUtil;
|
import ru.windcorp.progressia.common.util.VectorUtil;
|
||||||
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
||||||
import ru.windcorp.progressia.common.world.DecodingException;
|
import ru.windcorp.progressia.common.world.DecodingException;
|
||||||
@ -32,7 +31,7 @@ import ru.windcorp.progressia.server.Server;
|
|||||||
import ru.windcorp.progressia.server.world.generation.AbstractWorldGenerator;
|
import ru.windcorp.progressia.server.world.generation.AbstractWorldGenerator;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFeature;
|
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFeature;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
|
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer;
|
import ru.windcorp.progressia.server.world.generation.surface.TerrainSupplier;
|
||||||
|
|
||||||
public class PlanetGenerator extends AbstractWorldGenerator<Boolean> {
|
public class PlanetGenerator extends AbstractWorldGenerator<Boolean> {
|
||||||
|
|
||||||
@ -46,7 +45,7 @@ public class PlanetGenerator extends AbstractWorldGenerator<Boolean> {
|
|||||||
Server server,
|
Server server,
|
||||||
Planet planet,
|
Planet planet,
|
||||||
SurfaceFloatField heightMap,
|
SurfaceFloatField heightMap,
|
||||||
FloatRangeMap<TerrainLayer> layers,
|
TerrainSupplier terrain,
|
||||||
List<SurfaceFeature> features
|
List<SurfaceFeature> features
|
||||||
) {
|
) {
|
||||||
super(id, server, Boolean.class, "Test:PlanetGravityModel");
|
super(id, server, Boolean.class, "Test:PlanetGravityModel");
|
||||||
@ -56,7 +55,7 @@ public class PlanetGenerator extends AbstractWorldGenerator<Boolean> {
|
|||||||
PlanetGravityModel model = (PlanetGravityModel) this.getGravityModel();
|
PlanetGravityModel model = (PlanetGravityModel) this.getGravityModel();
|
||||||
model.configure(planet.getGravityModelSettings());
|
model.configure(planet.getGravityModelSettings());
|
||||||
|
|
||||||
this.terrainGenerator = new PlanetTerrainGenerator(this, heightMap, layers);
|
this.terrainGenerator = new PlanetTerrainGenerator(this, heightMap, terrain);
|
||||||
this.featureGenerator = new PlanetFeatureGenerator(this, features);
|
this.featureGenerator = new PlanetFeatureGenerator(this, features);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ import java.util.Map;
|
|||||||
|
|
||||||
import glm.vec._3.Vec3;
|
import glm.vec._3.Vec3;
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.util.FloatRangeMap;
|
|
||||||
import ru.windcorp.progressia.common.util.VectorUtil;
|
import ru.windcorp.progressia.common.util.VectorUtil;
|
||||||
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
||||||
import ru.windcorp.progressia.common.world.Coordinates;
|
import ru.windcorp.progressia.common.world.Coordinates;
|
||||||
@ -33,7 +32,7 @@ import ru.windcorp.progressia.server.Server;
|
|||||||
import ru.windcorp.progressia.server.world.generation.surface.Surface;
|
import ru.windcorp.progressia.server.world.generation.surface.Surface;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
|
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.SurfaceTerrainGenerator;
|
import ru.windcorp.progressia.server.world.generation.surface.SurfaceTerrainGenerator;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer;
|
import ru.windcorp.progressia.server.world.generation.surface.TerrainSupplier;
|
||||||
|
|
||||||
class PlanetTerrainGenerator {
|
class PlanetTerrainGenerator {
|
||||||
|
|
||||||
@ -43,7 +42,7 @@ class PlanetTerrainGenerator {
|
|||||||
public PlanetTerrainGenerator(
|
public PlanetTerrainGenerator(
|
||||||
PlanetGenerator generator,
|
PlanetGenerator generator,
|
||||||
SurfaceFloatField heightMap,
|
SurfaceFloatField heightMap,
|
||||||
FloatRangeMap<TerrainLayer> layers
|
TerrainSupplier terrain
|
||||||
) {
|
) {
|
||||||
this.parent = generator;
|
this.parent = generator;
|
||||||
|
|
||||||
@ -53,7 +52,7 @@ class PlanetTerrainGenerator {
|
|||||||
face -> new SurfaceTerrainGenerator(
|
face -> new SurfaceTerrainGenerator(
|
||||||
new Surface(face, seaLevel),
|
new Surface(face, seaLevel),
|
||||||
heightMap,
|
heightMap,
|
||||||
layers
|
terrain
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -86,6 +85,11 @@ class PlanetTerrainGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateBorderTerrain(Server server, DefaultChunkData chunk) {
|
private void generateBorderTerrain(Server server, DefaultChunkData chunk) {
|
||||||
|
if (chunk.getPosition().x == 0 && chunk.getPosition().y == 0 && chunk.getPosition().z == 0) {
|
||||||
|
generateCore(server, chunk);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BlockData stone = BlockDataRegistry.getInstance().get("Test:Stone");
|
BlockData stone = BlockDataRegistry.getInstance().get("Test:Stone");
|
||||||
BlockData air = BlockDataRegistry.getInstance().get("Test:Air");
|
BlockData air = BlockDataRegistry.getInstance().get("Test:Air");
|
||||||
|
|
||||||
@ -109,4 +113,16 @@ class PlanetTerrainGenerator {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void generateCore(Server server, DefaultChunkData chunk) {
|
||||||
|
BlockData tux = BlockDataRegistry.getInstance().get("Test:Tux");
|
||||||
|
BlockData air = BlockDataRegistry.getInstance().get("Test:Air");
|
||||||
|
|
||||||
|
|
||||||
|
GenericChunks.forEachBiC(bic -> {
|
||||||
|
chunk.setBlock(bic, air, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
chunk.setBlock(new Vec3i(7, 7, 0), tux, false);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ package ru.windcorp.progressia.server.world.generation.surface;
|
|||||||
|
|
||||||
import glm.vec._3.Vec3;
|
import glm.vec._3.Vec3;
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.util.FloatRangeMap;
|
|
||||||
import ru.windcorp.progressia.common.util.Vectors;
|
import ru.windcorp.progressia.common.util.Vectors;
|
||||||
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
@ -33,12 +32,12 @@ public class SurfaceTerrainGenerator {
|
|||||||
private final Surface surface;
|
private final Surface surface;
|
||||||
|
|
||||||
private final SurfaceFloatField heightMap;
|
private final SurfaceFloatField heightMap;
|
||||||
private final FloatRangeMap<TerrainLayer> layers;
|
private final TerrainSupplier terrain;
|
||||||
|
|
||||||
public SurfaceTerrainGenerator(Surface surface, SurfaceFloatField heightMap, FloatRangeMap<TerrainLayer> layers) {
|
public SurfaceTerrainGenerator(Surface surface, SurfaceFloatField heightMap, TerrainSupplier terrain) {
|
||||||
this.surface = surface;
|
this.surface = surface;
|
||||||
this.heightMap = heightMap;
|
this.heightMap = heightMap;
|
||||||
this.layers = layers;
|
this.terrain = terrain;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateTerrain(Server server, DefaultChunkData chunk) {
|
public void generateTerrain(Server server, DefaultChunkData chunk) {
|
||||||
@ -74,7 +73,7 @@ public class SurfaceTerrainGenerator {
|
|||||||
location.set(north, west, altitude);
|
location.set(north, west, altitude);
|
||||||
SurfaceBlockContext blockContext = context.push(location);
|
SurfaceBlockContext blockContext = context.push(location);
|
||||||
|
|
||||||
BlockData block = layers.get(depth).get(blockContext, depth);
|
BlockData block = terrain.get(blockContext, depth);
|
||||||
|
|
||||||
blockContext.pop();
|
blockContext.pop();
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import ru.windcorp.progressia.common.world.block.BlockData;
|
|||||||
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface TerrainLayer {
|
public interface TerrainSupplier {
|
||||||
|
|
||||||
BlockData get(SurfaceBlockContext context, float depth);
|
BlockData get(SurfaceBlockContext context, float depth);
|
||||||
|
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.server.world.tasks;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||||
|
import ru.windcorp.progressia.server.Server;
|
||||||
|
|
||||||
|
class AddEntity extends CachedChange {
|
||||||
|
|
||||||
|
private EntityData entity;
|
||||||
|
|
||||||
|
public AddEntity(Consumer<? super CachedChange> disposer) {
|
||||||
|
super(disposer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(EntityData entity) {
|
||||||
|
if (this.entity != null)
|
||||||
|
throw new IllegalStateException("Entity is not null. Current: " + this.entity + "; requested: " + entity);
|
||||||
|
|
||||||
|
this.entity = entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void affect(Server server) {
|
||||||
|
server.getWorld().spawnEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getRelevantChunk(Vec3i output) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isThreadSensitive() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
this.entity = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return System.identityHashCode(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof AddEntity))
|
||||||
|
return false;
|
||||||
|
return ((AddEntity) obj).entity == entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.server.world.tasks;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||||
|
import ru.windcorp.progressia.server.Server;
|
||||||
|
|
||||||
|
class RemoveEntity extends CachedChange {
|
||||||
|
|
||||||
|
private long entityId = EntityData.NULL_ENTITY_ID;
|
||||||
|
|
||||||
|
public RemoveEntity(Consumer<? super CachedChange> disposer) {
|
||||||
|
super(disposer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(long entityId) {
|
||||||
|
if (this.entityId != EntityData.NULL_ENTITY_ID)
|
||||||
|
throw new IllegalStateException("Entity ID is not null. Current: " + this.entityId + "; requested: " + entityId);
|
||||||
|
|
||||||
|
this.entityId = entityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void affect(Server server) {
|
||||||
|
server.getWorld().getData().removeEntity(entityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getRelevantChunk(Vec3i output) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isThreadSensitive() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
this.entityId = EntityData.NULL_ENTITY_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Long.hashCode(entityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof RemoveEntity))
|
||||||
|
return false;
|
||||||
|
return ((RemoveEntity) obj).entityId == entityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -46,6 +46,9 @@ public class WorldAccessor implements ReportingServerContext.ChangeListener {
|
|||||||
.addClass(SetBlock.class, () -> new SetBlock(disposer))
|
.addClass(SetBlock.class, () -> new SetBlock(disposer))
|
||||||
.addClass(AddTile.class, () -> new AddTile(disposer))
|
.addClass(AddTile.class, () -> new AddTile(disposer))
|
||||||
.addClass(RemoveTile.class, () -> new RemoveTile(disposer))
|
.addClass(RemoveTile.class, () -> new RemoveTile(disposer))
|
||||||
|
|
||||||
|
.addClass(AddEntity.class, () -> new AddEntity(disposer))
|
||||||
|
.addClass(RemoveEntity.class, () -> new RemoveEntity(disposer))
|
||||||
.addClass(ChangeEntity.class, () -> new ChangeEntity(disposer))
|
.addClass(ChangeEntity.class, () -> new ChangeEntity(disposer))
|
||||||
|
|
||||||
.addClass(BlockTriggeredUpdate.class, () -> new BlockTriggeredUpdate(disposer))
|
.addClass(BlockTriggeredUpdate.class, () -> new BlockTriggeredUpdate(disposer))
|
||||||
@ -81,14 +84,16 @@ public class WorldAccessor implements ReportingServerContext.ChangeListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEntityAdded(EntityData entity) {
|
public void onEntityAdded(EntityData entity) {
|
||||||
// TODO Auto-generated method stub
|
AddEntity change = cache.grab(AddEntity.class);
|
||||||
|
change.set(entity);
|
||||||
|
server.requestChange(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEntityRemoved(long entityId) {
|
public void onEntityRemoved(long entityId) {
|
||||||
// TODO Auto-generated method stub
|
RemoveEntity change = cache.grab(RemoveEntity.class);
|
||||||
|
change.set(entityId);
|
||||||
|
server.requestChange(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,7 +50,7 @@ public class LayerAbout extends GUILayer {
|
|||||||
new Label(
|
new Label(
|
||||||
"Version",
|
"Version",
|
||||||
font,
|
font,
|
||||||
new MutableStringLocalized("LayerAbout.Version").format("pre-alpha 2")
|
new MutableStringLocalized("LayerAbout.Version").format("pre-alpha 3")
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -266,12 +266,21 @@ public class LayerTestGUI extends GUILayer {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String[] CLOCK_CHARS = "\u2591\u2598\u259d\u2580\u2596\u258c\u259e\u259b\u2597\u259a\u2590\u259c\u2584\u2599\u259f\u2588"
|
||||||
|
.chars().mapToObj(c -> ((char) c) + "").toArray(String[]::new);
|
||||||
|
|
||||||
|
private static String getTPSClockChar() {
|
||||||
|
return CLOCK_CHARS[(int) (ServerState.getInstance().getUptimeTicks() % CLOCK_CHARS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
private static final Averager FPS_RECORD = new Averager();
|
private static final Averager FPS_RECORD = new Averager();
|
||||||
private static final Averager TPS_RECORD = new Averager();
|
private static final Averager TPS_RECORD = new Averager();
|
||||||
|
|
||||||
private static final Supplier<CharSequence> TPS_STRING = DynamicStrings.builder()
|
private static final Supplier<CharSequence> TPS_STRING = DynamicStrings.builder()
|
||||||
.addDyn(new MutableStringLocalized("LayerTestGUI.TPSDisplay"))
|
.addDyn(new MutableStringLocalized("LayerTestGUI.TPSDisplay"))
|
||||||
.addDyn(() -> TPS_RECORD.update(ServerState.getInstance().getTPS()), 5, 1)
|
.addDyn(() -> TPS_RECORD.update(ServerState.getInstance().getTPS()), 5, 1)
|
||||||
|
.add(' ')
|
||||||
|
.addDyn(LayerTestGUI::getTPSClockChar)
|
||||||
.buildSupplier();
|
.buildSupplier();
|
||||||
|
|
||||||
private static final Supplier<CharSequence> POS_STRING = DynamicStrings.builder()
|
private static final Supplier<CharSequence> POS_STRING = DynamicStrings.builder()
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.test;
|
||||||
|
|
||||||
|
import glm.vec._3.Vec3;
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
||||||
|
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||||
|
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||||
|
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerBlockContext;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerBlockContextRO;
|
||||||
|
import ru.windcorp.progressia.server.world.ticking.TickingPolicy;
|
||||||
|
|
||||||
|
public class TestBlockLogicStatieSpawner extends BlockLogic implements TickableBlock {
|
||||||
|
|
||||||
|
public TestBlockLogicStatieSpawner(String id) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(ServerBlockContext context) {
|
||||||
|
Vec3i loc = context.toAbsolute(context.getLocation(), null);
|
||||||
|
EntityData entity = new TestEntityDataStatie();
|
||||||
|
entity.setPosition(new Vec3(loc.x, loc.y, loc.z));
|
||||||
|
|
||||||
|
context.addEntity(entity);
|
||||||
|
context.setBlock(BlockDataRegistry.getInstance().get("Test:Air"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TickingPolicy getTickingPolicy(ServerBlockContextRO context) {
|
||||||
|
return TickingPolicy.RANDOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.test;
|
||||||
|
|
||||||
|
import glm.mat._4.Mat4;
|
||||||
|
import glm.vec._3.Vec3;
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.progressia.client.graphics.Colors;
|
||||||
|
import ru.windcorp.progressia.client.graphics.backend.Usage;
|
||||||
|
import ru.windcorp.progressia.client.graphics.model.Renderable;
|
||||||
|
import ru.windcorp.progressia.client.graphics.model.Shape;
|
||||||
|
import ru.windcorp.progressia.client.graphics.model.ShapeParts;
|
||||||
|
import ru.windcorp.progressia.client.graphics.model.Shapes;
|
||||||
|
import ru.windcorp.progressia.client.graphics.model.StaticModel;
|
||||||
|
import ru.windcorp.progressia.client.graphics.texture.ComplexTexture;
|
||||||
|
import ru.windcorp.progressia.client.graphics.texture.SimpleTextures;
|
||||||
|
import ru.windcorp.progressia.client.graphics.texture.TexturePrimitive;
|
||||||
|
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
|
||||||
|
import ru.windcorp.progressia.client.world.block.BlockRender;
|
||||||
|
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
||||||
|
|
||||||
|
public class TestBlockRenderTux extends BlockRender {
|
||||||
|
|
||||||
|
private final Renderable model;
|
||||||
|
|
||||||
|
public TestBlockRenderTux(String id) {
|
||||||
|
super(id);
|
||||||
|
|
||||||
|
TexturePrimitive primitive = SimpleTextures.get("blocks/Tux").getSprite().getPrimitive();
|
||||||
|
ComplexTexture texture = new ComplexTexture(primitive, 72, 60);
|
||||||
|
|
||||||
|
WorldRenderProgram program = WorldRenderProgram.getDefault();
|
||||||
|
StaticModel.Builder builder = StaticModel.builder();
|
||||||
|
|
||||||
|
final float scale = 1f / 40;
|
||||||
|
final float lift = -1f / 2 / scale;
|
||||||
|
|
||||||
|
builder.addPart(
|
||||||
|
new Shapes.PppBuilder(program, texture.getCuboidTextures(0, 36, 12)).setSize(12)
|
||||||
|
.centerAt(0, 0, 18 + (12 / 2) + lift).scale(scale).create()
|
||||||
|
);
|
||||||
|
builder.addPart(
|
||||||
|
new Shapes.PppBuilder(program, texture.getCuboidTextures(0, 0, 18)).setSize(18)
|
||||||
|
.centerAt(0, 0, 18 / 2 + lift).scale(scale).create()
|
||||||
|
);
|
||||||
|
builder.addPart(
|
||||||
|
new Shape(
|
||||||
|
Usage.STATIC,
|
||||||
|
program,
|
||||||
|
ShapeParts.createRectangle(
|
||||||
|
program,
|
||||||
|
texture.get(48, 44, 24, 16),
|
||||||
|
Colors.WHITE,
|
||||||
|
new Vec3(18 / 2 + 1, -(24 / 2), lift),
|
||||||
|
new Vec3(0, 24, 0),
|
||||||
|
new Vec3(0, 0, 16),
|
||||||
|
false
|
||||||
|
),
|
||||||
|
ShapeParts.createRectangle(
|
||||||
|
program,
|
||||||
|
texture.get(48, 44, 24, 16),
|
||||||
|
Colors.WHITE,
|
||||||
|
new Vec3(18 / 2 + 1, -(24 / 2), lift),
|
||||||
|
new Vec3(0, 24, 0),
|
||||||
|
new Vec3(0, 0, 16),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new Mat4().scale(scale)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.model = builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Renderable createRenderable(DefaultChunkData chunk, Vec3i relBlockInChunk) {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean needsOwnRenderable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -104,9 +104,10 @@ public class TestContent {
|
|||||||
registerSimplestBlock("Dirt");
|
registerSimplestBlock("Dirt");
|
||||||
registerSimplestBlock("Chernozem");
|
registerSimplestBlock("Chernozem");
|
||||||
registerSimplestBlock("Stone");
|
registerSimplestBlock("Stone");
|
||||||
|
registerSimplestBlock("Mantle");
|
||||||
|
registerSimplestBlock("Water");
|
||||||
registerSimplestBlock("Brick");
|
registerSimplestBlock("Brick");
|
||||||
registerSimplestBlock("BrickWhite");
|
registerSimplestBlock("BrickWhite");
|
||||||
registerSimplestBlock("Sand");
|
|
||||||
registerSimplestBlock("Concrete");
|
registerSimplestBlock("Concrete");
|
||||||
registerSimplestBlock("WoodenPlank");
|
registerSimplestBlock("WoodenPlank");
|
||||||
|
|
||||||
@ -132,6 +133,14 @@ public class TestContent {
|
|||||||
// Sic, using Glass logic for leaves because Test
|
// Sic, using Glass logic for leaves because Test
|
||||||
register(new TestBlockLogicGlass("Test:TemporaryLeaves"));
|
register(new TestBlockLogicGlass("Test:TemporaryLeaves"));
|
||||||
|
|
||||||
|
register(new BlockData("Test:StatieSpawner"));
|
||||||
|
register(new BlockRenderOpaqueCube("Test:StatieSpawner", getBlockTexture("StatieSpawner")));
|
||||||
|
register(new TestBlockLogicStatieSpawner("Test:StatieSpawner"));
|
||||||
|
|
||||||
|
register(new BlockData("Test:Tux"));
|
||||||
|
register(new TestBlockRenderTux("Test:Tux"));
|
||||||
|
register(new BlockLogic("Test:Tux"));
|
||||||
|
|
||||||
BlockDataRegistry.getInstance().values().forEach(PLACEABLE_BLOCKS::add);
|
BlockDataRegistry.getInstance().values().forEach(PLACEABLE_BLOCKS::add);
|
||||||
PLACEABLE_BLOCKS.removeIf(b -> placeableBlacklist.contains(b.getId()));
|
PLACEABLE_BLOCKS.removeIf(b -> placeableBlacklist.contains(b.getId()));
|
||||||
PLACEABLE_BLOCKS.sort(Comparator.comparing(BlockData::getId));
|
PLACEABLE_BLOCKS.sort(Comparator.comparing(BlockData::getId));
|
||||||
@ -185,7 +194,6 @@ public class TestContent {
|
|||||||
});
|
});
|
||||||
|
|
||||||
registerSimplestTransparentTile("Stones");
|
registerSimplestTransparentTile("Stones");
|
||||||
registerSimplestTransparentTile("Sand");
|
|
||||||
|
|
||||||
registerSimplestOpaqueTile("SnowOpaque");
|
registerSimplestOpaqueTile("SnowOpaque");
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
|
@ -18,26 +18,38 @@
|
|||||||
|
|
||||||
package ru.windcorp.progressia.test;
|
package ru.windcorp.progressia.test;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface;
|
||||||
import ru.windcorp.progressia.client.graphics.model.Renderable;
|
import ru.windcorp.progressia.client.graphics.model.Renderable;
|
||||||
import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper;
|
import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper;
|
||||||
import ru.windcorp.progressia.client.graphics.model.Shapes;
|
import ru.windcorp.progressia.client.graphics.model.Shapes.PppBuilder;
|
||||||
import ru.windcorp.progressia.client.graphics.texture.Texture;
|
import ru.windcorp.progressia.client.graphics.texture.ComplexTexture;
|
||||||
|
import ru.windcorp.progressia.client.graphics.texture.TexturePrimitive;
|
||||||
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
|
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
|
||||||
import ru.windcorp.progressia.client.world.entity.EntityRender;
|
import ru.windcorp.progressia.client.world.entity.EntityRender;
|
||||||
|
import ru.windcorp.progressia.client.world.entity.EntityRenderRegistry;
|
||||||
import ru.windcorp.progressia.client.world.entity.EntityRenderable;
|
import ru.windcorp.progressia.client.world.entity.EntityRenderable;
|
||||||
import ru.windcorp.progressia.common.world.entity.EntityData;
|
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||||
|
|
||||||
public class TestEntityRenderStatie extends EntityRender {
|
public class TestEntityRenderStatie extends EntityRender {
|
||||||
|
|
||||||
private final Renderable cube = new Shapes.PppBuilder(
|
private final static int PARTICLE_COUNT = 16;
|
||||||
WorldRenderProgram.getDefault(),
|
private final Renderable core;
|
||||||
(Texture) null
|
private final Renderable particle;
|
||||||
)
|
|
||||||
.setColorMultiplier(1, 1, 0)
|
|
||||||
.create();
|
|
||||||
|
|
||||||
public TestEntityRenderStatie(String id) {
|
public TestEntityRenderStatie(String id) {
|
||||||
super(id);
|
super(id);
|
||||||
|
|
||||||
|
TexturePrimitive texturePrimitive = EntityRenderRegistry.getEntityTexture("Statie");
|
||||||
|
ComplexTexture texture = new ComplexTexture(texturePrimitive, 4, 4);
|
||||||
|
WorldRenderProgram program = WorldRenderProgram.getDefault();
|
||||||
|
|
||||||
|
final float coreSize = 1f / 4;
|
||||||
|
final float particleSize = 1f / 16;
|
||||||
|
|
||||||
|
core = new PppBuilder(program, texture.getCuboidTextures(0, 2, 1)).setSize(coreSize).centerAt(0, 0, 0).create();
|
||||||
|
particle = new PppBuilder(program, texture.getCuboidTextures(0, 0, 1)).setSize(particleSize)
|
||||||
|
.centerAt(2.5f * coreSize, 0, 0).create();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -45,11 +57,28 @@ public class TestEntityRenderStatie extends EntityRender {
|
|||||||
return new EntityRenderable(entity) {
|
return new EntityRenderable(entity) {
|
||||||
@Override
|
@Override
|
||||||
public void doRender(ShapeRenderHelper renderer) {
|
public void doRender(ShapeRenderHelper renderer) {
|
||||||
|
double phase = GraphicsInterface.getTime();
|
||||||
|
renderer.pushTransform().translate(0, 0, (float) Math.sin(phase) * 0.1f);
|
||||||
|
|
||||||
renderer.pushTransform().scale(
|
renderer.pushTransform().scale(
|
||||||
((TestEntityDataStatie) entity).getSize() / 24.0f
|
((TestEntityDataStatie) entity).getSize() / 24.0f
|
||||||
);
|
).rotateY((float) -Math.sin(phase - Math.PI / 3) * Math.PI / 12);
|
||||||
|
|
||||||
cube.render(renderer);
|
core.render(renderer);
|
||||||
|
|
||||||
|
renderer.popTransform();
|
||||||
|
renderer.popTransform();
|
||||||
|
renderer.pushTransform().translate(0, 0, (float) Math.sin(phase + Math.PI / 2) * 0.05f);
|
||||||
|
|
||||||
|
for (int i = 0; i < PARTICLE_COUNT; ++i) {
|
||||||
|
double phaseOffset = 2 * Math.PI / PARTICLE_COUNT * i;
|
||||||
|
renderer.pushTransform()
|
||||||
|
.translate((float) Math.sin(phase + phaseOffset) * 0.1f, 0, 0)
|
||||||
|
.rotateX(Math.sin(phase / 2 + phaseOffset) * Math.PI / 6)
|
||||||
|
.rotateZ(phase + phaseOffset * 2);
|
||||||
|
particle.render(renderer);
|
||||||
|
renderer.popTransform();
|
||||||
|
}
|
||||||
|
|
||||||
renderer.popTransform();
|
renderer.popTransform();
|
||||||
}
|
}
|
||||||
|
@ -24,21 +24,18 @@ import java.util.List;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import ru.windcorp.progressia.common.Units;
|
import ru.windcorp.progressia.common.Units;
|
||||||
import ru.windcorp.progressia.common.util.ArrayFloatRangeMap;
|
|
||||||
import ru.windcorp.progressia.common.util.FloatRangeMap;
|
|
||||||
import ru.windcorp.progressia.common.util.noise.discrete.WorleyProceduralNoise;
|
import ru.windcorp.progressia.common.util.noise.discrete.WorleyProceduralNoise;
|
||||||
import ru.windcorp.progressia.common.world.Coordinates;
|
import ru.windcorp.progressia.common.world.Coordinates;
|
||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
|
||||||
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
|
||||||
import ru.windcorp.progressia.server.Server;
|
import ru.windcorp.progressia.server.Server;
|
||||||
import ru.windcorp.progressia.server.world.generation.WorldGenerator;
|
import ru.windcorp.progressia.server.world.generation.WorldGenerator;
|
||||||
import ru.windcorp.progressia.server.world.generation.planet.Planet;
|
import ru.windcorp.progressia.server.world.generation.planet.Planet;
|
||||||
import ru.windcorp.progressia.server.world.generation.planet.PlanetGenerator;
|
import ru.windcorp.progressia.server.world.generation.planet.PlanetGenerator;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFeature;
|
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFeature;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
|
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer;
|
import ru.windcorp.progressia.test.Rocks.Rock;
|
||||||
import ru.windcorp.progressia.test.Rocks.RockVariant;
|
|
||||||
import ru.windcorp.progressia.test.TestContent;
|
import ru.windcorp.progressia.test.TestContent;
|
||||||
|
import ru.windcorp.progressia.test.gen.feature.*;
|
||||||
|
import ru.windcorp.progressia.test.gen.terrain.*;
|
||||||
|
|
||||||
public class TestGenerationConfig {
|
public class TestGenerationConfig {
|
||||||
|
|
||||||
@ -71,47 +68,45 @@ public class TestGenerationConfig {
|
|||||||
|
|
||||||
TestHeightMap heightMap = new TestHeightMap(planet, planet.getRadius() / 4, fields);
|
TestHeightMap heightMap = new TestHeightMap(planet, planet.getRadius() / 4, fields);
|
||||||
|
|
||||||
FloatRangeMap<TerrainLayer> layers = new ArrayFloatRangeMap<>();
|
LayeredTerrain terrain = new LayeredTerrain();
|
||||||
registerTerrainLayers(layers);
|
registerTerrainLayers(terrain);
|
||||||
|
|
||||||
List<SurfaceFeature> features = new ArrayList<>();
|
List<SurfaceFeature> features = new ArrayList<>();
|
||||||
registerFeatures(features);
|
registerFeatures(features);
|
||||||
|
|
||||||
return server -> new PlanetGenerator("Test:PlanetGenerator", server, planet, heightMap, layers, features);
|
return server -> new PlanetGenerator("Test:PlanetGenerator", server, planet, heightMap, terrain, features);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerTerrainLayers(FloatRangeMap<TerrainLayer> layers) {
|
private void registerTerrainLayers(LayeredTerrain terrain) {
|
||||||
BlockData dirt = BlockDataRegistry.getInstance().get("Test:Dirt");
|
|
||||||
BlockData air = BlockDataRegistry.getInstance().get("Test:Air");
|
|
||||||
|
|
||||||
SurfaceFloatField cliffs = fields.get("Test:Cliff");
|
SurfaceFloatField cliffs = fields.get("Test:Cliff");
|
||||||
|
SurfaceFloatField beaches = fields.register(
|
||||||
|
"Test:Beach",
|
||||||
|
f -> multiply(
|
||||||
|
anti(fields.get("Test:Cliff", f))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
RockStrata rockStrata = createStrata();
|
||||||
|
|
||||||
WorleyProceduralNoise.Builder<TerrainLayer> builder = WorleyProceduralNoise.builder();
|
terrain.addLayer(new AirLayer("Test:Air"));
|
||||||
TestContent.ROCKS.getRocks().forEach(rock -> {
|
terrain.addLayer(new MantleLayer("Test:Mantle"));
|
||||||
builder.add((c, d) -> {
|
terrain.addLayer(new CrustLayer("Test:Crust", rockStrata));
|
||||||
if (c.getRandom().nextInt(3) == 0) {
|
terrain.addLayer(new WaterLayer("Test:Water"));
|
||||||
return rock.getBlock(RockVariant.CRACKED);
|
terrain.addLayer(new SoilLayer("Test:Soil"));
|
||||||
} else {
|
terrain.addLayer(new CliffLayer("Test:Cliffs", cliffs, rockStrata));
|
||||||
return rock.getBlock(RockVariant.MONOLITH);
|
terrain.addLayer(new BeachLayer("Test:Beaches", beaches, rockStrata));
|
||||||
}
|
}
|
||||||
}, 1);
|
|
||||||
});
|
private RockStrata createStrata() {
|
||||||
|
WorleyProceduralNoise.Builder<Rock> builder = WorleyProceduralNoise.builder();
|
||||||
|
TestContent.ROCKS.getRocks().forEach(rock -> builder.add(rock, 1));
|
||||||
|
|
||||||
SurfaceFloatField rockDepthOffsets = fields.register(
|
SurfaceFloatField rockDepthOffsets = fields.register(
|
||||||
"Test:RockDepthOffsets",
|
"Test:RockDepthOffsets",
|
||||||
() -> tweak(fields.primitive(), 40, 5)
|
() -> tweak(fields.primitive(), 40, 5)
|
||||||
);
|
);
|
||||||
RockLayer rockLayer = new RockLayer(builder.build(SEED), rockDepthOffsets);
|
|
||||||
|
|
||||||
layers.put(Float.NEGATIVE_INFINITY, 0, (c, d) -> air);
|
return new RockStrata(builder.build(SEED), rockDepthOffsets);
|
||||||
layers.put(0, 4, (c, d) -> {
|
|
||||||
if (cliffs.get(c.getSurface().getUp(), c.getLocation().x, c.getLocation().y) > 0) {
|
|
||||||
return rockLayer.get(c, d);
|
|
||||||
} else {
|
|
||||||
return dirt;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
layers.put(4, Float.POSITIVE_INFINITY, rockLayer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerFeatures(List<SurfaceFeature> features) {
|
private void registerFeatures(List<SurfaceFeature> features) {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package ru.windcorp.progressia.test.gen;
|
package ru.windcorp.progressia.test.gen.feature;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
@ -15,7 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package ru.windcorp.progressia.test.gen;
|
package ru.windcorp.progressia.test.gen.feature;
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
@ -15,7 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package ru.windcorp.progressia.test.gen;
|
package ru.windcorp.progressia.test.gen.feature;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
@ -15,7 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package ru.windcorp.progressia.test.gen;
|
package ru.windcorp.progressia.test.gen.feature;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -67,7 +67,6 @@ public class TestGrassFeature extends SurfaceTopLayerFeature {
|
|||||||
|
|
||||||
private final List<TileData> scatter = ImmutableList.of(
|
private final List<TileData> scatter = ImmutableList.of(
|
||||||
TileDataRegistry.getInstance().get("Test:Stones"),
|
TileDataRegistry.getInstance().get("Test:Stones"),
|
||||||
TileDataRegistry.getInstance().get("Test:Sand"),
|
|
||||||
TileDataRegistry.getInstance().get("Test:Bush"),
|
TileDataRegistry.getInstance().get("Test:Bush"),
|
||||||
TileDataRegistry.getInstance().get("Test:Fern")
|
TileDataRegistry.getInstance().get("Test:Fern")
|
||||||
);
|
);
|
||||||
@ -104,7 +103,17 @@ public class TestGrassFeature extends SurfaceTopLayerFeature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void growGrass(SurfaceBlockContext context, double grassiness) {
|
private void growGrass(SurfaceBlockContext context, double grassiness) {
|
||||||
TileData flatGrass = flatGrasses.get((float) grassiness);
|
|
||||||
|
double flatGrassiness = grassiness;
|
||||||
|
BlockData soil = context.getBlock();
|
||||||
|
if (soil.getId().endsWith("Sand")) {
|
||||||
|
flatGrassiness = flatGrassiness / 2 - 0.2;
|
||||||
|
if (flatGrassiness < 0) {
|
||||||
|
flatGrassiness = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TileData flatGrass = flatGrasses.get((float) flatGrassiness);
|
||||||
if (flatGrass != null) {
|
if (flatGrass != null) {
|
||||||
for (RelFace face : RelFace.getFaces()) {
|
for (RelFace face : RelFace.getFaces()) {
|
||||||
if (face == RelFace.DOWN)
|
if (face == RelFace.DOWN)
|
@ -15,7 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package ru.windcorp.progressia.test.gen;
|
package ru.windcorp.progressia.test.gen.feature;
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.test.gen.terrain;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
||||||
|
|
||||||
|
public class AirLayer extends TerrainLayer {
|
||||||
|
|
||||||
|
private final BlockData air = BlockDataRegistry.getInstance().get("Test:Air");
|
||||||
|
|
||||||
|
public AirLayer(String id) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockData generate(SurfaceBlockContext context, float depth, float intensity) {
|
||||||
|
return air;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getIntensity(SurfaceBlockContext context, float depth) {
|
||||||
|
return depth <= 0 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.test.gen.terrain;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
||||||
|
import ru.windcorp.progressia.test.Rocks.RockVariant;
|
||||||
|
|
||||||
|
public class BeachLayer extends TerrainLayer {
|
||||||
|
|
||||||
|
private final SurfaceFloatField beachSelector;
|
||||||
|
private final RockStrata strata;
|
||||||
|
|
||||||
|
public BeachLayer(String id, SurfaceFloatField beachSelector, RockStrata strata) {
|
||||||
|
super(id);
|
||||||
|
this.beachSelector = beachSelector;
|
||||||
|
this.strata = strata;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockData generate(SurfaceBlockContext context, float depth, float intensity) {
|
||||||
|
return strata.get(context, depth).getBlock(RockVariant.SAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getIntensity(SurfaceBlockContext context, float depth) {
|
||||||
|
if (depth < 0 || depth > 3) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float altitude = context.getLocation().z;
|
||||||
|
if (altitude < -5| altitude > 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 3 * beachSelector.get(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.test.gen.terrain;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
||||||
|
import ru.windcorp.progressia.test.Rocks.RockVariant;
|
||||||
|
|
||||||
|
public class CliffLayer extends TerrainLayer {
|
||||||
|
|
||||||
|
private final SurfaceFloatField cliffSelector;
|
||||||
|
private final RockStrata strata;
|
||||||
|
|
||||||
|
public CliffLayer(String id, SurfaceFloatField cliffSelector, RockStrata strata) {
|
||||||
|
super(id);
|
||||||
|
this.cliffSelector = cliffSelector;
|
||||||
|
this.strata = strata;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockData generate(SurfaceBlockContext context, float depth, float intensity) {
|
||||||
|
|
||||||
|
RockVariant variant;
|
||||||
|
switch (context.getRandom().nextInt(4)) {
|
||||||
|
case 0:
|
||||||
|
variant = RockVariant.GRAVEL;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
variant = RockVariant.MONOLITH;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
variant = RockVariant.CRACKED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strata.get(context, depth).getBlock(variant);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getIntensity(SurfaceBlockContext context, float depth) {
|
||||||
|
if (depth < 0 || depth > 7) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 100 * cliffSelector.get(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.test.gen.terrain;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.util.ArrayFloatRangeMap;
|
||||||
|
import ru.windcorp.progressia.common.util.FloatRangeMap;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
||||||
|
import ru.windcorp.progressia.test.Rocks.RockVariant;
|
||||||
|
|
||||||
|
public class CrustLayer extends TerrainLayer {
|
||||||
|
|
||||||
|
private static final FloatRangeMap<RockVariant> WEAR_TABLE = new ArrayFloatRangeMap<>();
|
||||||
|
static {
|
||||||
|
WEAR_TABLE.put(Float.NEGATIVE_INFINITY, 0.25f, RockVariant.MONOLITH);
|
||||||
|
WEAR_TABLE.put(0.25f, 0.5f, RockVariant.CRACKED);
|
||||||
|
WEAR_TABLE.put(0.5f, 0.75f, RockVariant.GRAVEL);
|
||||||
|
WEAR_TABLE.put(0.75f, Float.POSITIVE_INFINITY, RockVariant.SAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final RockStrata strata;
|
||||||
|
|
||||||
|
public CrustLayer(String id, RockStrata strata) {
|
||||||
|
super(id);
|
||||||
|
this.strata = strata;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockData generate(SurfaceBlockContext context, float depth, float intensity) {
|
||||||
|
|
||||||
|
RockVariant variant;
|
||||||
|
if (depth < 8) {
|
||||||
|
float wear = 1 - depth / 8;
|
||||||
|
float offset = (context.getRandom().nextFloat() * 2 - 1) * 0.5f;
|
||||||
|
variant = WEAR_TABLE.get(wear + offset);
|
||||||
|
} else {
|
||||||
|
variant = RockVariant.MONOLITH;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strata.get(context, depth).getBlock(variant);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getIntensity(SurfaceBlockContext context, float depth) {
|
||||||
|
if (depth < 0) {
|
||||||
|
return 0;
|
||||||
|
} else if (context.getLocation().z > -100) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.test.gen.terrain;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.TerrainSupplier;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
||||||
|
|
||||||
|
public class LayeredTerrain implements TerrainSupplier {
|
||||||
|
|
||||||
|
private final List<TerrainLayer> layers = new ArrayList<>();
|
||||||
|
|
||||||
|
public void addLayer(TerrainLayer layer) {
|
||||||
|
this.layers.add(layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockData get(SurfaceBlockContext context, float depth) {
|
||||||
|
TerrainLayer layer = null;
|
||||||
|
float intensity = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < layers.size(); ++i) {
|
||||||
|
TerrainLayer currentLayer = layers.get(i);
|
||||||
|
|
||||||
|
float currentIntensity = currentLayer.getIntensity(context, depth);
|
||||||
|
if (currentIntensity <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intensity < currentIntensity) {
|
||||||
|
intensity = currentIntensity;
|
||||||
|
layer = currentLayer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layer == null) {
|
||||||
|
layer = layers.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return layer.generate(context, depth, intensity);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.test.gen.terrain;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
||||||
|
|
||||||
|
public class MantleLayer extends TerrainLayer {
|
||||||
|
|
||||||
|
private final BlockData material = BlockDataRegistry.getInstance().get("Test:Mantle");
|
||||||
|
|
||||||
|
public MantleLayer(String id) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockData generate(SurfaceBlockContext context, float depth, float intensity) {
|
||||||
|
return material;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getIntensity(SurfaceBlockContext context, float depth) {
|
||||||
|
return context.getLocation().z <= -100 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -15,43 +15,38 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package ru.windcorp.progressia.test.gen;
|
package ru.windcorp.progressia.test.gen.terrain;
|
||||||
|
|
||||||
import ru.windcorp.progressia.common.util.noise.discrete.DiscreteNoise;
|
import ru.windcorp.progressia.common.util.noise.discrete.DiscreteNoise;
|
||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
|
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer;
|
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
||||||
|
import ru.windcorp.progressia.test.Rocks.Rock;
|
||||||
|
|
||||||
public class RockLayer implements TerrainLayer {
|
public class RockStrata {
|
||||||
|
|
||||||
private final DiscreteNoise<TerrainLayer> strata;
|
private final DiscreteNoise<Rock> distribution;
|
||||||
private final SurfaceFloatField depthOffsets;
|
private final SurfaceFloatField depthOffsets;
|
||||||
|
|
||||||
private final double horizontalScale = 200;
|
private final double horizontalScale = 800;
|
||||||
private final double verticalScale = 10;
|
private final double verticalScale = 20;
|
||||||
private final double depthInfluense = 0.1;
|
private final double depthInfluence = 0.1;
|
||||||
|
|
||||||
public RockLayer(DiscreteNoise<TerrainLayer> strata, SurfaceFloatField depthOffsets) {
|
public RockStrata(DiscreteNoise<Rock> distribution, SurfaceFloatField depthOffsets) {
|
||||||
this.strata = strata;
|
this.distribution = distribution;
|
||||||
this.depthOffsets = depthOffsets;
|
this.depthOffsets = depthOffsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Rock get(SurfaceBlockContext context, float depth) {
|
||||||
public BlockData get(SurfaceBlockContext context, float depth) {
|
|
||||||
|
|
||||||
double z = context.getLocation().z;
|
double z = context.getLocation().z;
|
||||||
z -= depth * depthInfluense;
|
z -= depth * depthInfluence;
|
||||||
z += depthOffsets.get(context);
|
z += depthOffsets.get(context);
|
||||||
z /= verticalScale;
|
z /= verticalScale;
|
||||||
|
|
||||||
return strata
|
return distribution.get(
|
||||||
.get(
|
|
||||||
context.getLocation().x / horizontalScale,
|
context.getLocation().x / horizontalScale,
|
||||||
context.getLocation().y / horizontalScale,
|
context.getLocation().y / horizontalScale,
|
||||||
z
|
z
|
||||||
)
|
);
|
||||||
.get(context, depth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.test.gen.terrain;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.Units;
|
||||||
|
import ru.windcorp.progressia.common.util.math.PiecewiseLinearFunction;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
||||||
|
|
||||||
|
public class SoilLayer extends TerrainLayer {
|
||||||
|
|
||||||
|
private static final PiecewiseLinearFunction THICKNESS = PiecewiseLinearFunction.builder()
|
||||||
|
.add(Units.get("-5 m"), Units.get("1 m"))
|
||||||
|
.add(Units.get("0 m"), Units.get("4 m"))
|
||||||
|
.add(Units.get("5 km"), Units.get("0 m"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private final BlockData soil = BlockDataRegistry.getInstance().get("Test:Dirt");
|
||||||
|
|
||||||
|
public SoilLayer(String id) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockData generate(SurfaceBlockContext context, float depth, float intensity) {
|
||||||
|
return soil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getIntensity(SurfaceBlockContext context, float depth) {
|
||||||
|
if (depth < 0) return 0;
|
||||||
|
|
||||||
|
float altitude = context.getLocation().z;
|
||||||
|
float thickness = THICKNESS.apply(altitude);
|
||||||
|
|
||||||
|
if (depth < thickness) {
|
||||||
|
return 2;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.test.gen.terrain;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
||||||
|
|
||||||
|
public abstract class TerrainLayer extends Namespaced {
|
||||||
|
|
||||||
|
public TerrainLayer(String id) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract BlockData generate(SurfaceBlockContext context, float depth, float intensity);
|
||||||
|
|
||||||
|
public abstract float getIntensity(SurfaceBlockContext context, float depth);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* 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 ru.windcorp.progressia.test.gen.terrain;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
||||||
|
|
||||||
|
public class WaterLayer extends TerrainLayer {
|
||||||
|
|
||||||
|
private final BlockData water = BlockDataRegistry.getInstance().get("Test:Water");
|
||||||
|
|
||||||
|
public WaterLayer(String id) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockData generate(SurfaceBlockContext context, float depth, float intensity) {
|
||||||
|
return water;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getIntensity(SurfaceBlockContext context, float depth) {
|
||||||
|
if (depth <= 0 && context.getLocation().z <= 0) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
BIN
src/main/resources/assets/textures/blocks/Mantle.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.6 KiB |
BIN
src/main/resources/assets/textures/blocks/StatieSpawner.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
src/main/resources/assets/textures/blocks/Tux.png
Normal file
After Width: | Height: | Size: 921 B |
BIN
src/main/resources/assets/textures/blocks/Water.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
src/main/resources/assets/textures/entities/Statie.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 8.6 KiB |