Added block breaking and refactored Controls
- Blocks can be broken by pointing at them at pressing LMB - Rewritten ControlTriggers - Rewritten KeyMatcher - CollisionPathComputer now has a 0.5 margin
This commit is contained in:
parent
56eaec522f
commit
cf18da8350
@ -0,0 +1,48 @@
|
||||
package ru.windcorp.progressia.client.comms.controls;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.input.InputEvent;
|
||||
import ru.windcorp.progressia.common.comms.controls.ControlData;
|
||||
import ru.windcorp.progressia.common.comms.controls.ControlDataRegistry;
|
||||
import ru.windcorp.progressia.common.comms.controls.PacketControl;
|
||||
import ru.windcorp.progressia.common.util.namespaces.NamespacedUtil;
|
||||
|
||||
public class ControlTriggerLambda extends ControlTriggerInputBased {
|
||||
|
||||
private final String packetId;
|
||||
private final Predicate<InputEvent> predicate;
|
||||
private final BiConsumer<InputEvent, ControlData> dataWriter;
|
||||
|
||||
public ControlTriggerLambda(
|
||||
String id,
|
||||
Predicate<InputEvent> predicate,
|
||||
BiConsumer<InputEvent, ControlData> dataWriter
|
||||
) {
|
||||
super(id);
|
||||
|
||||
this.packetId = NamespacedUtil.getId(
|
||||
NamespacedUtil.getNamespace(id),
|
||||
"ControlKeyPress" + NamespacedUtil.getName(id)
|
||||
);
|
||||
|
||||
this.predicate = predicate;
|
||||
this.dataWriter = dataWriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketControl onInputEvent(InputEvent event) {
|
||||
if (!predicate.test(event)) return null;
|
||||
|
||||
PacketControl packet = new PacketControl(
|
||||
packetId,
|
||||
ControlDataRegistry.getInstance().create(getId())
|
||||
);
|
||||
|
||||
dataWriter.accept(event, packet.getControl());
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
package ru.windcorp.progressia.client.comms.controls;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.input.InputEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.KeyEvent;
|
||||
import ru.windcorp.progressia.common.comms.controls.ControlDataRegistry;
|
||||
import ru.windcorp.progressia.common.comms.controls.PacketControl;
|
||||
import ru.windcorp.progressia.common.util.namespaces.NamespacedUtil;
|
||||
|
||||
public class ControlTriggerOnKeyPress extends ControlTriggerInputBased {
|
||||
|
||||
private final Predicate<KeyEvent> predicate;
|
||||
private final PacketControl packet;
|
||||
|
||||
public ControlTriggerOnKeyPress(
|
||||
String id,
|
||||
Predicate<KeyEvent> predicate
|
||||
) {
|
||||
super(id);
|
||||
this.predicate = predicate;
|
||||
this.packet = new PacketControl(
|
||||
NamespacedUtil.getId(getNamespace(), "ControlKeyPress" + getName()),
|
||||
ControlDataRegistry.getInstance().get(getId())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketControl onInputEvent(InputEvent event) {
|
||||
if (!(event instanceof KeyEvent)) return null;
|
||||
|
||||
KeyEvent keyEvent = (KeyEvent) event;
|
||||
|
||||
if (!keyEvent.isPress()) return null;
|
||||
if (!predicate.test(keyEvent)) return null;
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,176 @@
|
||||
package ru.windcorp.progressia.client.comms.controls;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.input.InputEvent;
|
||||
import ru.windcorp.progressia.common.comms.controls.ControlData;
|
||||
|
||||
public class ControlTriggers {
|
||||
|
||||
public static ControlTriggerInputBased of(
|
||||
String id,
|
||||
BiConsumer<InputEvent, ControlData> dataWriter,
|
||||
Predicate<InputEvent> predicate
|
||||
) {
|
||||
return new ControlTriggerLambda(id, predicate, dataWriter);
|
||||
}
|
||||
|
||||
public static ControlTriggerInputBased of(
|
||||
String id,
|
||||
Consumer<ControlData> dataWriter,
|
||||
Predicate<InputEvent> predicate
|
||||
) {
|
||||
return of(
|
||||
id,
|
||||
(input, control) -> dataWriter.accept(control),
|
||||
predicate
|
||||
);
|
||||
}
|
||||
|
||||
public static ControlTriggerInputBased of(
|
||||
String id,
|
||||
Predicate<InputEvent> predicate
|
||||
) {
|
||||
return of(
|
||||
id,
|
||||
(input, control) -> {},
|
||||
predicate
|
||||
);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static <I extends InputEvent> ControlTriggerInputBased of(
|
||||
String id,
|
||||
Class<I> inputType,
|
||||
BiConsumer<I, ControlData> dataWriter,
|
||||
Predicate<I>... predicates
|
||||
) {
|
||||
return of(
|
||||
id,
|
||||
createCheckedDataWriter(inputType, dataWriter),
|
||||
createCheckedCompoundPredicate(inputType, predicates)
|
||||
);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static <I extends InputEvent> ControlTriggerInputBased of(
|
||||
String id,
|
||||
Class<I> inputType,
|
||||
Consumer<ControlData> dataWriter,
|
||||
Predicate<I>... predicates
|
||||
) {
|
||||
return of(
|
||||
id,
|
||||
inputType,
|
||||
(input, control) -> dataWriter.accept(control),
|
||||
predicates
|
||||
);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static <I extends InputEvent> ControlTriggerInputBased of(
|
||||
String id,
|
||||
Class<I> inputType,
|
||||
Predicate<I>... predicates
|
||||
) {
|
||||
return of(
|
||||
id,
|
||||
(input, control) -> {},
|
||||
createCheckedCompoundPredicate(inputType, predicates)
|
||||
);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static ControlTriggerInputBased of(
|
||||
String id,
|
||||
BiConsumer<InputEvent, ControlData> dataWriter,
|
||||
Predicate<InputEvent>... predicates
|
||||
) {
|
||||
return of(
|
||||
id,
|
||||
InputEvent.class,
|
||||
dataWriter,
|
||||
predicates
|
||||
);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static <I extends InputEvent> ControlTriggerInputBased of(
|
||||
String id,
|
||||
Consumer<ControlData> dataWriter,
|
||||
Predicate<InputEvent>... predicates
|
||||
) {
|
||||
return of(
|
||||
id,
|
||||
(input, control) -> dataWriter.accept(control),
|
||||
predicates
|
||||
);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static ControlTriggerInputBased of(
|
||||
String id,
|
||||
Predicate<InputEvent>... predicates
|
||||
) {
|
||||
return of(
|
||||
id,
|
||||
InputEvent.class,
|
||||
(input, control) -> {},
|
||||
predicates
|
||||
);
|
||||
}
|
||||
|
||||
private static
|
||||
<I extends InputEvent>
|
||||
BiConsumer<InputEvent, ControlData>
|
||||
createCheckedDataWriter(
|
||||
Class<I> inputType,
|
||||
BiConsumer<I, ControlData> dataWriter
|
||||
) {
|
||||
return (inputEvent, control) -> dataWriter.accept(inputType.cast(inputEvent), control);
|
||||
}
|
||||
|
||||
private static
|
||||
<I extends InputEvent>
|
||||
Predicate<InputEvent>
|
||||
createCheckedCompoundPredicate(
|
||||
Class<I> inputType,
|
||||
Predicate<I>[] predicates
|
||||
) {
|
||||
return new CompoundCastPredicate<>(inputType, predicates);
|
||||
}
|
||||
|
||||
private static class CompoundCastPredicate<I extends InputEvent> implements Predicate<InputEvent> {
|
||||
|
||||
private final Class<I> inputType;
|
||||
private final Predicate<I>[] predicates;
|
||||
|
||||
public CompoundCastPredicate(Class<I> inputType, Predicate<I>[] predicates) {
|
||||
this.inputType = inputType;
|
||||
this.predicates = predicates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(InputEvent inputEvent) {
|
||||
if (!inputType.isInstance(inputEvent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
I castEvent = inputType.cast(inputEvent);
|
||||
|
||||
for (Predicate<I> predicate : predicates) {
|
||||
if (!predicate.test(castEvent)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private ControlTriggers() {}
|
||||
|
||||
}
|
@ -17,46 +17,24 @@
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.progressia.client.graphics.input;
|
||||
|
||||
import gnu.trove.set.TIntSet;
|
||||
import ru.windcorp.progressia.client.graphics.backend.InputTracker;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
public class KeyMatcher {
|
||||
|
||||
private final int key;
|
||||
private final int[] additionalKeys;
|
||||
private final int mods;
|
||||
|
||||
public KeyMatcher(int key, int[] additionalKeys, int mods) {
|
||||
protected KeyMatcher(int key, int mods) {
|
||||
this.key = key;
|
||||
this.additionalKeys = additionalKeys;
|
||||
this.mods = mods;
|
||||
}
|
||||
|
||||
public KeyMatcher(KeyEvent template, int... additionalKeys) {
|
||||
this(template.getKey(), additionalKeys, template.getMods());
|
||||
}
|
||||
|
||||
public static KeyMatcher createKeyMatcher(KeyEvent template) {
|
||||
return new KeyMatcher(
|
||||
template,
|
||||
InputTracker.getPressedKeys().toArray()
|
||||
);
|
||||
}
|
||||
|
||||
public boolean matches(KeyEvent event) {
|
||||
if (!event.isPress()) return false;
|
||||
if (event.getKey() != getKey()) return false;
|
||||
if (event.getMods() != getMods()) return false;
|
||||
|
||||
TIntSet pressedKeys = InputTracker.getPressedKeys();
|
||||
|
||||
if (pressedKeys.size() != additionalKeys.length) return false;
|
||||
|
||||
for (int additionalKey : additionalKeys) {
|
||||
if (!pressedKeys.contains(additionalKey)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ((event.getMods() & getMods()) != getMods()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -65,12 +43,52 @@ public class KeyMatcher {
|
||||
return key;
|
||||
}
|
||||
|
||||
public int[] getAdditionalKeys() {
|
||||
return additionalKeys;
|
||||
}
|
||||
|
||||
public int getMods() {
|
||||
return mods;
|
||||
}
|
||||
|
||||
public static KeyMatcher.Builder of(int key) {
|
||||
return new KeyMatcher.Builder(key);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private final int key;
|
||||
private int mods = 0;
|
||||
|
||||
public Builder(int key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public Builder with(int modifier) {
|
||||
this.mods += modifier;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withShift() {
|
||||
return with(GLFW.GLFW_MOD_SHIFT);
|
||||
}
|
||||
|
||||
public Builder withCtrl() {
|
||||
return with(GLFW.GLFW_MOD_CONTROL);
|
||||
}
|
||||
|
||||
public Builder withAlt() {
|
||||
return with(GLFW.GLFW_MOD_ALT);
|
||||
}
|
||||
|
||||
public Builder withSuper() {
|
||||
return with(GLFW.GLFW_MOD_SUPER);
|
||||
}
|
||||
|
||||
public KeyMatcher build() {
|
||||
return new KeyMatcher(key, mods);
|
||||
}
|
||||
|
||||
public Predicate<KeyEvent> matcher() {
|
||||
return build()::matches;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ import static java.lang.Math.*;
|
||||
|
||||
public class CollisionPathComputer {
|
||||
|
||||
private static final float PADDING = 0.5f;
|
||||
|
||||
public static void forEveryBlockInCollisionPath(
|
||||
Collideable coll,
|
||||
float maxTime,
|
||||
@ -52,18 +54,18 @@ public class CollisionPathComputer {
|
||||
Vec3i pos = Vectors.grab3i();
|
||||
|
||||
for (
|
||||
pos.x = (int) floor(origin.x + min(0, size.x) + min(0, displacement.x));
|
||||
pos.x <= (int) ceil(origin.x + max(0, size.x) + max(0, displacement.x));
|
||||
pos.x = (int) floor(origin.x + min(0, size.x) + min(0, displacement.x) - PADDING);
|
||||
pos.x <= (int) ceil(origin.x + max(0, size.x) + max(0, displacement.x) + PADDING);
|
||||
pos.x += 1
|
||||
) {
|
||||
for (
|
||||
pos.y = (int) floor(origin.y + min(0, size.y) + min(0, displacement.y));
|
||||
pos.y <= (int) ceil(origin.y + max(0, size.y) + max(0, displacement.y));
|
||||
pos.y = (int) floor(origin.y + min(0, size.y) + min(0, displacement.y) - PADDING);
|
||||
pos.y <= (int) ceil(origin.y + max(0, size.y) + max(0, displacement.y) + PADDING);
|
||||
pos.y += 1
|
||||
) {
|
||||
for (
|
||||
pos.z = (int) floor(origin.z + min(0, size.z) + min(0, displacement.z));
|
||||
pos.z <= (int) ceil(origin.z + max(0, size.z) + max(0, displacement.z));
|
||||
pos.z = (int) floor(origin.z + min(0, size.z) + min(0, displacement.z) - PADDING);
|
||||
pos.z <= (int) ceil(origin.z + max(0, size.z) + max(0, displacement.z) + PADDING);
|
||||
pos.z += 1
|
||||
) {
|
||||
action.accept(pos);
|
||||
|
@ -1,8 +1,8 @@
|
||||
package ru.windcorp.progressia.common.comms.controls;
|
||||
|
||||
import ru.windcorp.progressia.common.util.namespaces.NamespacedInstanceRegistry;
|
||||
import ru.windcorp.progressia.common.util.namespaces.NamespacedFactoryRegistry;
|
||||
|
||||
public class ControlDataRegistry extends NamespacedInstanceRegistry<ControlData> {
|
||||
public class ControlDataRegistry extends NamespacedFactoryRegistry<ControlData> {
|
||||
|
||||
private static final ControlDataRegistry INSTANCE = new ControlDataRegistry();
|
||||
|
||||
|
@ -7,6 +7,15 @@ import ru.windcorp.progressia.server.comms.Client;
|
||||
|
||||
public abstract class ControlLogic extends Namespaced {
|
||||
|
||||
@FunctionalInterface
|
||||
public static interface Lambda {
|
||||
void apply(
|
||||
Server server,
|
||||
PacketControl packet,
|
||||
Client client
|
||||
);
|
||||
}
|
||||
|
||||
public ControlLogic(String id) {
|
||||
super(id);
|
||||
}
|
||||
@ -17,4 +26,13 @@ public abstract class ControlLogic extends Namespaced {
|
||||
Client client
|
||||
);
|
||||
|
||||
public static ControlLogic of(String id, Lambda logic) {
|
||||
return new ControlLogic(id) {
|
||||
@Override
|
||||
public void apply(Server server, PacketControl packet, Client client) {
|
||||
logic.apply(server, packet, client);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
package ru.windcorp.progressia.test;
|
||||
|
||||
import glm.vec._3.i.Vec3i;
|
||||
import ru.windcorp.progressia.common.comms.controls.ControlData;
|
||||
|
||||
public class ControlBreakBlockData extends ControlData {
|
||||
|
||||
private final Vec3i blockInWorld = new Vec3i();
|
||||
|
||||
public ControlBreakBlockData(String id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public Vec3i getBlockInWorld() {
|
||||
return blockInWorld;
|
||||
}
|
||||
|
||||
public void setBlockInWorld(Vec3i blockInWorld) {
|
||||
this.blockInWorld.set(blockInWorld.x, blockInWorld.y, blockInWorld.z);
|
||||
}
|
||||
|
||||
}
|
@ -8,8 +8,11 @@ import java.util.function.Consumer;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import glm.vec._3.i.Vec3i;
|
||||
import ru.windcorp.progressia.client.ClientState;
|
||||
import ru.windcorp.progressia.client.comms.controls.*;
|
||||
import ru.windcorp.progressia.client.graphics.input.KeyEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.KeyMatcher;
|
||||
import ru.windcorp.progressia.client.graphics.world.LocalPlayer;
|
||||
import ru.windcorp.progressia.client.world.block.*;
|
||||
import ru.windcorp.progressia.client.world.entity.*;
|
||||
import ru.windcorp.progressia.client.world.tile.*;
|
||||
@ -21,8 +24,6 @@ import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.block.*;
|
||||
import ru.windcorp.progressia.common.world.entity.*;
|
||||
import ru.windcorp.progressia.common.world.tile.*;
|
||||
import ru.windcorp.progressia.server.Server;
|
||||
import ru.windcorp.progressia.server.comms.Client;
|
||||
import ru.windcorp.progressia.server.comms.controls.*;
|
||||
import ru.windcorp.progressia.server.world.block.*;
|
||||
import ru.windcorp.progressia.server.world.entity.*;
|
||||
@ -88,7 +89,7 @@ public class TestContent {
|
||||
|
||||
private static void registerEntities() {
|
||||
float scale = 1.8f / 8;
|
||||
registerEntityData("Test:Player", e -> e.setCollisionModel(new AABB(0, 0, 4*scale, 0.75f, 0.75f, 1.8f)));
|
||||
registerEntityData("Test:Player", e -> e.setCollisionModel(new AABB(0, 0, 4*scale, 0.8f, 0.8f, 1.8f)));
|
||||
register(new TestEntityRenderHuman("Test:Player"));
|
||||
register(new EntityLogic("Test:Player"));
|
||||
|
||||
@ -98,25 +99,43 @@ public class TestContent {
|
||||
}
|
||||
|
||||
private static void regsiterControls() {
|
||||
ControlDataRegistry.getInstance().register(new ControlData("Test:Switch000"));
|
||||
ControlTriggerRegistry.getInstance().register(new ControlTriggerOnKeyPress("Test:Switch000", new KeyMatcher(GLFW.GLFW_KEY_H, new int[0], 0)::matches));
|
||||
ControlLogicRegistry.getInstance().register(new ControlLogic("Test:Switch000") {
|
||||
@Override
|
||||
public void apply(Server server, PacketControl packet, Client client) {
|
||||
Vec3i z000 = new Vec3i(0, 0, 0);
|
||||
ControlDataRegistry data = ControlDataRegistry.getInstance();
|
||||
ControlTriggerRegistry triggers = ControlTriggerRegistry.getInstance();
|
||||
ControlLogicRegistry logic = ControlLogicRegistry.getInstance();
|
||||
|
||||
ChunkData data = server.getWorld().getChunk(z000).getData();
|
||||
data.register("Test:Switch000", ControlData::new);
|
||||
triggers.register(ControlTriggers.of(
|
||||
"Test:Switch000",
|
||||
KeyEvent.class,
|
||||
KeyMatcher.of(GLFW.GLFW_KEY_H).matcher()
|
||||
));
|
||||
logic.register(ControlLogic.of("Test:Switch000", (server, packet, client) -> {
|
||||
Vec3i z000 = new Vec3i(0, 0, 0);
|
||||
|
||||
BlockData block;
|
||||
if (data.getBlock(z000).getId().equals("Test:Stone")) {
|
||||
block = BlockDataRegistry.getInstance().get("Test:Glass");
|
||||
} else {
|
||||
block = BlockDataRegistry.getInstance().get("Test:Stone");
|
||||
}
|
||||
ChunkData chunk = server.getWorld().getChunk(z000).getData();
|
||||
|
||||
server.getAdHocChanger().setBlock(z000, block);
|
||||
BlockData block;
|
||||
if (chunk.getBlock(z000).getId().equals("Test:Stone")) {
|
||||
block = BlockDataRegistry.getInstance().get("Test:Glass");
|
||||
} else {
|
||||
block = BlockDataRegistry.getInstance().get("Test:Stone");
|
||||
}
|
||||
});
|
||||
|
||||
server.getAdHocChanger().setBlock(z000, block);
|
||||
}));
|
||||
|
||||
data.register("Test:BreakBlock", ControlBreakBlockData::new);
|
||||
triggers.register(ControlTriggers.of(
|
||||
"Test:BreakBlock",
|
||||
KeyEvent.class,
|
||||
TestContent::onBlockBreakTrigger,
|
||||
KeyMatcher.of(GLFW.GLFW_MOUSE_BUTTON_LEFT).matcher(),
|
||||
i -> getLookingAt() != null
|
||||
));
|
||||
logic.register(ControlLogic.of("Test:BreakBlock", (server, packet, client) -> {
|
||||
Vec3i blockInWorld = ((ControlBreakBlockData) packet.getControl()).getBlockInWorld();
|
||||
server.getAdHocChanger().setBlock(blockInWorld, BlockDataRegistry.getInstance().get("Test:Air"));
|
||||
}));
|
||||
}
|
||||
|
||||
private static void register(BlockData x) {
|
||||
@ -172,4 +191,18 @@ public class TestContent {
|
||||
EntityLogicRegistry.getInstance().register(x);
|
||||
}
|
||||
|
||||
private static Vec3i getLookingAt() {
|
||||
ru.windcorp.progressia.client.Client client = ClientState.getInstance();
|
||||
if (client == null) return null;
|
||||
|
||||
LocalPlayer player = client.getLocalPlayer();
|
||||
if (player == null) return null;
|
||||
|
||||
return player.getLookingAt();
|
||||
}
|
||||
|
||||
private static void onBlockBreakTrigger(ControlData control) {
|
||||
((ControlBreakBlockData) control).setBlockInWorld(getLookingAt());
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user