Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/main/java/cam72cam/immersiverailroading/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,12 @@ public static class ConfigDebug {

@Comment("Does stock drops itself/components when player is in creative mode?")
public static boolean stockDropInCreativeMode = true;

@Comment("Enable track snapping")
public static boolean enableTrackSnapping = false;

@Comment("Should track snapping also snap angle")
public static boolean trackSnapAngle = false;
}

public static boolean isFuelRequired(Gauge gauge) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package cam72cam.immersiverailroading.items;

import cam72cam.immersiverailroading.Config;
import cam72cam.immersiverailroading.IRBlocks;
import cam72cam.immersiverailroading.ImmersiveRailroading;
import cam72cam.immersiverailroading.library.GuiTypes;
import cam72cam.immersiverailroading.tile.TileRailBase;
import cam72cam.immersiverailroading.tile.TileRailPreview;
import cam72cam.immersiverailroading.util.TrackUtil;
import cam72cam.immersiverailroading.util.BlockUtil;
import cam72cam.immersiverailroading.util.PlacementInfo;
import cam72cam.mod.item.*;
Expand Down Expand Up @@ -49,21 +51,31 @@ public ClickResult onClickBlock(Player player, World world, Vec3i pos, Player.Ha
d.write();
Audio.playSound(world, pos, StandardSound.BLOCK_ANVIL_PLACE, SoundCategory.BLOCKS, 0.5f, 0.2f);
} else {
pos = pos.up();

Vec3i tepos = new Data(held).pos;
if (tepos != null) {
if (BlockUtil.canBeReplaced(world, pos.down(), true)) {
if (!BlockUtil.isIRRail(world, pos.down()) || world.getBlockEntity(pos.down(), TileRailBase.class).getRailHeight() < 0.5) {
pos = pos.down();
}
}
TileRailPreview tr = world.getBlockEntity(tepos, TileRailPreview.class);
if (tr != null) {
PlacementInfo info = TrackUtil.getNeighborNode(player, player.getWorld(), pos, hit, tr.getItem());
boolean useSnapping = info != null && Config.ConfigDebug.enableTrackSnapping;
float yaw;
if(useSnapping) {
pos = new Vec3i(info.placementPosition);
hit = info.placementPosition.subtract(pos);
yaw = info.yaw;
} else {
pos = pos.up();
if (BlockUtil.canBeReplaced(world, pos.down(), true)) {
if (!BlockUtil.isIRRail(world, pos.down()) || world.getBlockEntity(pos.down(), TileRailBase.class).getRailHeight() < 0.5) {
pos = pos.down();
}
}
yaw = player.getRotationYawHead();
}
if (tr.isAboveRails()) {
tepos = tepos.down();
}
tr.setCustomInfo(new PlacementInfo(tr.getItem(), player.getYawHead(), hit.subtract(0, hit.y, 0).add(pos).subtract(tepos)));
tr.setCustomInfo(new PlacementInfo(tr.getItem(), yaw, hit.subtract(0, hit.y, 0).add(pos).subtract(tepos), useSnapping));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package cam72cam.immersiverailroading.items;

import cam72cam.immersiverailroading.Config;
import cam72cam.immersiverailroading.IRBlocks;
import cam72cam.immersiverailroading.ImmersiveRailroading;
import cam72cam.immersiverailroading.items.nbt.RailSettings;
Expand All @@ -9,6 +10,7 @@
import cam72cam.immersiverailroading.registry.TrackDefinition;
import cam72cam.immersiverailroading.tile.TileRailBase;
import cam72cam.immersiverailroading.tile.TileRailPreview;
import cam72cam.immersiverailroading.util.TrackUtil;
import cam72cam.immersiverailroading.util.BlockUtil;
import cam72cam.immersiverailroading.util.IRFuzzy;
import cam72cam.immersiverailroading.util.PlacementInfo;
Expand Down Expand Up @@ -55,7 +57,9 @@ public void onClickAir(Player player, World world, Player.Hand hand) {
@Override
public ClickResult onClickBlock(Player player, World world, Vec3i pos, Player.Hand hand, Facing facing, Vec3d hit) {
ItemStack stack = player.getHeldItem(hand);
PlacementInfo snapped = TrackUtil.getNeighborNode(player, player.getWorld(), pos, hit, stack);
RailSettings stackInfo = RailSettings.from(stack);
float yaw;

if (world.isServer && hand == Player.Hand.SECONDARY) {
ItemStack blockinfo = world.getItemStack(pos);
Expand All @@ -68,11 +72,19 @@ public ClickResult onClickBlock(Player player, World world, Vec3i pos, Player.Ha
return ClickResult.ACCEPTED;
}

pos = pos.up();

if (BlockUtil.canBeReplaced(world, pos.down(), true)) {
if (!BlockUtil.isIRRail(world, pos.down()) || world.getBlockEntity(pos.down(), TileRailBase.class).getRailHeight() < 0.5) {
pos = pos.down();
boolean useSnapping = snapped != null && Config.ConfigDebug.enableTrackSnapping;
if(useSnapping) {
pos = new Vec3i(snapped.placementPosition);
hit = snapped.placementPosition.subtract(pos);
yaw = snapped.yaw;
} else {
pos = pos.up();
yaw = player.getRotationYawHead();

if (BlockUtil.canBeReplaced(world, pos.down(), true)) {
if (!BlockUtil.isIRRail(world, pos.down()) || world.getBlockEntity(pos.down(), TileRailBase.class).getRailHeight() < 0.5) {
pos = pos.down();
}
}
}

Expand All @@ -83,13 +95,13 @@ public ClickResult onClickBlock(Player player, World world, Vec3i pos, Player.Ha
world.setBlock(pos, IRBlocks.BLOCK_RAIL_PREVIEW);
TileRailPreview te = world.getBlockEntity(pos, TileRailPreview.class);
if (te != null) {
PlacementInfo placementInfo = new PlacementInfo(stack, player.getYawHead(), hit.subtract(0, hit.y, 0));
PlacementInfo placementInfo = new PlacementInfo(stack, yaw, hit.subtract(0, hit.y, 0), useSnapping);
te.setup(stack, placementInfo);
}
return ClickResult.ACCEPTED;
}

PlacementInfo placementInfo = new PlacementInfo(stack, player.getYawHead(), hit.subtract(0, hit.y, 0));
PlacementInfo placementInfo = new PlacementInfo(stack, yaw, hit.subtract(0, hit.y, 0), useSnapping);
RailInfo info = new RailInfo(stack, placementInfo, null);
info.build(player, pos);
return ClickResult.ACCEPTED;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package cam72cam.immersiverailroading.render.item;

import cam72cam.immersiverailroading.Config;
import cam72cam.immersiverailroading.util.TrackUtil;
import cam72cam.immersiverailroading.library.TrackItems;
import cam72cam.immersiverailroading.render.ExpireableMap;
import cam72cam.immersiverailroading.render.rail.RailRender;
Expand Down Expand Up @@ -55,18 +57,33 @@ public static void render(ItemStack stack, World world, RenderState state) {

private static ExpireableMap<String, RailInfo> infoCache = new ExpireableMap<>();
public static void renderMouseover(Player player, ItemStack stack, Vec3i pos, Vec3d vec, RenderState state, float partialTicks) {
Vec3d hit = vec.subtract(pos);
World world = player.getWorld();
Vec3d cameraPos = GlobalRender.getCameraPos(partialTicks);

PlacementInfo closeEnd = TrackUtil.getNeighborNode(player, world, pos, vec.subtract(pos), stack);
boolean useSnapping = closeEnd != null && Config.ConfigDebug.enableTrackSnapping;

pos = pos.up();
Vec3d hit;
float yaw;

if (BlockUtil.canBeReplaced(world, pos.down(), true)) {
if (!BlockUtil.isIRRail(world, pos.down()) || world.getBlockEntity(pos.down(), TileRailBase.class).getRailHeight() < 0.5) {
pos = pos.down();
if (!useSnapping) {
hit = vec.subtract(pos);
pos = pos.up();

if (BlockUtil.canBeReplaced(world, pos.down(), true)) {
if (!BlockUtil.isIRRail(world, pos.down()) || world.getBlockEntity(pos.down(), TileRailBase.class).getRailHeight() < 0.5) {
pos = pos.down();
}
}

yaw = player.getRotationYawHead();
} else {
pos = new Vec3i(closeEnd.placementPosition);
hit = closeEnd.placementPosition.subtract(pos);
yaw = closeEnd.yaw;
}

RailInfo info = new RailInfo(stack, new PlacementInfo(stack, player.getRotationYawHead(), hit.subtract(0, hit.y, 0)), null);
RailInfo info = new RailInfo(stack, new PlacementInfo(stack, yaw, hit.subtract(0, hit.y, 0), useSnapping), null);
String key = info.uniqueID + info.placementInfo.placementPosition;
RailInfo cached = infoCache.get(key);
if (cached != null) {
Expand All @@ -77,8 +94,6 @@ public static void renderMouseover(Player player, ItemStack stack, Vec3i pos, Ve

state.blend(new BlendMode(BlendMode.GL_CONSTANT_ALPHA, BlendMode.GL_ONE).constantColor(1, 1, 1, 0.5f)).lightmap(1, 1);


Vec3d cameraPos = GlobalRender.getCameraPos(partialTicks);
Vec3d offPos = info.placementInfo.placementPosition.add(pos).subtract(cameraPos);
state.translate(offPos.x, offPos.y, offPos.z);

Expand Down
85 changes: 44 additions & 41 deletions src/main/java/cam72cam/immersiverailroading/util/PlacementInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public static int segmentation() {
}

public PlacementInfo(ItemStack stack, float yawHead, Vec3d hit) {
this(stack, yawHead, hit, false);
}
public PlacementInfo(ItemStack stack, float yawHead, Vec3d hit, boolean snapping) {
yawHead = ((- yawHead % 360) + 360) % 360;
this.yaw = ((int)((yawHead + 90/(segmentation() * 2f)) * segmentation())) / 90 * 90 / (segmentation() * 1f);

Expand All @@ -44,59 +47,59 @@ public PlacementInfo(ItemStack stack, float yawHead, Vec3d hit) {

double hitX = hit.x % 1;
double hitZ = hit.z % 1;

switch (settings.posType) {
case FIXED:
hitX = 0.5f;
hitZ = 0.5f;
break;
case PIXELS:
hitX = ((int) (hitX * 16)) / 16f;
hitZ = ((int) (hitZ * 16)) / 16f;
//Fall through
case SMOOTH:
if (hit.z < 0) {
hitZ += 1;
}
if (hit.x < 0) {
hitX += 1;
}
break;
case PIXELS_LOCKED:
hitX = ((int) (hitX * 16)) / 16f;
hitZ = ((int) (hitZ * 16)) / 16f;
//Fall through
case SMOOTH_LOCKED:
if (quarter != 0) {
if (!snapping) {
switch (settings.posType) {
case FIXED:
hitX = 0.5f;
hitZ = 0.5f;
break;
case PIXELS:
hitX = ((int) (hitX * 16)) / 16f;
hitZ = ((int) (hitZ * 16)) / 16f;
//Fall through
case SMOOTH:
if (hit.z < 0) {
hitZ += 1;
}
if (hit.x < 0) {
hitX += 1;
}
break;
}

switch (facing()) {
case EAST:
case WEST:
hitZ = 0.5f;
if (hit.x < 0) {
hitX += 1;
}
break;
case NORTH:
case SOUTH:
hitX = 0.5f;
case PIXELS_LOCKED:
hitX = ((int) (hitX * 16)) / 16f;
hitZ = ((int) (hitZ * 16)) / 16f;
//Fall through
case SMOOTH_LOCKED:
if (quarter != 0) {
if (hit.z < 0) {
hitZ += 1;
}
if (hit.x < 0) {
hitX += 1;
}
break;
default:
}
break;
}
}

switch (facing()) {
case EAST:
case WEST:
hitZ = 0.5f;
if (hit.x < 0) {
hitX += 1;
}
break;
case NORTH:
case SOUTH:
hitX = 0.5f;
if (hit.z < 0) {
hitZ += 1;
}
break;
default:
}
break;
}
}
this.placementPosition = new Vec3d(new Vec3i(hit)).add(hitX, 0, hitZ);
this.direction = direction;
this.control = null;
Expand Down
95 changes: 95 additions & 0 deletions src/main/java/cam72cam/immersiverailroading/util/TrackUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package cam72cam.immersiverailroading.util;

import cam72cam.immersiverailroading.Config;
import cam72cam.immersiverailroading.items.nbt.RailSettings;
import cam72cam.immersiverailroading.library.TrackDirection;
import cam72cam.immersiverailroading.tile.TileRail;
import cam72cam.immersiverailroading.tile.TileRailBase;
import cam72cam.immersiverailroading.track.BuilderBase;
import cam72cam.immersiverailroading.track.VecYPR;
import cam72cam.mod.entity.Player;
import cam72cam.mod.item.ItemStack;
import cam72cam.mod.math.Vec3d;
import cam72cam.mod.math.Vec3i;
import cam72cam.mod.world.World;

import java.util.List;

public class TrackUtil {
public static PlacementInfo getNeighborNode(Player player, World world, Vec3i pos, Vec3d hit, ItemStack stack) {
RailSettings stackInfo = RailSettings.from(stack);
Vec3d worldPos = new Vec3d(pos).add(hit);
Vec3d minPos = worldPos;
double min = Double.MAX_VALUE;
int hori = Math.max((int) (stackInfo.gauge.scale() * 2), 1);
int vert = 1;
float yaw = player.getRotationYaw();
float rotationYawHead = (player.getRotationYawHead() + 360f) % 360f;

for (int x = -hori; x <= hori; x++) {
for (int y = -vert; y <= vert; y++) {
for (int z = -hori; z <= hori; z++) {
Vec3i offset = pos.add(x, y, z);
TileRailBase tile = world.getBlockEntity(offset, TileRailBase.class);
while (tile != null){
if (!(tile instanceof TileRail)) {
tile = tile.getParentTile();
}

TileRail rail = (TileRail) tile;
if (rail == null || rail.info == null ||
Math.abs(rail.getTrackGauge() - stackInfo.gauge.value()) > 1.0E-6) continue;

BuilderBase builder = rail.info.getBuilder(world);
List<VecYPR> renderData = builder.getRenderData();
if (renderData.isEmpty()) continue;

if (renderData.size() > 1) {
Vec3d p1 = renderData.get(0).add(rail.info.placementInfo.placementPosition).add(
tile.getPos());
float yaw1 = VecUtil.toYaw(renderData.get(1).subtract(renderData.get(0)));
double dist1 = p1.distanceTo(worldPos);
if (dist1 < min) {
min = dist1;
minPos = p1;
yaw = yaw1;
}

Vec3d p2 = renderData.get(renderData.size() - 1)
.add(rail.info.placementInfo.placementPosition).add(tile.getPos());
float yaw2 = VecUtil.toYaw(renderData.get(renderData.size() - 2).subtract(
renderData.get(renderData.size() - 1)));
double dist = p2.distanceTo(worldPos);
if (dist < min) {
min = dist;
minPos = p2;
yaw = yaw2;
}
} else {
Vec3d p = renderData.get(0).add(rail.info.placementInfo.placementPosition).add(
tile.getPos());
float currentYaw = renderData.get(0).getYaw();
if (Math.abs(currentYaw - rotationYawHead) > 90) {
currentYaw += 180;
}
double dist = p.distanceTo(worldPos);
if (dist < min) {
min = dist;
minPos = p;
yaw = currentYaw;
}
}

tile = tile.getReplacedTile();
}
}
}
}

if (min <= hori) {
yaw = Config.ConfigDebug.trackSnapAngle ? (540 - yaw) % 360 : rotationYawHead;
return new PlacementInfo(minPos, TrackDirection.NONE, yaw, null);
}
return null;
}
}