WIP Covers

This commit is contained in:
Buuz135
2021-02-17 16:10:52 +01:00
parent 6fae37bd67
commit 27f46bdd99
18 changed files with 1650 additions and 5 deletions

View File

@@ -43,6 +43,8 @@ public final class RSItems {
public static final RegistryObject<WirelessCraftingMonitorItem> WIRELESS_CRAFTING_MONITOR; public static final RegistryObject<WirelessCraftingMonitorItem> WIRELESS_CRAFTING_MONITOR;
public static final RegistryObject<WirelessCraftingMonitorItem> CREATIVE_WIRELESS_CRAFTING_MONITOR; public static final RegistryObject<WirelessCraftingMonitorItem> CREATIVE_WIRELESS_CRAFTING_MONITOR;
public static final RegistryObject<BlockItem> MACHINE_CASING; public static final RegistryObject<BlockItem> MACHINE_CASING;
public static final RegistryObject<CoverItem> COVER;
public static final RegistryObject<CoverItem> HOLLOW_COVER;
public static final Map<ProcessorItem.Type, RegistryObject<ProcessorItem>> PROCESSORS = new EnumMap<>(ProcessorItem.Type.class); public static final Map<ProcessorItem.Type, RegistryObject<ProcessorItem>> PROCESSORS = new EnumMap<>(ProcessorItem.Type.class);
@@ -121,6 +123,8 @@ public final class RSItems {
registerBlockItemFor(RSBlocks.QUARTZ_ENRICHED_IRON); registerBlockItemFor(RSBlocks.QUARTZ_ENRICHED_IRON);
MACHINE_CASING = registerBlockItemFor(RSBlocks.MACHINE_CASING); MACHINE_CASING = registerBlockItemFor(RSBlocks.MACHINE_CASING);
COVER = ITEMS.register("cover", CoverItem::new);
HOLLOW_COVER = ITEMS.register("hollow_cover", HollowCoverItem::new);
registerBlockItemFor(RSBlocks.CABLE); registerBlockItemFor(RSBlocks.CABLE);
registerBlockItemFor(RSBlocks.DISK_DRIVE); registerBlockItemFor(RSBlocks.DISK_DRIVE);

View File

@@ -0,0 +1,9 @@
package com.refinedmods.refinedstorage.api.network.node;
import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;
public interface ICoverable {
CoverManager getCoverManager();
}

View File

@@ -1,15 +1,22 @@
package com.refinedmods.refinedstorage.apiimpl.network.node; package com.refinedmods.refinedstorage.apiimpl.network.node;
import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RS;
import com.refinedmods.refinedstorage.api.network.node.ICoverable;
import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;
import com.refinedmods.refinedstorage.util.WorldUtils;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
public class CableNetworkNode extends NetworkNode { public class CableNetworkNode extends NetworkNode implements ICoverable {
public static final ResourceLocation ID = new ResourceLocation(RS.ID, "cable"); public static final ResourceLocation ID = new ResourceLocation(RS.ID, "cable");
private CoverManager coverManager;
public CableNetworkNode(World world, BlockPos pos) { public CableNetworkNode(World world, BlockPos pos) {
super(world, pos); super(world, pos);
this.coverManager = new CoverManager(this);
} }
@Override @Override
@@ -21,4 +28,27 @@ public class CableNetworkNode extends NetworkNode {
public ResourceLocation getId() { public ResourceLocation getId() {
return ID; return ID;
} }
@Override
public CoverManager getCoverManager() {
return coverManager;
}
@Override
public void read(CompoundNBT tag) {
if (tag.contains("Cover")) this.coverManager.readFromNbt(tag.getCompound("Cover"));
super.read(tag);
}
@Override
public void update() {
super.update();
//WorldUtils.updateBlock(world, pos);
}
@Override
public CompoundNBT write(CompoundNBT tag) {
tag.put("Cover", this.coverManager.writeToNbt());
return super.write(tag);
}
} }

View File

@@ -0,0 +1,22 @@
package com.refinedmods.refinedstorage.apiimpl.network.node.cover;
import net.minecraft.item.ItemStack;
public class Cover {
private ItemStack stack;
private CoverType type;
public Cover(ItemStack stack, CoverType type) {
this.stack = stack;
this.type = type;
}
public ItemStack getStack() {
return stack;
}
public CoverType getType() {
return type;
}
}

View File

@@ -0,0 +1,199 @@
package com.refinedmods.refinedstorage.apiimpl.network.node.cover;
import com.refinedmods.refinedstorage.api.network.node.ICoverable;
import com.refinedmods.refinedstorage.api.network.node.INetworkNode;
import com.refinedmods.refinedstorage.api.util.Action;
import com.refinedmods.refinedstorage.apiimpl.API;
import com.refinedmods.refinedstorage.apiimpl.network.node.CableNetworkNode;
import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode;
import com.refinedmods.refinedstorage.item.CoverItem;
import net.minecraft.block.*;
import net.minecraft.client.Minecraft;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.client.model.data.ModelProperty;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemStackHandler;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
public class CoverManager {
public static final ModelProperty<CoverManager> PROPERTY = new ModelProperty<>();
private static final String NBT_DIRECTION = "Direction";
private static final String NBT_ITEM = "Item";
private static final String NBT_TYPE = "Type";
private Map<Direction, Cover> covers = new HashMap<>();
private NetworkNode node;
public CoverManager(NetworkNode node) {
this.node = node;
}
public boolean canConduct(Direction direction) {
Cover cover = getCover(direction);
if (cover != null && cover.getType() != CoverType.HOLLOW) {
return false;
}
if (node.getWorld() instanceof ServerWorld){
INetworkNode neighbor = API.instance().getNetworkNodeManager((ServerWorld) node.getWorld()).getNode(node.getPos().offset(direction));
if (neighbor instanceof ICoverable) {
cover = ((ICoverable) neighbor).getCoverManager().getCover(direction.getOpposite());
if (cover != null && cover.getType() != CoverType.HOLLOW) {
return false;
}
}
}
return true;
}
@Nullable
public Cover getCover(Direction facing) {
return covers.get(facing);
}
public boolean hasCover(Direction facing) {
return covers.containsKey(facing);
}
public boolean setCover(Direction facing, @Nullable Cover cover) {
if (cover == null || (isValidCover(cover.getStack()) && !hasCover(facing))) {
if (cover != null) {
if (!(node instanceof CableNetworkNode) && facing == node.getDirection() && cover.getType() != CoverType.HOLLOW) {
return false;
}
}
if (cover == null) {
covers.remove(facing);
} else {
covers.put(facing, cover);
}
node.markDirty();
if (node.getNetwork() != null) {
node.getNetwork().getNodeGraph().invalidate(Action.PERFORM, node.getNetwork().getWorld(), node.getNetwork().getPosition());
}
return true;
}
return false;
}
public void readFromNbt(CompoundNBT nbt) {
covers.clear();
System.out.println(nbt);
for (String s : nbt.keySet()) {
CompoundNBT tag = nbt.getCompound(s);
if (tag.contains(NBT_DIRECTION) && tag.contains(NBT_ITEM)) {
Direction direction = Direction.byIndex(tag.getInt(NBT_DIRECTION));
ItemStack item = ItemStack.read(tag.getCompound(NBT_ITEM));
int type = tag.contains(NBT_TYPE) ? tag.getInt(NBT_TYPE) : 0;
if (type >= CoverType.values().length) {
type = 0;
}
if (isValidCover(item)) {
covers.put(direction, new Cover(item, CoverType.values()[type]));
}
}
}
}
public CompoundNBT writeToNbt() {
CompoundNBT list = new CompoundNBT();
for (Map.Entry<Direction, Cover> entry : covers.entrySet()) {
CompoundNBT tag = new CompoundNBT();
tag.putInt(NBT_DIRECTION, entry.getKey().ordinal());
tag.put(NBT_ITEM, entry.getValue().getStack().serializeNBT());
tag.putInt(NBT_TYPE, entry.getValue().getType().ordinal());
list.put(entry.getKey().ordinal() + "",tag);
}
return list;
}
public IItemHandlerModifiable getAsInventory() {
ItemStackHandler handler = new ItemStackHandler(covers.size());
int i = 0;
for (Map.Entry<Direction, Cover> entry : covers.entrySet()) {
ItemStack cover = entry.getValue().getType().createStack();
CoverItem.setItem(cover, entry.getValue().getStack());
handler.setStackInSlot(i++, cover);
}
return handler;
}
@SuppressWarnings("deprecation")
public static boolean isValidCover(ItemStack item) {
if (item.isEmpty()) {
return false;
}
Block block = getBlock(item);
BlockState state = getBlockState(item);
return block != null && state != null && ((isModelSupported(state) && !block.ticksRandomly(state) && !block.hasTileEntity(state)) || block instanceof GlassBlock || block instanceof StainedGlassBlock); //Removed is top solid as it needs world param
}
private static boolean isModelSupported(BlockState state) {
if (state.getRenderType() != BlockRenderType.MODEL) {
return false;
}
return state.isSolid() && state.isSolidSide(Minecraft.getInstance().world, new BlockPos(0,0,0), Direction.UP); //I dont trust this
}
@Nullable
public static Block getBlock(@Nullable ItemStack item) {
if (item == null) {
return null;
}
Block block = Block.getBlockFromItem(item.getItem());
if (block == Blocks.AIR) {
return null;
}
return block;
}
@Nullable
@SuppressWarnings("deprecation")
public static BlockState getBlockState(@Nullable ItemStack item) {
Block block = getBlock(item);
if (block == null) {
return null;
}
try {
return block.getDefaultState();
} catch (Exception e) {
return null;
}
}
}

View File

@@ -0,0 +1,14 @@
package com.refinedmods.refinedstorage.apiimpl.network.node.cover;
import com.refinedmods.refinedstorage.RSItems;
import net.minecraft.block.Blocks;
import net.minecraft.item.ItemStack;
public enum CoverType {
NORMAL,
HOLLOW;
public ItemStack createStack() {
return new ItemStack(this == NORMAL ? RSItems.COVER.get() : RSItems.HOLLOW_COVER.get() );
}
}

View File

@@ -1,11 +1,13 @@
package com.refinedmods.refinedstorage.integration.jei; package com.refinedmods.refinedstorage.integration.jei;
import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RS;
import com.refinedmods.refinedstorage.RSItems;
import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.BaseScreen;
import mezz.jei.api.IModPlugin; import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin; import mezz.jei.api.JeiPlugin;
import mezz.jei.api.registration.IGuiHandlerRegistration; import mezz.jei.api.registration.IGuiHandlerRegistration;
import mezz.jei.api.registration.IRecipeTransferRegistration; import mezz.jei.api.registration.IRecipeTransferRegistration;
import mezz.jei.api.registration.ISubtypeRegistration;
import mezz.jei.api.runtime.IJeiRuntime; import mezz.jei.api.runtime.IJeiRuntime;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@@ -39,4 +41,9 @@ public class RSJeiPlugin implements IModPlugin {
public static IJeiRuntime getRuntime() { public static IJeiRuntime getRuntime() {
return runtime; return runtime;
} }
@Override
public void registerItemSubtypes(ISubtypeRegistration registration) {
registration.useNbtForSubtypes(RSItems.COVER.get(), RSItems.HOLLOW_COVER.get());
}
} }

View File

@@ -0,0 +1,164 @@
package com.refinedmods.refinedstorage.item;
import com.refinedmods.refinedstorage.RS;
import com.refinedmods.refinedstorage.api.network.node.ICoverable;
import com.refinedmods.refinedstorage.api.network.node.INetworkNode;
import com.refinedmods.refinedstorage.api.network.security.Permission;
import com.refinedmods.refinedstorage.apiimpl.API;
import com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover;
import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;
import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType;
import com.refinedmods.refinedstorage.tile.NetworkNodeTile;
import com.refinedmods.refinedstorage.util.WorldUtils;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.item.*;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.client.model.ModelDataManager;
import net.minecraftforge.registries.ForgeRegistries;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class CoverItem extends Item {
private static final String NBT_ITEM = "Item";
public static final ItemStack HIDDEN_COVER_ALTERNATIVE = new ItemStack(Blocks.STONE_BRICKS);
public CoverItem() {
super(new Item.Properties().group(RS.MAIN_GROUP));
}
public static void setItem(ItemStack cover, ItemStack item) {
if (!cover.hasTag()) {
cover.setTag(new CompoundNBT());
}
cover.getTag().put(NBT_ITEM, item.serializeNBT());
}
@Nonnull
public static ItemStack getItem(ItemStack cover) {
if (!cover.hasTag() || !cover.getTag().contains(NBT_ITEM)) {
return ItemStack.EMPTY;
}
return ItemStack.read(cover.getTag().getCompound(NBT_ITEM));
}
@Override
public void addInformation(ItemStack stack, @Nullable World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
super.addInformation(stack, worldIn, tooltip, flagIn);
ItemStack item = getItem(stack);
if (!item.isEmpty()) {
tooltip.add(item.getItem().getDisplayName(item));
}
}
@Override
public void fillItemGroup(ItemGroup group, NonNullList<ItemStack> items) {
//if (RS.INSTANCE.config.hideCovers) {
// ItemStack stack = new ItemStack(this);
//setItem(stack, HIDDEN_COVER_ALTERNATIVE);
//items.add(stack);
//return;
//}
if (this.isInGroup(group)) {
for (Block block : ForgeRegistries.BLOCKS.getValues()) {
Item item = Item.getItemFromBlock(block);
if (item == Items.AIR) {
continue;
}
NonNullList<ItemStack> subBlocks = NonNullList.create();
block.fillItemGroup(ItemGroup.SEARCH, subBlocks);
for (ItemStack subBlock : subBlocks) {
if (CoverManager.isValidCover(subBlock)) {
ItemStack stack = new ItemStack(this);
setItem(stack, subBlock);
items.add(stack);
}
}
}
}
}
@Override
public ActionResultType onItemUse(ItemUseContext context) {
BlockPos pos = context.getPos();
Direction facing = context.getFace();
World world = context.getWorld();
ItemStack stack = context.getPlayer().getHeldItem(context.getHand());
TileEntity tile = world.getTileEntity(pos);
// Support placing on the bottom side without too much hassle.
if (!canPlaceOn(tile)) {
pos = pos.up();
facing = Direction.DOWN;
tile = world.getTileEntity(pos);
}
if (canPlaceOn(tile)) {
if (world.isRemote) {
ModelDataManager.requestModelDataRefresh(tile);
return ActionResultType.SUCCESS;
}
INetworkNode node = ((NetworkNodeTile<?>) tile).getNode();
if (node.getNetwork() != null && !node.getNetwork().getSecurityManager().hasPermission(Permission.BUILD, context.getPlayer())) {
WorldUtils.sendNoPermissionMessage(context.getPlayer());
return ActionResultType.FAIL;
}
if (((ICoverable) node).getCoverManager().setCover(facing, createCover(getItem(stack)))) {
context.getPlayer().getHeldItem(context.getHand()).shrink(1);
WorldUtils.updateBlock(world, pos);
API.instance().getNetworkNodeManager((ServerWorld) world).markForSaving();
return ActionResultType.SUCCESS;
}
return ActionResultType.FAIL;
}
return ActionResultType.PASS;
}
private boolean canPlaceOn(TileEntity tile) {
return tile instanceof NetworkNodeTile && ((NetworkNodeTile<?>) tile).getNode() instanceof ICoverable;
}
protected Cover createCover(ItemStack stack) {
return new Cover(stack, CoverType.NORMAL);
}
}

View File

@@ -0,0 +1,17 @@
package com.refinedmods.refinedstorage.item;
import com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover;
import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType;
import net.minecraft.item.ItemStack;
public class HollowCoverItem extends CoverItem{
public HollowCoverItem() {
super();
}
@Override
protected Cover createCover(ItemStack stack) {
return new Cover(stack, CoverType.HOLLOW);
}
}

View File

@@ -0,0 +1,67 @@
package com.refinedmods.refinedstorage.render;
import com.refinedmods.refinedstorage.render.collision.CollisionGroup;
import com.refinedmods.refinedstorage.util.CollisionUtils;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import javax.annotation.Nonnull;
public class ConstantsCable {
public static final CollisionGroup CORE = new CollisionGroup().addItem(CollisionUtils.getBounds(6, 6, 6, 10, 10, 10));
public static final CollisionGroup NORTH = new CollisionGroup().addItem(CollisionUtils.getBounds(6, 6, 0, 10, 10, 6));
public static final CollisionGroup EAST = new CollisionGroup().addItem(CollisionUtils.getBounds(10, 6, 6, 16, 10, 10));
public static final CollisionGroup SOUTH = new CollisionGroup().addItem(CollisionUtils.getBounds(6, 6, 10, 10, 10, 16));
public static final CollisionGroup WEST = new CollisionGroup().addItem(CollisionUtils.getBounds(0, 6, 6, 6, 10, 10));
public static final CollisionGroup UP = new CollisionGroup().addItem(CollisionUtils.getBounds(6, 10, 6, 10, 16, 10));
public static final CollisionGroup DOWN = new CollisionGroup().addItem(CollisionUtils.getBounds(6, 0, 6, 10, 6, 10));
public static final CollisionGroup HOLDER_NORTH = new CollisionGroup().addItem(getHolderBounds(Direction.NORTH));
public static final CollisionGroup HOLDER_EAST = new CollisionGroup().addItem(getHolderBounds(Direction.EAST));
public static final CollisionGroup HOLDER_SOUTH = new CollisionGroup().addItem(getHolderBounds(Direction.SOUTH));
public static final CollisionGroup HOLDER_WEST = new CollisionGroup().addItem(getHolderBounds(Direction.WEST));
public static final CollisionGroup HOLDER_UP = new CollisionGroup().addItem(getHolderBounds(Direction.UP));
public static final CollisionGroup HOLDER_DOWN = new CollisionGroup().addItem(getHolderBounds(Direction.DOWN));
@Nonnull
public static AxisAlignedBB getCoverBounds(Direction side) {
switch (side) {
case DOWN:
return CollisionUtils.getBounds(0, 0, 0, 16, 2, 16);
case UP:
return CollisionUtils.getBounds(0, 14, 0, 16, 16, 16);
case NORTH:
return CollisionUtils.getBounds(0, 0, 0, 16, 16, 2);
case SOUTH:
return CollisionUtils.getBounds(0, 0, 14, 16, 16, 16);
case WEST:
return CollisionUtils.getBounds(0, 0, 0, 2, 16, 16);
case EAST:
return CollisionUtils.getBounds(14, 0, 0, 16, 16, 16);
default:
return null;
}
}
@Nonnull
public static AxisAlignedBB getHolderBounds(Direction side) {
switch (side) {
case DOWN:
return CollisionUtils.getBounds(7, 2, 7, 9, 6, 9);
case UP:
return CollisionUtils.getBounds(7, 10, 7, 9, 14, 9);
case NORTH:
return CollisionUtils.getBounds(7, 7, 2, 9, 9, 6);
case SOUTH:
return CollisionUtils.getBounds(7, 7, 10, 9, 9, 14);
case WEST:
return CollisionUtils.getBounds(2, 7, 7, 6, 9, 9);
case EAST:
return CollisionUtils.getBounds(10, 7, 7, 14, 9, 9);
default:
return null;
}
}
}

View File

@@ -0,0 +1,48 @@
package com.refinedmods.refinedstorage.render.collision;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
public class CollisionGroup {
private List<AxisAlignedBB> items = new ArrayList<>();
private boolean canAccessGui;
@Nullable
private Direction direction;
public CollisionGroup addItem(AxisAlignedBB item) {
items.add(item);
return this;
}
public List<AxisAlignedBB> getItems() {
return items;
}
public boolean canAccessGui() {
return canAccessGui;
}
public CollisionGroup setCanAccessGui(boolean canAccessGui) {
this.canAccessGui = canAccessGui;
return this;
}
public CollisionGroup setDirection(Direction direction) {
this.direction = direction;
return this;
}
@Nullable
public Direction getDirection() {
return direction;
}
}

View File

@@ -0,0 +1,364 @@
package com.refinedmods.refinedstorage.render.model;
import com.refinedmods.refinedstorage.RS;
import com.refinedmods.refinedstorage.RSBlocks;
import com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover;
import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;
import com.refinedmods.refinedstorage.block.BaseBlock;
import com.refinedmods.refinedstorage.render.ConstantsCable;
import com.refinedmods.refinedstorage.util.RenderUtils;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Atlases;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraftforge.client.model.data.IModelData;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class BakedModelCableCover extends DelegateBakedModel{
private static TextureAtlasSprite BORDER_SPRITE;
public BakedModelCableCover(IBakedModel base) {
super(base);
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand, IModelData data) {
List<BakedQuad> quads = new ArrayList<>(base.getQuads(state, side, rand, data));
if (data != null && data.hasProperty(CoverManager.PROPERTY)) {
CoverManager manager = data.getData(CoverManager.PROPERTY);
addCover(quads, manager.getCover(Direction.NORTH), Direction.NORTH, side, rand, manager, state, true);
addCover(quads, manager.getCover(Direction.DOWN), Direction.SOUTH, side, rand, manager, state, true);
addCover(quads, manager.getCover(Direction.EAST), Direction.EAST, side, rand, manager, state, true);
addCover(quads, manager.getCover(Direction.WEST), Direction.WEST, side, rand, manager, state, true);
addCover(quads, manager.getCover(Direction.DOWN), Direction.DOWN, side, rand, manager, state, true);
addCover(quads, manager.getCover(Direction.UP), Direction.UP, side, rand, manager, state, true);
}
return quads;
}
private static int getHollowCoverSize(@Nullable BlockState state, Direction coverSide) {
if (state == null) {
return 6;
}
BaseBlock block = (BaseBlock) state.getBlock();
if (block == RSBlocks.CABLE.get()){
return 6;
}
if (block.getDirection() != null && state.get(block.getDirection().getProperty()) == coverSide) {
if (block == RSBlocks.EXPORTER.get()) {
return 6;
} else if (block == RSBlocks.EXTERNAL_STORAGE.get() || block == RSBlocks.IMPORTER.get()) {
return 3;
} else if (block == RSBlocks.CONSTRUCTOR.get() || block == RSBlocks.DESTRUCTOR.get()) { //Removed reader and writer
return 2;
}
}
return 6;
}
protected static void addCover(List<BakedQuad> quads, @Nullable Cover cover, Direction coverSide, Direction side, Random rand, @Nullable CoverManager manager, BlockState state, boolean handle) {
if (cover == null) {
return;
}
BlockState coverState = CoverManager.getBlockState(cover.getStack());
if (coverState == null) {
return;
}
boolean hasUp = false, hasDown = false, hasEast = false, hasWest = false;
if (manager != null) {
hasUp = manager.hasCover(Direction.UP);
hasDown = manager.hasCover(Direction.DOWN);
hasEast = manager.hasCover(Direction.EAST);
hasWest = manager.hasCover(Direction.WEST);
}
TextureAtlasSprite sprite = RenderUtils.getSprite(Minecraft.getInstance().getBlockRendererDispatcher().getModelForState(coverState), coverState, side, rand);
switch (cover.getType()) {
case NORMAL:
addNormalCover(quads, sprite, coverSide, hasUp, hasDown, hasEast, hasWest, handle);
break;
case HOLLOW:
addHollowCover(quads, sprite, coverSide, hasUp, hasDown, hasEast, hasWest, getHollowCoverSize(state, coverSide));
break;
}
}
private static void addNormalCover(List<BakedQuad> quads, TextureAtlasSprite sprite, Direction coverSide, boolean hasUp, boolean hasDown, boolean hasEast, boolean hasWest, boolean handle) {
AxisAlignedBB bounds = ConstantsCable.getCoverBounds(coverSide);
Vector3f from = new Vector3f((float) bounds.minX * 16, (float) bounds.minY * 16, (float) bounds.minZ * 16);
Vector3f to = new Vector3f((float) bounds.maxX * 16, (float) bounds.maxY * 16, (float) bounds.maxZ * 16);
if (coverSide == Direction.NORTH) {
if (hasWest) {
from.setX(2);
}
if (hasEast) {
to.setX(14);
}
} else if (coverSide == Direction.SOUTH) {
if (hasWest) {
from.setX(2);
}
if (hasEast) {
to.setX(14);
}
}
if (coverSide.getAxis() != Direction.Axis.Y) {
if (hasDown) {
from.setY(2);
}
if (hasUp) {
to.setY(14);
}
}
quads.addAll(new CubeBuilder().from(from.getX(), from.getY(), from.getZ()).to(to.getX(), to.getY(), to.getZ()).addFaces(face -> new CubeBuilder.Face(face, sprite)).bake());
if (handle) {
if (BORDER_SPRITE == null) {
BORDER_SPRITE = Minecraft.getInstance().getAtlasSpriteGetter(AtlasTexture.LOCATION_BLOCKS_TEXTURE).apply(new ResourceLocation(RS.ID , "block/cable_part_border"));
}
bounds = ConstantsCable.getHolderBounds(coverSide);
from = new Vector3f((float) bounds.minX * 16, (float) bounds.minY * 16, (float) bounds.minZ * 16);
to = new Vector3f((float) bounds.maxX * 16, (float) bounds.maxY * 16, (float) bounds.maxZ * 16);
quads.addAll(new CubeBuilder().from(from.getX(), from.getY(), from.getZ()).to(to.getX(), to.getY(), to.getZ()).addFaces(face -> new CubeBuilder.Face(face, BORDER_SPRITE)).bake());
}
}
private static void addHollowCover(List<BakedQuad> quads, TextureAtlasSprite sprite, Direction coverSide, boolean hasUp, boolean hasDown, boolean hasEast, boolean hasWest, int size) {
AxisAlignedBB bounds = ConstantsCable.getCoverBounds(coverSide);
Vector3f from = new Vector3f((float) bounds.minX * 16, (float) bounds.minY * 16, (float) bounds.minZ * 16);
Vector3f to = new Vector3f((float) bounds.maxX * 16, (float) bounds.maxY * 16, (float) bounds.maxZ * 16);
if (coverSide.getAxis() != Direction.Axis.Y) {
if (hasDown) {
from.setY(2);
}
if (hasUp) {
to.setY(14);
}
}
// Right
if (coverSide == Direction.NORTH) {
if (hasWest) {
from.setX(2);
} else {
from.setX(0);
}
to.setX(size);
} else if (coverSide == Direction.SOUTH) {
if (hasEast) {
to.setX(14);
} else {
to.setX(16);
}
from.setX(16 - size);
} else if (coverSide == Direction.EAST) {
from.setZ(0);
to.setZ(size);
} else if (coverSide == Direction.WEST) {
from.setZ(16 - size);
to.setZ(16);
} else if (coverSide == Direction.DOWN || coverSide == Direction.UP) {
from.setZ(16 - size);
to.setZ(16);
}
quads.addAll(new CubeBuilder()
.from(from.getX(), from.getY(), from.getZ())
.to(to.getX(), to.getY(), to.getZ())
.addFaces(face -> new CubeBuilder.Face(face, sprite))
.bake()
);
// Left
if (coverSide == Direction.NORTH) {
if (hasEast) {
to.setX(14);
} else {
to.setX(16);
}
from.setX(16 - size);
} else if (coverSide == Direction.SOUTH) {
if (hasWest) {
from.setX(2);
} else {
from.setX(0);
}
to.setX(size);
} else if (coverSide == Direction.EAST) {
from.setZ(16 - size);
to.setZ(16);
} else if (coverSide == Direction.WEST) {
from.setZ(0);
to.setZ(size);
} else if (coverSide == Direction.DOWN || coverSide == Direction.UP) {
from.setZ(0);
to.setZ(size);
}
quads.addAll(new CubeBuilder()
.from(from.getX(), from.getY(), from.getZ())
.to(to.getX(), to.getY(), to.getZ())
.addFaces(face -> new CubeBuilder.Face(face, sprite))
.bake()
);
// Bottom
if (coverSide == Direction.NORTH) {
from.setX(size);
to.setX(16 - size);
if (hasDown) {
from.setY(2);
} else {
from.setY(0);
}
to.setY(size);
} else if (coverSide == Direction.SOUTH) {
from.setX(size);
to.setX(16 - size);
if (hasDown) {
from.setY(2);
} else {
from.setY(0);
}
to.setY(size);
} else if (coverSide == Direction.EAST) {
from.setZ(size);
to.setZ(16 - size);
if (hasDown) {
from.setY(2);
} else {
from.setY(0);
}
to.setY(size);
} else if (coverSide == Direction.WEST) {
from.setZ(size);
to.setZ(16 - size);
if (hasDown) {
from.setY(2);
} else {
from.setY(0);
}
to.setY(size);
} else if (coverSide == Direction.DOWN || coverSide == Direction.UP) {
from.setZ(size);
to.setZ(16 - size);
from.setX(0);
to.setX(size);
}
quads.addAll(new CubeBuilder()
.from(from.getX(), from.getY(), from.getZ())
.to(to.getX(), to.getY(), to.getZ())
.addFaces(face -> new CubeBuilder.Face(face, sprite))
.bake()
);
// Up
if (coverSide == Direction.NORTH) {
from.setX(size);
to.setX(16 - size);
if (hasUp) {
to.setY(14);
} else {
to.setY(16);
}
from.setY(16 - size);
} else if (coverSide == Direction.SOUTH) {
from.setX(size);
to.setX(16 - size);
if (hasUp) {
to.setY(14);
} else {
to.setY(16);
}
from.setY(16 - size);
} else if (coverSide == Direction.EAST) {
from.setZ(size);
to.setZ(16 - size);
if (hasUp) {
to.setY(14);
} else {
to.setY(16);
}
from.setY(16 - size);
} else if (coverSide == Direction.WEST) {
from.setZ(size);
to.setZ(16 - size);
if (hasUp) {
to.setY(14);
} else {
to.setY(16);
}
from.setY(16 - size);
} else if (coverSide == Direction.DOWN || coverSide == Direction.UP) {
from.setZ(size);
to.setZ(16 - size);
from.setX(16 - size);
to.setX(16);
}
quads.addAll(new CubeBuilder()
.from(from.getX(), from.getY(), from.getZ())
.to(to.getX(), to.getY(), to.getZ())
.addFaces(face -> new CubeBuilder.Face(face, sprite))
.bake()
);
}
}

View File

@@ -0,0 +1,158 @@
package com.refinedmods.refinedstorage.render.model;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover;
import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType;
import com.refinedmods.refinedstorage.item.CoverItem;
import com.refinedmods.refinedstorage.util.RenderUtils;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ItemCameraTransforms;
import net.minecraft.client.renderer.model.ItemOverrideList;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.math.vector.TransformationMatrix;
import javax.annotation.Nullable;
import java.util.*;
public class BakedModelCover extends BakedModelCableCover{
private class CacheKey {
private BlockState state;
private ItemStack stack;
private Direction side;
private CoverType type;
CacheKey(BlockState state, ItemStack stack, Direction side, CoverType type) {
this.state = state;
this.stack = stack;
this.side = side;
this.type = type;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
BakedModelCover.CacheKey cacheKey = (BakedModelCover.CacheKey) o;
return cacheKey.type == type && cacheKey.stack.getItem() == stack.getItem() /* && cacheKey.stack.getItemDamage() == stack.getItemDamage()*/ && cacheKey.side == side && Objects.equals(cacheKey.state, state);
}
@Override
public int hashCode() {
int result = stack.getItem().hashCode();
//result = 31 * result + stack.getDamage();
result = 31 * result + (side != null ? side.hashCode() : 0);
result = 31 * result + (state != null ? state.hashCode() : 0);
result = 31 * result + type.hashCode();
return result;
}
}
private static final LoadingCache<CacheKey, List<BakedQuad>> CACHE = CacheBuilder.newBuilder().build(new CacheLoader<CacheKey, List<BakedQuad>>() {
@Override
public List<BakedQuad> load(CacheKey key) {
List<BakedQuad> quads = new ArrayList<>();
addCover(quads, new Cover(key.stack, key.type), Direction.NORTH, key.side, new Random(), null, null, true);
return quads;
}
});
private ItemStack stack;
private CoverType type;
public BakedModelCover(ItemStack stack, CoverType type) {
super(null);
this.stack = stack;
this.type = type;
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
if (stack.isEmpty()) {
return Collections.emptyList();
}
CacheKey key = new CacheKey(state, CoverItem.getItem(stack), side, type);
return CACHE.getUnchecked(key);
}
@Override
public ItemOverrideList getOverrides() {
return new ItemOverrideList() {
@Override
public IBakedModel func_239290_a_(IBakedModel originalModel, ItemStack stack, @Nullable ClientWorld world, @Nullable LivingEntity entity) {
return new BakedModelCover(stack, type);
}
};
}
// @Override
// public Pair<? extends IBakedModel, Matrix4f> handlePerspective(ItemCameraTransforms.TransformType cameraTransformType) {
// TRSRTransformation transform = RenderUtils.getDefaultBlockTransforms().get(cameraTransformType);
//
// return Pair.of(this, transform == null ? RenderUtils.EMPTY_MATRIX_TRANSFORM : transform.getMatrix());
// }
@Override
public IBakedModel handlePerspective(ItemCameraTransforms.TransformType cameraTransformType, MatrixStack matrixStack) {
TransformationMatrix transform = RenderUtils.getDefaultBlockTransforms().get(cameraTransformType);
if (transform != null) transform.push(matrixStack);
return this;
}
@Override
public boolean isAmbientOcclusion() {
return true;
}
@Override
public boolean isGui3d() {
return true;
}
@Override
public boolean isBuiltInRenderer() {
return false;
}
@Override
public TextureAtlasSprite getParticleTexture() {
return null;
}
@Override
public boolean isAmbientOcclusion(BlockState state) {
return true;
}
@Override
@SuppressWarnings("deprecation")
public ItemCameraTransforms getItemCameraTransforms() {
return ItemCameraTransforms.DEFAULT;
}
@Override
public boolean func_230044_c_() {
return true;
}
}

View File

@@ -0,0 +1,354 @@
package com.refinedmods.refinedstorage.render.model;
import com.refinedmods.refinedstorage.util.RenderUtils;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.util.Direction;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
public class CubeBuilder {
public enum UvRotation {
CLOCKWISE_0,
CLOCKWISE_90,
CLOCKWISE_180,
CLOCKWISE_270
}
private static class Uv {
private float xFrom;
private float xTo;
private float yFrom;
private float yTo;
}
public static class Face {
private Direction face;
private TextureAtlasSprite sprite;
private int light;
private UvRotation uvRotation = UvRotation.CLOCKWISE_0;
public Face(Direction face, TextureAtlasSprite sprite) {
this.face = face;
this.sprite = sprite;
}
public Face(Direction face, TextureAtlasSprite sprite, UvRotation uvRotation) {
this(face, sprite);
this.uvRotation = uvRotation;
}
public Face(Direction face, TextureAtlasSprite sprite, UvRotation uvRotation, int light) {
this(face, sprite, uvRotation);
this.light = light;
}
}
private Vector3f from;
private Vector3f to;
private VertexFormat format = DefaultVertexFormats.BLOCK; //Changed from Item
private Map<Direction, Face> faces = new HashMap<>();
private int color = 0xFFFFFFFF;
public CubeBuilder from(float x, float y, float z) {
this.from = new Vector3f(x / 16, y / 16, z / 16);
return this;
}
public CubeBuilder to(float x, float y, float z) {
this.to = new Vector3f(x / 16, y / 16, z / 16);
return this;
}
public CubeBuilder color(int color) {
this.color = color;
return this;
}
public CubeBuilder lightmap() {
this.format = RenderUtils.getFormatWithLightMap(format);
return this;
}
public CubeBuilder addFaces(Function<Direction, Face> faceSupplier) {
for (Direction facing : Direction.values()) {
addFace(faceSupplier.apply(facing));
}
return this;
}
public CubeBuilder addFace(Face face) {
faces.put(face.face, face);
return this;
}
public List<BakedQuad> bake() {
List<BakedQuad> quads = new ArrayList<>();
for (Map.Entry<Direction, Face> entry : faces.entrySet()) {
quads.add(bakeFace(entry.getKey(), entry.getValue()));
}
return quads;
}
private BakedQuad bakeFace(Direction facing, Face cubeFace) {
BakedQuadBuilder builder = new BakedQuadBuilder(cubeFace.sprite); //TODO See if can change the vertex format
//builder.setTexture(cubeFace.sprite);
builder.setQuadOrientation(facing);
builder.setQuadTint(-1);
builder.setApplyDiffuseLighting(true);
Uv uv = getDefaultUv(facing, cubeFace.sprite, from.getX(), from.getY(), from.getZ(), to.getX(), to.getY(), to.getZ());
switch (facing) {
case DOWN:
addVertexTopRight(builder, cubeFace, to.getX(), from.getY(), from.getZ(), uv);
addVertexBottomRight(builder, cubeFace, to.getX(), from.getY(), to.getZ(), uv);
addVertexBottomLeft(builder, cubeFace, from.getX(), from.getY(), to.getZ(), uv);
addVertexTopLeft(builder, cubeFace, from.getX(), from.getY(), from.getZ(), uv);
break;
case UP:
addVertexTopLeft(builder, cubeFace, from.getX(), to.getY(), from.getZ(), uv);
addVertexBottomLeft(builder, cubeFace, from.getX(), to.getY(), to.getZ(), uv);
addVertexBottomRight(builder, cubeFace, to.getX(), to.getY(), to.getZ(), uv);
addVertexTopRight(builder, cubeFace, to.getX(), to.getY(), from.getZ(), uv);
break;
case NORTH:
addVertexBottomRight(builder, cubeFace, to.getX(), to.getY(), from.getZ(), uv);
addVertexTopRight(builder, cubeFace, to.getX(), from.getY(), from.getZ(), uv);
addVertexTopLeft(builder, cubeFace, from.getX(), from.getY(), from.getZ(), uv);
addVertexBottomLeft(builder, cubeFace, from.getX(), to.getY(), from.getZ(), uv);
break;
case SOUTH:
addVertexBottomLeft(builder, cubeFace, from.getX(), to.getY(), to.getZ(), uv);
addVertexTopLeft(builder, cubeFace, from.getX(), from.getY(), to.getZ(), uv);
addVertexTopRight(builder, cubeFace, to.getX(), from.getY(), to.getZ(), uv);
addVertexBottomRight(builder, cubeFace, to.getX(), to.getY(), to.getZ(), uv);
break;
case WEST:
addVertexTopLeft(builder, cubeFace, from.getX(), from.getY(), from.getZ(), uv);
addVertexTopRight(builder, cubeFace, from.getX(), from.getY(), to.getZ(), uv);
addVertexBottomRight(builder, cubeFace, from.getX(), to.getY(), to.getZ(), uv);
addVertexBottomLeft(builder, cubeFace, from.getX(), to.getY(), from.getZ(), uv);
break;
case EAST:
addVertexBottomRight(builder, cubeFace, to.getX(), to.getY(), from.getZ(), uv);
addVertexBottomLeft(builder, cubeFace, to.getX(), to.getY(), to.getZ(), uv);
addVertexTopLeft(builder, cubeFace, to.getX(), from.getY(), to.getZ(), uv);
addVertexTopRight(builder, cubeFace, to.getX(), from.getY(), from.getZ(), uv);
break;
}
return builder.build();
}
private Uv getDefaultUv(Direction face, TextureAtlasSprite texture, float fromX, float fromY, float fromZ, float toX, float toY, float toZ) {
Uv uv = new Uv();
switch (face) {
case DOWN:
uv.xFrom = texture.getInterpolatedU(fromX * 16);
uv.yFrom = texture.getInterpolatedV(16 - fromZ * 16);
uv.xTo = texture.getInterpolatedU(toX * 16);
uv.yTo = texture.getInterpolatedV(16 - toZ * 16);
break;
case UP:
uv.xFrom = texture.getInterpolatedU(fromX * 16);
uv.yFrom = texture.getInterpolatedV(fromZ * 16);
uv.xTo = texture.getInterpolatedU(toX * 16);
uv.yTo = texture.getInterpolatedV(toZ * 16);
break;
case NORTH:
uv.xFrom = texture.getInterpolatedU(16 - fromX * 16);
uv.yFrom = texture.getInterpolatedV(16 - fromY * 16);
uv.xTo = texture.getInterpolatedU(16 - toX * 16);
uv.yTo = texture.getInterpolatedV(16 - toY * 16);
break;
case SOUTH:
uv.xFrom = texture.getInterpolatedU(fromX * 16);
uv.yFrom = texture.getInterpolatedV(16 - fromY * 16);
uv.xTo = texture.getInterpolatedU(toX * 16);
uv.yTo = texture.getInterpolatedV(16 - toY * 16);
break;
case WEST:
uv.xFrom = texture.getInterpolatedU(fromZ * 16);
uv.yFrom = texture.getInterpolatedV(16 - fromY * 16);
uv.xTo = texture.getInterpolatedU(toZ * 16);
uv.yTo = texture.getInterpolatedV(16 - toY * 16);
break;
case EAST:
uv.xFrom = texture.getInterpolatedU(16 - toZ * 16);
uv.yFrom = texture.getInterpolatedV(16 - fromY * 16);
uv.xTo = texture.getInterpolatedU(16 - fromZ * 16);
uv.yTo = texture.getInterpolatedV(16 - toY * 16);
break;
}
return uv;
}
private void addVertexTopLeft(BakedQuadBuilder builder, Face face, float x, float y, float z, Uv uv) {
float u;
float v;
switch (face.uvRotation) {
default:
case CLOCKWISE_0:
u = uv.xFrom;
v = uv.yFrom;
break;
case CLOCKWISE_90:
u = uv.xFrom;
v = uv.yTo;
break;
case CLOCKWISE_180:
u = uv.xTo;
v = uv.yTo;
break;
case CLOCKWISE_270:
u = uv.xTo;
v = uv.yFrom;
break;
}
addVertex(builder, face, x, y, z, u, v);
}
private void addVertexTopRight(BakedQuadBuilder builder, Face face, float x, float y, float z, Uv uv) {
float u;
float v;
switch (face.uvRotation) {
default:
case CLOCKWISE_0:
u = uv.xTo;
v = uv.yFrom;
break;
case CLOCKWISE_90:
u = uv.xFrom;
v = uv.yFrom;
break;
case CLOCKWISE_180:
u = uv.xFrom;
v = uv.yTo;
break;
case CLOCKWISE_270:
u = uv.xTo;
v = uv.yTo;
break;
}
addVertex(builder, face, x, y, z, u, v);
}
private void addVertexBottomRight(BakedQuadBuilder builder, Face face, float x, float y, float z, Uv uv) {
float u;
float v;
switch (face.uvRotation) {
default:
case CLOCKWISE_0:
u = uv.xTo;
v = uv.yTo;
break;
case CLOCKWISE_90:
u = uv.xTo;
v = uv.yFrom;
break;
case CLOCKWISE_180:
u = uv.xFrom;
v = uv.yFrom;
break;
case CLOCKWISE_270:
u = uv.xFrom;
v = uv.yTo;
break;
}
addVertex(builder, face, x, y, z, u, v);
}
private void addVertexBottomLeft(BakedQuadBuilder builder, Face face, float x, float y, float z, Uv uv) {
float u;
float v;
switch (face.uvRotation) {
default:
case CLOCKWISE_0:
u = uv.xFrom;
v = uv.yTo;
break;
case CLOCKWISE_90:
u = uv.xTo;
v = uv.yTo;
break;
case CLOCKWISE_180:
u = uv.xTo;
v = uv.yFrom;
break;
case CLOCKWISE_270:
u = uv.xFrom;
v = uv.yFrom;
break;
}
addVertex(builder, face, x, y, z, u, v);
}
private void addVertex(BakedQuadBuilder builder, Face face, float x, float y, float z, float u, float v) {
VertexFormat format = builder.getVertexFormat();
for (int i = 0; i < format.getElements().size(); i++) {
VertexFormatElement e = format.getElements().get(i);
switch (e.getUsage()) {
case POSITION:
builder.put(i, x, y, z);
break;
case NORMAL:
builder.put(i, face.face.getXOffset(), face.face.getYOffset(), face.face.getZOffset());
break;
case COLOR:
float r = (color >> 16 & 0xFF) / 255F;
float g = (color >> 8 & 0xFF) / 255F;
float b = (color & 0xFF) / 255F;
float a = (color >> 24 & 0xFF) / 255F;
builder.put(i, r, g, b, a);
break;
case UV:
if (e.getIndex() == 0) {
builder.put(i, u, v);
} else {
builder.put(i, (float) (face.light * 0x20) / 0xFFFF, (float) (face.light * 0x20) / 0xFFFF);
}
break;
default:
builder.put(i);
break;
}
}
}
}

View File

@@ -2,6 +2,7 @@ package com.refinedmods.refinedstorage.setup;
import com.refinedmods.refinedstorage.*; import com.refinedmods.refinedstorage.*;
import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.API;
import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType;
import com.refinedmods.refinedstorage.container.CrafterContainer; import com.refinedmods.refinedstorage.container.CrafterContainer;
import com.refinedmods.refinedstorage.container.CrafterManagerContainer; import com.refinedmods.refinedstorage.container.CrafterManagerContainer;
import com.refinedmods.refinedstorage.container.slot.CrafterManagerSlot; import com.refinedmods.refinedstorage.container.slot.CrafterManagerSlot;
@@ -23,14 +24,17 @@ import net.minecraft.client.gui.ScreenManager;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.RenderTypeLookup; import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.Slot; import net.minecraft.inventory.container.Slot;
import net.minecraft.item.DyeColor; import net.minecraft.item.DyeColor;
import net.minecraft.item.ItemModelsProperties; import net.minecraft.item.ItemModelsProperties;
import net.minecraft.item.ItemStack;
import net.minecraft.resources.IReloadableResourceManager; import net.minecraft.resources.IReloadableResourceManager;
import net.minecraft.resources.IResourceManager; import net.minecraft.resources.IResourceManager;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.ModelBakeEvent; import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
@@ -107,6 +111,9 @@ public class ClientSetup {
false, false,
new ResourceLocation(RS.ID, "block/disks/leds") new ResourceLocation(RS.ID, "block/disks/leds")
)); ));
bakedModelOverrideRegistry.add(new ResourceLocation(RS.ID, "cable"), (base, registry) -> new BakedModelCableCover(base));
bakedModelOverrideRegistry.add(new ResourceLocation(RS.ID, "cover"), (base, registry) -> new BakedModelCover(ItemStack.EMPTY, CoverType.NORMAL));
bakedModelOverrideRegistry.add(new ResourceLocation(RS.ID, "hollow_cover"), (base, registry) -> new BakedModelCover(ItemStack.EMPTY, CoverType.HOLLOW));
forEachColorApply("disk_manipulator", (name, color) -> bakedModelOverrideRegistry.add(name, (base, registry) -> new FullbrightBakedModel( forEachColorApply("disk_manipulator", (name, color) -> bakedModelOverrideRegistry.add(name, (base, registry) -> new FullbrightBakedModel(
new DiskManipulatorBakedModel( new DiskManipulatorBakedModel(
@@ -167,6 +174,7 @@ public class ClientSetup {
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onClientSetup); FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onClientSetup);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onModelBake); FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onModelBake);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onTextureStitch);
MinecraftForge.EVENT_BUS.addListener(new ExperimentalLightingPipelineNagger()::onPlayerLoggedIn); MinecraftForge.EVENT_BUS.addListener(new ExperimentalLightingPipelineNagger()::onPlayerLoggedIn);
API.instance().addPatternRenderHandler(pattern -> Screen.hasShiftDown()); API.instance().addPatternRenderHandler(pattern -> Screen.hasShiftDown());
@@ -305,4 +313,10 @@ public class ClientSetup {
} }
} }
} }
@SubscribeEvent
public void onTextureStitch(TextureStitchEvent.Pre event){
if (event.getMap().getTextureLocation().equals(AtlasTexture.LOCATION_BLOCKS_TEXTURE))
event.addSprite(new ResourceLocation(RS.ID ,"block/cable_part_border"));
}
} }

View File

@@ -1,15 +1,46 @@
package com.refinedmods.refinedstorage.tile; package com.refinedmods.refinedstorage.tile;
import com.refinedmods.refinedstorage.RSTiles; import com.refinedmods.refinedstorage.RSTiles;
import com.refinedmods.refinedstorage.api.network.node.ICoverable;
import com.refinedmods.refinedstorage.apiimpl.network.node.CableNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.CableNetworkNode;
import com.refinedmods.refinedstorage.apiimpl.network.node.DiskState;
import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager;
import com.refinedmods.refinedstorage.tile.data.TileDataManager;
import com.refinedmods.refinedstorage.tile.data.TileDataParameter;
import com.refinedmods.refinedstorage.util.WorldUtils;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.client.Minecraft;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.IntNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.IDataSerializer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.client.model.ModelDataManager;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelDataMap;
import net.minecraftforge.client.model.data.ModelProperty;
import net.minecraftforge.common.util.Constants;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.HashMap;
public class CableTile extends NetworkNodeTile<CableNetworkNode> { public class CableTile extends NetworkNodeTile<CableNetworkNode> {
public static final TileDataParameter<CompoundNBT, CableTile> COVER_MANAGER = new TileDataParameter<>(DataSerializers.COMPOUND_NBT, new CompoundNBT(), t -> t.getNode().getCoverManager().writeToNbt(), (t, v) -> t.getNode().getCoverManager().readFromNbt(v), (initial, p) -> Minecraft.getInstance().enqueue(() -> {
}));
static {
TileDataManager.registerParameter(COVER_MANAGER);
}
public CableTile() { public CableTile() {
super(RSTiles.CABLE); super(RSTiles.CABLE);
dataManager.addWatchedParameter(COVER_MANAGER);
} }
@Override @Override
@@ -17,4 +48,30 @@ public class CableTile extends NetworkNodeTile<CableNetworkNode> {
public CableNetworkNode createNode(World world, BlockPos pos) { public CableNetworkNode createNode(World world, BlockPos pos) {
return new CableNetworkNode(world, pos); return new CableNetworkNode(world, pos);
} }
@Nonnull
@Override
public IModelData getModelData() {
return new ModelDataMap.Builder().withInitial(CoverManager.PROPERTY, this.getNode().getCoverManager()).build();
}
@Override
public CompoundNBT writeUpdate(CompoundNBT tag) {
super.writeUpdate(tag);
tag.put("Covers", this.getNode().getCoverManager().writeToNbt());
return tag;
}
@Override
public void readUpdate(CompoundNBT tag) {
super.readUpdate(tag);
this.getNode().getCoverManager().readFromNbt(tag.getCompound("Covers"));
requestModelDataUpdate();
WorldUtils.updateBlock(world, pos);
}
} }

View File

@@ -19,4 +19,9 @@ public final class CollisionUtils {
&& hit.z >= aabb.minZ && hit.z >= aabb.minZ
&& hit.z <= aabb.maxZ; && hit.z <= aabb.maxZ;
} }
public static AxisAlignedBB getBounds(int fromX, int fromY, int fromZ, int toX, int toY, int toZ) {
return new AxisAlignedBB((float) fromX / 16F, (float) fromY / 16F, (float) fromZ / 16F, (float) toX / 16F, (float) toY / 16F, (float) toZ / 16F);
}
} }

View File

@@ -1,29 +1,45 @@
package com.refinedmods.refinedstorage.util; package com.refinedmods.refinedstorage.util;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.IComparer;
import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.API;
import com.refinedmods.refinedstorage.render.Styles; import com.refinedmods.refinedstorage.render.Styles;
import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.BaseScreen;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ItemCameraTransforms;
import net.minecraft.client.renderer.model.ItemTransformVec3f;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.client.util.ITooltipFlag; import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Quaternion;
import net.minecraft.util.math.vector.TransformationMatrix;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraft.util.text.*; import net.minecraft.util.text.*;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.client.event.RenderTooltipEvent; import net.minecraftforge.client.event.RenderTooltipEvent;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fml.client.gui.GuiUtils; import net.minecraftforge.fml.client.gui.GuiUtils;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.ArrayList; import java.util.*;
import java.util.HashSet; import java.util.function.Consumer;
import java.util.List;
import java.util.Set;
public final class RenderUtils { public final class RenderUtils {
private RenderUtils() { private RenderUtils() {
@@ -299,4 +315,100 @@ public final class RenderUtils {
public static boolean inBounds(int x, int y, int w, int h, double ox, double oy) { public static boolean inBounds(int x, int y, int w, int h, double ox, double oy) {
return ox >= x && ox <= x + w && oy >= y && oy <= y + h; return ox >= x && ox <= x + w && oy >= y && oy <= y + h;
} }
public static boolean isLightMapDisabled() {
return false; //FMLClientHandler.instance().hasOptifine() || !ForgeModContainer.forgeLightPipelineEnabled; TODO
}
public static VertexFormat getFormatWithLightMap(VertexFormat format) {
if (isLightMapDisabled()) {
return format;
}
if (format == DefaultVertexFormats.BLOCK) {
return DefaultVertexFormats.BLOCK;
} else if (!format.hasUV(1)) { ;
return new VertexFormat(ImmutableList.<VertexFormatElement>builder().addAll(format.getElements()).add(DefaultVertexFormats.TEX_2S).build());
}
return format;
}
public static TextureAtlasSprite getSprite(IBakedModel coverModel, BlockState coverState, Direction facing, Random rand) {
TextureAtlasSprite sprite = null;
RenderType originalLayer = MinecraftForgeClient.getRenderLayer();
try {
for (RenderType layer : RenderType.getBlockRenderTypes()) {
ForgeHooksClient.setRenderLayer(layer);
for (BakedQuad bakedQuad : coverModel.getQuads(coverState, facing, rand)) {
return bakedQuad.func_187508_a();
}
for (BakedQuad bakedQuad : coverModel.getQuads(coverState, null, rand)) {
if (sprite == null) {
sprite = bakedQuad.func_187508_a();
}
if (bakedQuad.getFace() == facing) {
return bakedQuad.func_187508_a();
}
}
}
} catch (Exception e) {
// NO OP
} finally {
ForgeHooksClient.setRenderLayer(originalLayer);
}
if (sprite == null) {
try {
sprite = coverModel.getParticleTexture();
} catch (Exception e) {
// NO OP
}
}
if (sprite == null) {
sprite = null; //TODO Get missing sprite
}
return sprite;
}
private static ImmutableMap<ItemCameraTransforms.TransformType, TransformationMatrix> DEFAULT_BLOCK_TRANSFORM;
public static ImmutableMap<ItemCameraTransforms.TransformType, TransformationMatrix> getDefaultBlockTransforms() {
if (DEFAULT_BLOCK_TRANSFORM != null) {
return DEFAULT_BLOCK_TRANSFORM;
}
TransformationMatrix thirdperson = getTransform(0, 2.5f, 0, 75, 45, 0, 0.375f);
return DEFAULT_BLOCK_TRANSFORM = ImmutableMap.<ItemCameraTransforms.TransformType, TransformationMatrix>builder()
.put(ItemCameraTransforms.TransformType.GUI, getTransform(0, 0, 0, 30, 225, 0, 0.625f))
.put(ItemCameraTransforms.TransformType.GROUND, getTransform(0, 3, 0, 0, 0, 0, 0.25f))
.put(ItemCameraTransforms.TransformType.FIXED, getTransform(0, 0, 0, 0, 0, 0, 0.5f))
.put(ItemCameraTransforms.TransformType.THIRD_PERSON_RIGHT_HAND, thirdperson)
.put(ItemCameraTransforms.TransformType.THIRD_PERSON_LEFT_HAND, leftifyTransform(thirdperson))
.put(ItemCameraTransforms.TransformType.FIRST_PERSON_RIGHT_HAND, getTransform(0, 0, 0, 0, 45, 0, 0.4f))
.put(ItemCameraTransforms.TransformType.FIRST_PERSON_LEFT_HAND, getTransform(0, 0, 0, 0, 225, 0, 0.4f))
.build();
}
private static TransformationMatrix leftifyTransform(TransformationMatrix transform) {
return transform.blockCornerToCenter().blockCenterToCorner();
}
private static TransformationMatrix getTransform(float tx, float ty, float tz, float ax, float ay, float az, float s) {
return new TransformationMatrix(
new Vector3f(tx / 16, ty / 16, tz / 16),
new Quaternion(ax, ay, az, true),
new Vector3f(s, s, s),
null
);
}
} }