2018-12-20 00:39:10 +00:00
|
|
|
package net.shadowfacts.simplemultipart.util;
|
|
|
|
|
|
|
|
import com.google.common.collect.ImmutableMap;
|
|
|
|
import net.minecraft.entity.player.PlayerEntity;
|
|
|
|
import net.minecraft.nbt.CompoundTag;
|
|
|
|
import net.minecraft.state.PropertyContainer;
|
|
|
|
import net.minecraft.state.StateFactory;
|
|
|
|
import net.minecraft.state.property.Property;
|
|
|
|
import net.minecraft.util.HitResult;
|
|
|
|
import net.minecraft.util.Identifier;
|
|
|
|
import net.minecraft.util.math.BlockPos;
|
|
|
|
import net.minecraft.util.math.MathHelper;
|
|
|
|
import net.minecraft.util.math.Vec3d;
|
|
|
|
import net.minecraft.util.shape.VoxelShape;
|
|
|
|
import net.minecraft.world.World;
|
|
|
|
import net.shadowfacts.simplemultipart.SimpleMultipart;
|
2018-12-28 02:55:51 +00:00
|
|
|
import net.shadowfacts.simplemultipart.container.MultipartContainer;
|
2018-12-20 00:39:10 +00:00
|
|
|
import net.shadowfacts.simplemultipart.multipart.Multipart;
|
|
|
|
import net.shadowfacts.simplemultipart.multipart.MultipartState;
|
|
|
|
|
|
|
|
import java.util.*;
|
|
|
|
|
|
|
|
/**
|
2018-12-28 18:10:59 +00:00
|
|
|
* Helper methods relating to multiparts.
|
|
|
|
*
|
2018-12-20 00:39:10 +00:00
|
|
|
* @author shadowfacts
|
2018-12-28 18:10:59 +00:00
|
|
|
* @since 0.1.0
|
2018-12-20 00:39:10 +00:00
|
|
|
*/
|
|
|
|
public class MultipartHelper {
|
|
|
|
|
2018-12-28 18:10:59 +00:00
|
|
|
/**
|
|
|
|
* Performs a ray trace to determine the hit multipart.
|
|
|
|
*
|
|
|
|
* @param container The container being ray traced in.
|
|
|
|
* @param world The world.
|
|
|
|
* @param pos The position of the container.
|
|
|
|
* @param player The player performing the ray trace.
|
|
|
|
* @return A hit result for the hit multipart. {@ode null} if not part was hit.
|
|
|
|
*/
|
2018-12-25 15:30:46 +00:00
|
|
|
public static MultipartHitResult rayTrace(MultipartContainer container, World world, BlockPos pos, PlayerEntity player) {
|
2018-12-20 00:39:10 +00:00
|
|
|
// copied from BoatItem::use
|
|
|
|
float var6 = MathHelper.lerp(1.0F, player.prevPitch, player.pitch);
|
|
|
|
float var7 = MathHelper.lerp(1.0F, player.prevYaw, player.yaw);
|
|
|
|
double var8 = MathHelper.lerp(1.0D, player.prevX, player.x);
|
|
|
|
double var10 = MathHelper.lerp(1.0D, player.prevY, player.y) + (double)player.getEyeHeight();
|
|
|
|
double var12 = MathHelper.lerp(1.0D, player.prevZ, player.z);
|
|
|
|
Vec3d start = new Vec3d(var8, var10, var12);
|
|
|
|
|
|
|
|
float var15 = MathHelper.cos(-var7 * 0.017453292F - 3.1415927F);
|
|
|
|
float var16 = MathHelper.sin(-var7 * 0.017453292F - 3.1415927F);
|
|
|
|
float var17 = -MathHelper.cos(-var6 * 0.017453292F);
|
|
|
|
float var18 = MathHelper.sin(-var6 * 0.017453292F);
|
|
|
|
float var19 = var16 * var17;
|
|
|
|
float var21 = var15 * var17;
|
|
|
|
Vec3d end = start.add((double)var19 * 5.0D, (double)var18 * 5.0D, (double)var21 * 5.0D);
|
|
|
|
|
|
|
|
return rayTrace(container, world, pos, start, end);
|
|
|
|
}
|
|
|
|
|
2018-12-28 18:10:59 +00:00
|
|
|
/**
|
|
|
|
* Performs a ray trace to determine the hit multipart.
|
|
|
|
*
|
|
|
|
* @param container The container being ray traced in.
|
|
|
|
* @param world The world.
|
|
|
|
* @param pos The position of the container.
|
|
|
|
* @param start The start position for the ray.
|
|
|
|
* @param end The end position for the ray.
|
|
|
|
* @return A hit result for the hit multipart. {@code null} if no part was hit.
|
|
|
|
*/
|
2018-12-25 15:30:46 +00:00
|
|
|
public static MultipartHitResult rayTrace(MultipartContainer container, World world, BlockPos pos, Vec3d start, Vec3d end) {
|
2018-12-24 22:16:38 +00:00
|
|
|
return container.getParts().stream()
|
2018-12-25 15:20:44 +00:00
|
|
|
.map(view -> {
|
|
|
|
VoxelShape shape = view.getState().getBoundingShape(view);
|
2018-12-20 00:39:10 +00:00
|
|
|
HitResult result = shape.rayTrace(start, end, pos);
|
2018-12-25 15:20:44 +00:00
|
|
|
return result == null ? null : new MultipartHitResult(result, view);
|
2018-12-20 00:39:10 +00:00
|
|
|
})
|
|
|
|
.filter(Objects::nonNull)
|
|
|
|
.min(Comparator.comparingDouble(hit -> hit.pos.subtract(start).lengthSquared()))
|
|
|
|
.orElse(null);
|
|
|
|
}
|
|
|
|
|
2018-12-28 18:10:59 +00:00
|
|
|
/**
|
|
|
|
* Creates a NBT representation of the given multipart state.
|
|
|
|
*
|
|
|
|
* @param state The multipart state.
|
|
|
|
* @return A compound tag containing the multipart and it's property values.
|
|
|
|
*/
|
2018-12-20 00:39:10 +00:00
|
|
|
public static CompoundTag serializeMultipartState(MultipartState state) {
|
|
|
|
CompoundTag tag = new CompoundTag();
|
|
|
|
tag.putString("Name", SimpleMultipart.MULTIPART.getId(state.getMultipart()).toString());
|
|
|
|
|
|
|
|
ImmutableMap<Property<?>, Comparable<?>> propertyMap = state.getEntries();
|
|
|
|
if (!propertyMap.isEmpty()) {
|
|
|
|
CompoundTag propertyTag = new CompoundTag();
|
|
|
|
|
|
|
|
for (Map.Entry<Property<?>, Comparable<?>> e : propertyMap.entrySet()) {
|
|
|
|
Property<?> property = e.getKey();
|
|
|
|
String str = getValueAsString(state, property);
|
|
|
|
propertyTag.putString(property.getName(), str);
|
|
|
|
}
|
|
|
|
|
|
|
|
tag.put("Properties", propertyTag);
|
|
|
|
}
|
|
|
|
|
|
|
|
return tag;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static <C extends PropertyContainer<C>, T extends Comparable<T>> String getValueAsString(C state, Property<T> property) {
|
|
|
|
return property.getValueAsString(state.get(property));
|
|
|
|
}
|
|
|
|
|
2018-12-28 18:10:59 +00:00
|
|
|
/**
|
|
|
|
* Retrieves the multipart state specified by the given tag.
|
|
|
|
*
|
|
|
|
* @param tag A tag containing the multipart information.
|
|
|
|
* Generated by {@link MultipartHelper#serializeMultipartState(MultipartState)}
|
|
|
|
* @return The multipart state represented by the tag.
|
|
|
|
*/
|
2018-12-24 21:38:52 +00:00
|
|
|
public static MultipartState deserializeMultipartState(CompoundTag tag) {
|
2018-12-20 00:39:10 +00:00
|
|
|
if (!tag.containsKey("Name", 8)) {
|
|
|
|
return null;
|
|
|
|
} else {
|
|
|
|
Multipart part = SimpleMultipart.MULTIPART.get(new Identifier(tag.getString("Name")));
|
|
|
|
MultipartState state = part.getDefaultState();
|
|
|
|
|
|
|
|
if (tag.containsKey("Properties", 10)) {
|
|
|
|
CompoundTag propertyTag = tag.getCompound("Properties");
|
|
|
|
|
|
|
|
StateFactory<Multipart, MultipartState> stateFactory = part.getStateFactory();
|
|
|
|
|
|
|
|
for (String propertyName : propertyTag.getKeys()) {
|
|
|
|
Property<?> property = stateFactory.getProperty(propertyName);
|
|
|
|
|
|
|
|
if (property != null) {
|
|
|
|
String valueStr = propertyTag.getString(propertyName);
|
|
|
|
state = withProperty(state, property, valueStr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private static <C extends PropertyContainer<C>, T extends Comparable<T>> C withProperty(C state, Property<T> property, String valueString) {
|
|
|
|
Optional<T> value = property.getValue(valueString);
|
|
|
|
if (!value.isPresent()) {
|
|
|
|
// TODO: logging
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
return state.with(property, value.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|