Compare commits
1 Commits
master
...
experiment
| Author | SHA1 | Date | |
|---|---|---|---|
| e0b04f0efd |
@@ -44,6 +44,7 @@ sourceSets {
|
||||
}
|
||||
|
||||
loom {
|
||||
accessWidenerPath = file("src/main/resources/reframed.accesswidener")
|
||||
runs {
|
||||
// This adds a new gradle task that runs the datagen API: "gradlew runDatagen"
|
||||
datagen {
|
||||
|
||||
@@ -9,7 +9,7 @@ loader_version=0.15.11
|
||||
|
||||
# Mod Properties
|
||||
modrinth_id = jCpoCBpn
|
||||
mod_version = 1.6.8
|
||||
mod_version = 1.6.6
|
||||
maven_group = fr.adrien1106
|
||||
archives_base_name = ReFramed
|
||||
mod_id = reframed
|
||||
|
||||
@@ -103,6 +103,7 @@ public class ReFramed implements ModInitializer {
|
||||
BLUEPRINT = registerItem("blueprint" , new ReFramedBlueprintItem(new Item.Settings()));
|
||||
BLUEPRINT_WRITTEN = registerItem("blueprint_written" , new ReFramedBlueprintWrittenItem(new Item.Settings().maxCount(1)));
|
||||
|
||||
registerBlock("test", new TestBlock(cp(Blocks.OAK_PLANKS).nonOpaque())); // TODO remove
|
||||
|
||||
REFRAMED_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, id("camo"),
|
||||
BlockEntityType.Builder.create(
|
||||
@@ -135,11 +136,11 @@ public class ReFramed implements ModInitializer {
|
||||
private static AbstractBlock.Settings cp(Block base) {
|
||||
return AbstractBlock.Settings.copy(base)
|
||||
.luminance(state -> state.contains(LIGHT) && state.get(LIGHT) ? 15 : 0)
|
||||
.nonOpaque()
|
||||
.sounds(BlockSoundGroup.WOOD)
|
||||
.hardness(0.2f)
|
||||
.suffocates(Blocks::never)
|
||||
.solidBlock(Blocks::always);
|
||||
// .blockVision(Blocks::always);
|
||||
.suffocates((a,b,c) -> false)
|
||||
.blockVision((a,b,c) -> false);
|
||||
}
|
||||
|
||||
private static <I extends Item> I registerItem(String path, I item) {
|
||||
|
||||
@@ -2,11 +2,9 @@ package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.util.blocks.BlockHelper;
|
||||
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.ai.pathing.NavigationType;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
@@ -19,7 +17,6 @@ import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.ItemScatterer;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
import net.minecraft.util.function.BooleanBiFunction;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
@@ -34,7 +31,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static fr.adrien1106.reframed.block.ReFramedEntity.BLOCKSTATE_KEY;
|
||||
@@ -43,26 +39,10 @@ import static fr.adrien1106.reframed.util.blocks.BlockProperties.LIGHT;
|
||||
public class ReFramedBlock extends Block implements BlockEntityProvider {
|
||||
|
||||
public ReFramedBlock(Settings settings) {
|
||||
super(settings.dynamicBounds());
|
||||
super(settings);
|
||||
setDefaultState(getDefaultState().with(LIGHT, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public int getOpacity(BlockState state, BlockView world, BlockPos pos) {
|
||||
if (state.get(LIGHT)) return 0;
|
||||
if (!(world.getBlockEntity(pos) instanceof ReFramedEntity frame_entity)
|
||||
|| frame_entity.getTheme(0).isOpaque())
|
||||
return world.getMaxLightLevel();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
|
||||
return ReFramed.REFRAMED_BLOCK_ENTITY.instantiate(pos, state);
|
||||
@@ -228,17 +208,4 @@ public class ReFramedBlock extends Block implements BlockEntityProvider {
|
||||
public Map<Integer, Integer> getThemeMap(BlockState state, BlockState new_state) {
|
||||
return Map.of();
|
||||
}
|
||||
|
||||
public VoxelShape getShadingShape(BlockState state, BlockView world, BlockPos pos) {
|
||||
if (!(world.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity)) return this.getCollisionShape(state, world, pos, ShapeContext.absent());
|
||||
|
||||
AtomicInteger i = new AtomicInteger(1);
|
||||
return framed_entity.getThemes().stream().map((theme) -> {
|
||||
int index = i.getAndIncrement();
|
||||
return theme.isTransparent(world, pos) ? VoxelShapes.empty() : this.getShape(state, index);
|
||||
}).reduce(
|
||||
VoxelShapes.empty(),
|
||||
(prev, current) -> VoxelShapes.combine(prev, current, BooleanBiFunction.OR)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,12 +32,12 @@ public class ReFramedEntity extends BlockEntity implements ThemeableBlockEntity
|
||||
protected BlockState first_state = Blocks.AIR.getDefaultState();
|
||||
protected byte bit_field = SOLIDITY_MASK;
|
||||
|
||||
public static final byte LIGHT_MASK = 0b001;
|
||||
public static final byte REDSTONE_MASK = 0b010;
|
||||
public static final byte SOLIDITY_MASK = 0b100;
|
||||
protected static final byte LIGHT_MASK = 0b001;
|
||||
protected static final byte REDSTONE_MASK = 0b010;
|
||||
protected static final byte SOLIDITY_MASK = 0b100;
|
||||
|
||||
public static final String BLOCKSTATE_KEY = "s";
|
||||
public static final String BITFIELD_KEY = "b";
|
||||
protected static final String BITFIELD_KEY = "b";
|
||||
|
||||
public ReFramedEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
@@ -145,10 +145,7 @@ public class ReFramedEntity extends BlockEntity implements ThemeableBlockEntity
|
||||
if (isSolid()) bit_field &= ~SOLIDITY_MASK;
|
||||
else bit_field |= SOLIDITY_MASK;
|
||||
|
||||
if(world != null) {
|
||||
world.setBlockState(pos, getCachedState());
|
||||
ReFramed.chunkRerenderProxy.accept(world, pos);
|
||||
}
|
||||
if(world != null) world.setBlockState(pos, getCachedState());
|
||||
markDirtyAndDispatch();
|
||||
}
|
||||
|
||||
|
||||
36
src/main/java/fr/adrien1106/reframed/block/TestBlock.java
Normal file
36
src/main/java/fr/adrien1106/reframed/block/TestBlock.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package fr.adrien1106.reframed.block;
|
||||
|
||||
import fr.adrien1106.reframed.client.voxel.MorphVoxel;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.world.BlockView;
|
||||
|
||||
public class TestBlock extends Block {
|
||||
|
||||
public static MorphVoxel voxel = new MorphVoxel(createCuboidShape(1, 1, 1, 15, 15, 15),
|
||||
new Vec3d[] {
|
||||
new Vec3d(0, 0, 0),
|
||||
new Vec3d(1, 0, 0),
|
||||
new Vec3d(1, 1, 1),
|
||||
new Vec3d(0, 1, 1),
|
||||
new Vec3d(0, 1, 1),
|
||||
new Vec3d(1, 1, 1),
|
||||
new Vec3d(1, 0, 1),
|
||||
new Vec3d(0, 0, 1)
|
||||
|
||||
});
|
||||
|
||||
public TestBlock(Settings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
||||
return voxel;
|
||||
}
|
||||
}
|
||||
@@ -23,13 +23,7 @@ public class WaterloggableReFramedBlock extends ReFramedBlock implements Waterlo
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||
super.appendProperties(builder.add(Properties.WATERLOGGED));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public boolean hasSidedTransparency(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||
|
||||
@@ -51,7 +51,7 @@ public class CamoAppearanceManager {
|
||||
for(BlendMode blend : BlendMode.values()) {
|
||||
finder.clear().disableDiffuse(false).blendMode(blend);
|
||||
|
||||
materials.put(blend, finder.ambientOcclusion(TriState.TRUE).find());
|
||||
materials.put(blend, finder.ambientOcclusion(TriState.FALSE).find());
|
||||
ao_materials.put(blend, finder.ambientOcclusion(TriState.DEFAULT).find()); //not "true" since that *forces* AO, i just want to *allow* AO
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package fr.adrien1106.reframed.client.util;
|
||||
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public record RaycastResult(Vec3d pos, Direction face, boolean inside) {
|
||||
}
|
||||
@@ -89,12 +89,8 @@ public class RenderHelper {
|
||||
BlockState self_theme = frame_entity.getTheme(theme_index);
|
||||
BlockState other_theme = frame_entity.getTheme(cull_theme);
|
||||
|
||||
try {
|
||||
if (self_theme.isSideInvisible(other_theme, null)) return false;
|
||||
} catch (NullPointerException e) { // this can happen if mod haven't thought about inner faces
|
||||
return true;
|
||||
}
|
||||
return self_theme.isOpaque() != other_theme.isOpaque() && self_theme.isOpaque();
|
||||
if (self_theme.isSideInvisible(other_theme, null)) return false;
|
||||
return !self_theme.isOpaque() || !other_theme.isOpaque();
|
||||
}
|
||||
|
||||
// Doing this method from scratch as it is simpler to do than injecting everywhere
|
||||
@@ -108,7 +104,7 @@ public class RenderHelper {
|
||||
? e : null;
|
||||
|
||||
// normal behaviour
|
||||
if ((theme_index == 0 && self != null) || (self == null && other == null))
|
||||
if (theme_index == 0 || (self == null && other == null))
|
||||
return Block.shouldDrawSide(self_state, world, pos, side, other_pos);
|
||||
|
||||
// self is a normal Block
|
||||
@@ -120,7 +116,7 @@ public class RenderHelper {
|
||||
VoxelShape other_shape = VoxelShapes.empty();
|
||||
for (BlockState s: other.getThemes()) {
|
||||
i++;
|
||||
if (self_state.isSideInvisible(s, side) || (s.isOpaque() && (other.isSolid() || self_state.isTransparent(world ,pos))))
|
||||
if (self_state.isSideInvisible(s, side) || s.isOpaque())
|
||||
other_shape = combine(
|
||||
other_shape,
|
||||
other_block
|
||||
@@ -164,7 +160,7 @@ public class RenderHelper {
|
||||
VoxelShape other_shape = VoxelShapes.empty();
|
||||
for (BlockState s: other.getThemes()) {
|
||||
i++;
|
||||
if (self_theme.isSideInvisible(s, side) || (s.isOpaque() && (!self.isSolid() || (other.isSolid() == self.isSolid()))))
|
||||
if (self_theme.isSideInvisible(s, side) || s.isOpaque())
|
||||
other_shape = combine(
|
||||
other_shape,
|
||||
other_block
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package fr.adrien1106.reframed.client.voxel;
|
||||
|
||||
import fr.adrien1106.reframed.client.util.RaycastResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MorphBox extends Box {
|
||||
protected List<Triangle> triangles;
|
||||
|
||||
public MorphBox(List<Triangle> triangles) {
|
||||
super(new BlockPos(0, 0, 0));
|
||||
this.triangles = triangles;
|
||||
}
|
||||
|
||||
public RaycastResult triangleRaycast(Vec3d min, Vec3d max) {
|
||||
return triangles.stream()
|
||||
.map(triangle -> {
|
||||
Vec3d inter = triangle.intersection(min, max);
|
||||
if (inter == null) return null;
|
||||
return new RaycastResult(
|
||||
inter,
|
||||
triangle.face(),
|
||||
false
|
||||
);
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.findFirst()
|
||||
.orElseGet(() -> isInside(min) ? new RaycastResult(
|
||||
min,
|
||||
triangles.get(0).face(),
|
||||
true
|
||||
) : null);
|
||||
}
|
||||
|
||||
public boolean isInside(Vec3d point) {
|
||||
return triangles.stream().allMatch(triangle -> triangle.after(point));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package fr.adrien1106.reframed.client.voxel;
|
||||
|
||||
import fr.adrien1106.reframed.client.util.RaycastResult;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.util.shape.SimpleVoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Represents a VoxelShape that can be morphed using its 8 vertices.
|
||||
* the vertices are distributed as follows:
|
||||
* <pre><code>
|
||||
* E--------F ABCD -> NORTH
|
||||
* ^ /| /| EFGH -> SOUTH
|
||||
* |/ | / | AHED -> EAST
|
||||
* D--------C | BCGF -> WEST
|
||||
* | |/ | | ABGH -> DOWN
|
||||
* | H-----|--G CDFE -> UP
|
||||
* | / | /
|
||||
* |/ |/
|
||||
* A--------B->
|
||||
* </code></pre>
|
||||
*/
|
||||
public class MorphVoxel extends SimpleVoxelShape {
|
||||
|
||||
private static final int[][] EDGE_INDICES = {
|
||||
{0, 1},
|
||||
{1, 2},
|
||||
{2, 3},
|
||||
{3, 0},
|
||||
{0, 7},
|
||||
{1, 6},
|
||||
{2, 5},
|
||||
{3, 4},
|
||||
{4, 5},
|
||||
{5, 6},
|
||||
{6, 7},
|
||||
{7, 4}
|
||||
};
|
||||
|
||||
private static final int[][] FACE_INDICES = {
|
||||
{7, 6, 1, 0},
|
||||
{5, 4, 3, 2},
|
||||
{0, 1, 2, 3},
|
||||
{4, 5, 6, 7},
|
||||
{0, 3, 4, 7},
|
||||
{6, 5, 2, 1}
|
||||
};
|
||||
|
||||
protected final Vec3d[] v;
|
||||
MorphBox box;
|
||||
|
||||
public MorphVoxel(VoxelShape wrapper, Vec3d[] vertices) {
|
||||
super(wrapper.voxels);
|
||||
List<Triangle> triangles = new ArrayList<>();
|
||||
Stream.of(Direction.values()).forEach(dir -> {
|
||||
int i = dir.ordinal();
|
||||
List<Vec3d> v = IntStream.range(0, 4).mapToObj(j -> { // remove matching vertices
|
||||
if (vertices[FACE_INDICES[i][j]].equals(vertices[FACE_INDICES[i][(j+1)%4]])) return null;
|
||||
return vertices[FACE_INDICES[i][j]];
|
||||
}).filter(Objects::nonNull).toList();
|
||||
|
||||
if (v.size() < 3) return; // skip if there are less than 3 vertices (e.g. a line/dot)
|
||||
triangles.add(Triangle.of(dir,v));
|
||||
});
|
||||
box = new MorphBox(triangles);
|
||||
v = vertices;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockHitResult raycast(Vec3d start, Vec3d end, BlockPos pos) {
|
||||
RaycastResult result = box.triangleRaycast(start.subtract(pos.getX(), pos.getY(), pos.getZ()), end.subtract(pos.getX(), pos.getY(), pos.getZ()));
|
||||
return result == null
|
||||
? null
|
||||
: new BlockHitResult(
|
||||
result.pos().add(pos.getX(), pos.getY(), pos.getZ()),
|
||||
result.face(),
|
||||
pos,
|
||||
result.inside()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachEdge(VoxelShapes.BoxConsumer consumer) {
|
||||
IntStream.range(0, 12).forEach(i -> {
|
||||
Vec3d a = v[EDGE_INDICES[i][0]];
|
||||
Vec3d b = v[EDGE_INDICES[i][1]];
|
||||
consumer.consume(a.x, a.y, a.z, b.x, b.y, b.z);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package fr.adrien1106.reframed.client.voxel;
|
||||
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* Represents a Face of a MorphVoxel.
|
||||
* @param v - list of vertices on the same plane
|
||||
* @param e - list of the outer edges
|
||||
* @param n - normal of the face
|
||||
* @param face - the direction of the face
|
||||
*/
|
||||
public record Triangle(Vec3d[] v, Vec3d[] e, Vec3d n, Direction face) {
|
||||
|
||||
/**
|
||||
* Creates a Triangle from a list of vertices.
|
||||
* @param face - the direction of the face
|
||||
* @param vertices - list of vertices on the same plane
|
||||
* @return the Triangle
|
||||
*/
|
||||
public static Triangle of(Direction face, List<Vec3d> vertices) {
|
||||
assert vertices.size() >= 3;
|
||||
Vec3d[] v = vertices.toArray(new Vec3d[0]);
|
||||
|
||||
// compute the edges
|
||||
Vec3d[] e = new Vec3d[v.length];
|
||||
IntStream.range(0, v.length).forEach(i -> e[i] = v[(i + 1) % v.length].subtract(v[i]));
|
||||
|
||||
// compute the normal
|
||||
Vec3d n = v[1].subtract(v[0]).crossProduct(v[2].subtract(v[0])).normalize();
|
||||
|
||||
return new Triangle(v, e, n, face);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the intersection of a ray with the triangle.
|
||||
* @param start - the start of the ray
|
||||
* @param end - the end of the ray
|
||||
* @return the intersection point or null if there is no intersection
|
||||
*/
|
||||
public Vec3d intersection(Vec3d start, Vec3d end) {
|
||||
Vec3d start_v0 = start.subtract(v[0]);
|
||||
Vec3d end_v1 = end.subtract(v[1]);
|
||||
|
||||
// check if the ray intersects the plane
|
||||
if (n.dotProduct(start_v0) * n.dotProduct(end_v1) >= 0) return null;
|
||||
|
||||
Vec3d ray = end.subtract(start);
|
||||
double direction = n.dotProduct(ray);
|
||||
|
||||
// plane normal is facing away from the ray
|
||||
if (direction < 0) return null;
|
||||
|
||||
// get Intersection point
|
||||
double t = -n.dotProduct(start_v0) / direction;
|
||||
Vec3d intersection = start.add(ray.multiply(t));
|
||||
|
||||
// check if the intersection is inside the triangle
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
Vec3d edge = e[i];
|
||||
Vec3d edge_intersection = intersection.subtract(v[i]);
|
||||
if (edge_intersection.length() < 1e-6) break; // intersection is on the vertex
|
||||
|
||||
double a = n.dotProduct(edge.crossProduct(edge_intersection));
|
||||
if (a <= 0) return null; // intersection is outside the triangle
|
||||
if (a <= edge.length() * 1e-6) break; // intersection is on the edge
|
||||
}
|
||||
|
||||
return intersection;
|
||||
}
|
||||
|
||||
public boolean after(Vec3d point) {
|
||||
return n.dotProduct(point.subtract(v[0])) > 0;
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,8 @@ public class GBlockstate extends FabricModelProvider {
|
||||
providers.put(ReFramedPostBlock.class, new Post());
|
||||
providers.put(ReFramedFenceBlock.class, new Fence());
|
||||
providers.put(ReFramedPostFenceBlock.class, new PostFence());
|
||||
|
||||
providers.put(TestBlock.class, new Test());
|
||||
}
|
||||
|
||||
public GBlockstate(FabricDataOutput output) {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package fr.adrien1106.reframed.generator.block;
|
||||
|
||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.data.client.BlockStateSupplier;
|
||||
import net.minecraft.data.client.VariantsBlockStateSupplier;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.R0;
|
||||
|
||||
public class Test implements BlockStateProvider {
|
||||
|
||||
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart(Block block) {
|
||||
return VariantsBlockStateSupplier.create(
|
||||
block,
|
||||
GBlockstate.variant(
|
||||
new Identifier("block/barrier"),
|
||||
true,
|
||||
R0, R0
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,7 @@ public class BlockItemMixin {
|
||||
)
|
||||
)
|
||||
private static void placeBlockWithOffHandCamo(World world, PlayerEntity player, BlockPos pos, ItemStack stack, CallbackInfoReturnable<Boolean> cir, @Local LocalRef<NbtCompound> compound) {
|
||||
if (player == null
|
||||
|| compound.get() != null
|
||||
if (compound.get() != null
|
||||
|| player.getOffHandStack().isEmpty()
|
||||
|| player.getMainHandStack().isEmpty()
|
||||
|| !(player.getMainHandStack().getItem() instanceof BlockItem frame)
|
||||
|
||||
@@ -31,8 +31,6 @@ public class CompatMixinPlugin implements IMixinConfigPlugin {
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.IndiumNonTerrainBlockRenderContextMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.render.BlockRenderContextMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.SodiumBlockOcclusionCacheMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(2)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.render.FluidRendererMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(2)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.SodiumFluidRendererMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(2)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.ContinuityConnectionPredicateMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.ContinuityCTMBakedModelMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4)));
|
||||
CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.ContinuityCTMQuadTransformMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4)));
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
package fr.adrien1106.reframed.mixin.compat;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import fr.adrien1106.reframed.block.ReFramedBlock;
|
||||
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.FluidRenderer;
|
||||
import me.jellysquid.mods.sodium.client.world.WorldSlice;
|
||||
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.BlockView;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(FluidRenderer.class)
|
||||
public abstract class SodiumFluidRendererMixin {
|
||||
|
||||
@Redirect(
|
||||
method = "isSideExposed",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/block/BlockState;isOpaque()Z"
|
||||
)
|
||||
)
|
||||
private boolean isSideOpaqueExposed(BlockState state) {
|
||||
if (!(state.getBlock() instanceof ReFramedBlock)) return state.isOpaque();
|
||||
return true; // forces to compute correct shape
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "isSideExposed",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/block/BlockState;getCullingShape(Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/util/shape/VoxelShape;"
|
||||
)
|
||||
)
|
||||
private VoxelShape isSideShapeExposed(BlockState state, BlockView world, BlockPos pos) {
|
||||
if (!(state.getBlock() instanceof ReFramedBlock block)) return state.getCullingShape(world, pos);
|
||||
return block.getShadingShape(state, world, pos);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "render",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/fabricmc/fabric/api/client/render/fluid/v1/FluidRenderHandlerRegistry;isBlockTransparent(Lnet/minecraft/block/Block;)Z"
|
||||
)
|
||||
)
|
||||
private boolean getThemeState(FluidRenderHandlerRegistry fluid_handler, Block block, @Local(argsOnly = true) WorldSlice world, @Local(ordinal = 2) BlockPos pos, @Local BlockState state, @Local Direction dir) {
|
||||
if (!(block instanceof ReFramedBlock rfblock && world.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity)) return fluid_handler.isBlockTransparent(block);
|
||||
return !VoxelShapes.isSideCovered(VoxelShapes.fullCube(), rfblock.getShadingShape(state, world, pos), dir)
|
||||
&& framed_entity.getThemes().stream()
|
||||
.anyMatch(s -> s.getBlock() instanceof LeavesBlock
|
||||
|| s.getBlock() instanceof TranslucentBlock
|
||||
|| s.getBlock() instanceof AirBlock
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package fr.adrien1106.reframed.mixin.render;
|
||||
|
||||
import fr.adrien1106.reframed.client.util.RenderHelper;
|
||||
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockView;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(Block.class)
|
||||
public abstract class BlockMixin {
|
||||
|
||||
@Inject(
|
||||
method = "shouldDrawSide",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true
|
||||
) // serves as a safety sometimes mods implements culling cache and hence will break some injections...
|
||||
private static void shouldDrawSide(BlockState state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos, CallbackInfoReturnable<Boolean> cir) {
|
||||
if (!(world.getBlockEntity(other_pos) instanceof ThemeableBlockEntity)) return;
|
||||
cir.setReturnValue(RenderHelper.shouldDrawSide(state, world, pos, side, other_pos, 0));
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package fr.adrien1106.reframed.mixin.render;
|
||||
|
||||
import fr.adrien1106.reframed.block.ReFramedBlock;
|
||||
import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.client.render.block.FluidRenderer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import net.minecraft.world.BlockView;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(FluidRenderer.class)
|
||||
public abstract class FluidRendererMixin {
|
||||
|
||||
@Inject(
|
||||
method = "isSideCovered(Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/Direction;FLnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;)Z",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true
|
||||
) // force dynamic water side rendering
|
||||
private static void isSameSideCovered(BlockView world, Direction direction, float height, BlockPos pos, BlockState state, CallbackInfoReturnable<Boolean> cir) {
|
||||
if (!(state.getBlock() instanceof ReFramedBlock block)
|
||||
) return;
|
||||
|
||||
boolean is_covered = VoxelShapes.isSideCovered(
|
||||
VoxelShapes.cuboid(0.0, 0.0, 0.0, 1.0, height, 1.0),
|
||||
block.getShadingShape(state, world, pos),
|
||||
direction
|
||||
);
|
||||
cir.setReturnValue(is_covered);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "render",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/BlockRenderView;getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/BlockState;",
|
||||
ordinal = 7
|
||||
)
|
||||
)
|
||||
private BlockState getThemeState(BlockRenderView world, BlockPos pos) {
|
||||
if (!(world.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity)) return world.getBlockState(pos);
|
||||
return framed_entity.getThemes().stream()
|
||||
.anyMatch(state -> state.getBlock() instanceof LeavesBlock
|
||||
|| state.getBlock() instanceof TranslucentBlock
|
||||
|| state.getBlock() instanceof AirBlock
|
||||
)
|
||||
? Blocks.GLASS.getDefaultState()
|
||||
: world.getBlockState(pos) ;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,4 @@ public interface ThemeableBlockEntity {
|
||||
void setTheme(BlockState state, int i);
|
||||
|
||||
List<BlockState> getThemes();
|
||||
|
||||
boolean isSolid();
|
||||
}
|
||||
|
||||
@@ -12,11 +12,10 @@ import net.minecraft.util.math.BlockPos;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static fr.adrien1106.reframed.block.ReFramedEntity.*;
|
||||
import static fr.adrien1106.reframed.block.ReFramedEntity.BLOCKSTATE_KEY;
|
||||
|
||||
public class ThemedBlockEntity extends BlockEntity implements ThemeableBlockEntity {
|
||||
private final List<BlockState> themes;
|
||||
private final boolean isSolid;
|
||||
|
||||
public ThemedBlockEntity(NbtCompound compound, BlockPos pos, BlockState state) {
|
||||
super(null, pos, state);
|
||||
@@ -27,7 +26,6 @@ public class ThemedBlockEntity extends BlockEntity implements ThemeableBlockEnti
|
||||
compound.getCompound(BLOCKSTATE_KEY + i)
|
||||
));
|
||||
}
|
||||
isSolid = !compound.contains(BITFIELD_KEY) || (compound.getByte(BITFIELD_KEY) & SOLIDITY_MASK) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,9 +47,4 @@ public class ThemedBlockEntity extends BlockEntity implements ThemeableBlockEnti
|
||||
public List<BlockState> getThemes() {
|
||||
return themes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid() {
|
||||
return isSolid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,17 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [0, 0, 8],
|
||||
"from": [0, 0, 0],
|
||||
"to": [8, 8, 16],
|
||||
"faces": {
|
||||
"south": {"uv": [0, 8, 8, 16], "texture": "#side", "cullface": "south"},
|
||||
"west": {"uv": [8, 8, 16, 16], "texture": "#side", "cullface": "west"},
|
||||
"up": {"uv": [0, 8, 8, 16], "texture": "#top"},
|
||||
"down": {"uv": [0, 0, 8, 8], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [0, 0, 0],
|
||||
"to": [8, 8, 8],
|
||||
"faces": {
|
||||
"north": {"uv": [8, 8, 16, 16], "texture": "#side", "cullface": "north"},
|
||||
"west": {"uv": [0, 8, 8, 16], "texture": "#side", "cullface": "west"},
|
||||
"up": {"uv": [0, 0, 8, 8], "texture": "#top"},
|
||||
"down": {"uv": [0, 8, 8, 16], "texture": "#bottom", "cullface": "down"}
|
||||
"south": {"uv": [0, 8, 8, 16], "texture": "#side", "cullface": "south"},
|
||||
"west": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "west"},
|
||||
"up": {"uv": [0, 0, 8, 16], "texture": "#top"},
|
||||
"down": {"uv": [0, 0, 8, 16], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,26 +1,16 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"textures": {
|
||||
"particle": "#side"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [8, 8, 0],
|
||||
"from": [8, 0, 0],
|
||||
"to": [16, 16, 8],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 8, 8], "texture": "#side", "cullface": "north"},
|
||||
"east": {"uv": [8, 0, 16, 8], "texture": "#side", "cullface": "east"},
|
||||
"west": {"uv": [0, 0, 8, 8], "texture": "#side"},
|
||||
"up": {"uv": [8, 0, 16, 8], "texture": "#top", "cullface": "up"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [8, 0, 0],
|
||||
"to": [16, 8, 8],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 8, 8, 16], "texture": "#side", "cullface": "north"},
|
||||
"east": {"uv": [8, 8, 16, 16], "texture": "#side", "cullface": "east"},
|
||||
"west": {"uv": [0, 8, 8, 16], "texture": "#side"},
|
||||
"north": {"uv": [0, 0, 8, 16], "texture": "#side", "cullface": "north"},
|
||||
"east": {"uv": [8, 0, 16, 16], "texture": "#side", "cullface": "east"},
|
||||
"west": {"uv": [0, 0, 8, 16], "texture": "#side"},
|
||||
"up": {"uv": [8, 0, 16, 8], "texture": "#top", "cullface": "up"},
|
||||
"down": {"uv": [8, 8, 16, 16], "texture": "#bottom", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
@@ -60,7 +50,7 @@
|
||||
"name": "outer_stairs",
|
||||
"origin": [8, 8, 8],
|
||||
"color": 0,
|
||||
"children": [0, 1, 2, 3, 4]
|
||||
"children": [0, 1, 2, 3]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
"mixins": [
|
||||
"reframed.mixins.json"
|
||||
],
|
||||
"accessWidener": "reframed.accesswidener",
|
||||
"depends": {
|
||||
"minecraft": "${minecraft_version}",
|
||||
"fabricloader": "^${loader_version}",
|
||||
|
||||
4
src/main/resources/reframed.accesswidener
Normal file
4
src/main/resources/reframed.accesswidener
Normal file
@@ -0,0 +1,4 @@
|
||||
accessWidener v2 named
|
||||
|
||||
accessible field net/minecraft/util/shape/VoxelShape voxels Lnet/minecraft/util/shape/VoxelSet;
|
||||
extendable class net/minecraft/util/shape/SimpleVoxelShape
|
||||
@@ -33,17 +33,14 @@
|
||||
"compat.IndiumNonTerrainBlockRenderContextMixin",
|
||||
"compat.IndiumTerrainRenderContextMixin",
|
||||
"compat.SodiumBlockOcclusionCacheMixin",
|
||||
"compat.SodiumFluidRendererMixin",
|
||||
"model.WeightedBakedModelAccessor",
|
||||
"particles.AccessorParticle",
|
||||
"particles.AccessorSpriteBillboardParticle",
|
||||
"particles.MixinBlockDustParticle",
|
||||
"render.AbstractBlockRenderContextMixin",
|
||||
"render.BlockMixin",
|
||||
"render.BlockModelRendererMixin",
|
||||
"render.BlockRenderContextMixin",
|
||||
"render.BlockRenderInfoMixin",
|
||||
"render.FluidRendererMixin",
|
||||
"render.MultipartBakedModelMixin",
|
||||
"render.TerrainRenderContextMixin",
|
||||
"render.WorldRendererMixin",
|
||||
|
||||
Reference in New Issue
Block a user