mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-01-23 03:18:06 +01:00
Schematicannon and Holograms
- Uploaded Blueprints can be previewed by the owner - The Schematicannon prints the schematic from blocks in attached inventories
This commit is contained in:
parent
550b477d8d
commit
b66aa4c4d3
15 changed files with 1002 additions and 66 deletions
|
@ -1,5 +1,6 @@
|
||||||
package com.simibubi.create;
|
package com.simibubi.create;
|
||||||
|
|
||||||
|
import com.simibubi.create.item.ItemBlueprint;
|
||||||
import com.simibubi.create.item.ItemWandSymmetry;
|
import com.simibubi.create.item.ItemWandSymmetry;
|
||||||
|
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
|
@ -11,7 +12,7 @@ public enum AllItems {
|
||||||
|
|
||||||
SYMMETRY_WAND(new ItemWandSymmetry(standardProperties())),
|
SYMMETRY_WAND(new ItemWandSymmetry(standardProperties())),
|
||||||
EMPTY_BLUEPRINT(new Item(standardProperties().maxStackSize(1))),
|
EMPTY_BLUEPRINT(new Item(standardProperties().maxStackSize(1))),
|
||||||
BLUEPRINT(new Item(standardProperties().maxStackSize(1)));
|
BLUEPRINT(new ItemBlueprint(standardProperties()));
|
||||||
|
|
||||||
public Item item;
|
public Item item;
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import com.simibubi.create.networking.Packets;
|
import com.simibubi.create.networking.Packets;
|
||||||
|
import com.simibubi.create.schematic.SchematicHologram;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
|
@ -50,6 +51,7 @@ public class Create {
|
||||||
AllTileEntities.registerRenderers();
|
AllTileEntities.registerRenderers();
|
||||||
cSchematicLoader = new ClientSchematicLoader();
|
cSchematicLoader = new ClientSchematicLoader();
|
||||||
sSchematicLoader = new ServerSchematicLoader();
|
sSchematicLoader = new ServerSchematicLoader();
|
||||||
|
new SchematicHologram();
|
||||||
// ScrollFixer.init();
|
// ScrollFixer.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ import net.minecraft.util.text.TextFormatting;
|
||||||
|
|
||||||
public class ServerSchematicLoader {
|
public class ServerSchematicLoader {
|
||||||
|
|
||||||
private static final String PATH = "schematics/uploaded";
|
public static final String PATH = "schematics/uploaded";
|
||||||
private Map<String, OutputStream> activeDownloads;
|
private Map<String, OutputStream> activeDownloads;
|
||||||
private Map<String, DimensionPos> activeTables;
|
private Map<String, DimensionPos> activeTables;
|
||||||
|
|
||||||
|
@ -38,6 +38,9 @@ public class ServerSchematicLoader {
|
||||||
|
|
||||||
FilesHelper.createFolderIfMissing(playerPath);
|
FilesHelper.createFolderIfMissing(playerPath);
|
||||||
|
|
||||||
|
if (activeDownloads.containsKey(playerSchematicId))
|
||||||
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Files.deleteIfExists(Paths.get(PATH, playerSchematicId));
|
Files.deleteIfExists(Paths.get(PATH, playerSchematicId));
|
||||||
OutputStream writer = Files.newOutputStream(Paths.get(PATH, playerSchematicId),
|
OutputStream writer = Files.newOutputStream(Paths.get(PATH, playerSchematicId),
|
||||||
|
@ -45,6 +48,15 @@ public class ServerSchematicLoader {
|
||||||
Create.logger.info("Receiving New Schematic: " + playerSchematicId);
|
Create.logger.info("Receiving New Schematic: " + playerSchematicId);
|
||||||
activeDownloads.put(playerSchematicId, writer);
|
activeDownloads.put(playerSchematicId, writer);
|
||||||
activeTables.put(playerSchematicId, dimensionPos);
|
activeTables.put(playerSchematicId, dimensionPos);
|
||||||
|
|
||||||
|
if (player.openContainer instanceof SchematicTableContainer) {
|
||||||
|
SchematicTableContainer c = (SchematicTableContainer) player.openContainer;
|
||||||
|
c.schematicUploading = schematic;
|
||||||
|
c.isUploading = true;
|
||||||
|
c.sendSchematicUpdate = true;
|
||||||
|
player.openContainer.detectAndSendChanges();
|
||||||
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -53,11 +65,14 @@ public class ServerSchematicLoader {
|
||||||
public void handleWriteRequest(ServerPlayerEntity player, String schematic, byte[] data) {
|
public void handleWriteRequest(ServerPlayerEntity player, String schematic, byte[] data) {
|
||||||
String playerSchematicId = player.getName().getFormattedText() + "/" + schematic;
|
String playerSchematicId = player.getName().getFormattedText() + "/" + schematic;
|
||||||
if (activeDownloads.containsKey(playerSchematicId)) {
|
if (activeDownloads.containsKey(playerSchematicId)) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
activeDownloads.get(playerSchematicId).write(data);
|
activeDownloads.get(playerSchematicId).write(data);
|
||||||
Create.logger.info("Writing to Schematic: " + playerSchematicId);
|
Create.logger.info("Writing to Schematic: " + playerSchematicId);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
activeDownloads.remove(playerSchematicId);
|
||||||
|
activeTables.remove(playerSchematicId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,13 +83,27 @@ public class ServerSchematicLoader {
|
||||||
if (activeDownloads.containsKey(playerSchematicId)) {
|
if (activeDownloads.containsKey(playerSchematicId)) {
|
||||||
try {
|
try {
|
||||||
activeDownloads.get(playerSchematicId).close();
|
activeDownloads.get(playerSchematicId).close();
|
||||||
|
activeDownloads.remove(playerSchematicId);
|
||||||
Create.logger.info("Finished receiving Schematic: " + playerSchematicId);
|
Create.logger.info("Finished receiving Schematic: " + playerSchematicId);
|
||||||
|
|
||||||
DimensionPos dimpos = activeTables.remove(playerSchematicId);
|
DimensionPos dimpos = activeTables.remove(playerSchematicId);
|
||||||
|
|
||||||
|
if (dimpos == null)
|
||||||
|
return;
|
||||||
|
|
||||||
BlockState blockState = dimpos.world.getBlockState(dimpos.pos);
|
BlockState blockState = dimpos.world.getBlockState(dimpos.pos);
|
||||||
if (!AllBlocks.SCHEMATIC_TABLE.typeOf(blockState))
|
if (!AllBlocks.SCHEMATIC_TABLE.typeOf(blockState))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (player.openContainer instanceof SchematicTableContainer) {
|
||||||
|
SchematicTableContainer c = (SchematicTableContainer) player.openContainer;
|
||||||
|
c.isUploading = false;
|
||||||
|
c.schematicUploading = null;
|
||||||
|
c.progress = 0;
|
||||||
|
c.sendSchematicUpdate = true;
|
||||||
|
c.detectAndSendChanges();
|
||||||
|
}
|
||||||
|
|
||||||
SchematicTableTileEntity tileEntity = (SchematicTableTileEntity) dimpos.world.getTileEntity(dimpos.pos);
|
SchematicTableTileEntity tileEntity = (SchematicTableTileEntity) dimpos.world.getTileEntity(dimpos.pos);
|
||||||
if (tileEntity.inputStack.isEmpty())
|
if (tileEntity.inputStack.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
@ -82,15 +111,19 @@ public class ServerSchematicLoader {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tileEntity.inputStack = ItemStack.EMPTY;
|
tileEntity.inputStack = ItemStack.EMPTY;
|
||||||
tileEntity.outputStack = new ItemStack(AllItems.BLUEPRINT.get());
|
ItemStack blueprint = new ItemStack(AllItems.BLUEPRINT.get());
|
||||||
tileEntity.outputStack
|
blueprint.setDisplayName(new StringTextComponent(TextFormatting.RESET + "" + TextFormatting.WHITE
|
||||||
.setDisplayName(new StringTextComponent(TextFormatting.RESET + "" + TextFormatting.WHITE
|
+ "Blueprint (" + TextFormatting.GOLD + schematic + TextFormatting.WHITE + ")"));
|
||||||
+ "Blueprint (" + TextFormatting.GOLD + schematic + TextFormatting.WHITE + ")"));
|
blueprint.getTag().putString("Owner", player.getName().getFormattedText());
|
||||||
tileEntity.markDirty();
|
blueprint.getTag().putString("File", schematic);
|
||||||
|
|
||||||
|
tileEntity.outputStack = blueprint;
|
||||||
|
|
||||||
dimpos.world.notifyBlockUpdate(dimpos.pos, blockState, blockState, 3);
|
dimpos.world.notifyBlockUpdate(dimpos.pos, blockState, blockState, 3);
|
||||||
|
|
||||||
if (player.openContainer instanceof SchematicTableContainer) {
|
if (player.openContainer instanceof SchematicTableContainer) {
|
||||||
((SchematicTableContainer) player.openContainer).updateContent();
|
SchematicTableContainer c = (SchematicTableContainer) player.openContainer;
|
||||||
player.openContainer.detectAndSendChanges();
|
c.updateContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
|
@ -2,14 +2,20 @@ package com.simibubi.create.block;
|
||||||
|
|
||||||
import com.simibubi.create.AllContainers;
|
import com.simibubi.create.AllContainers;
|
||||||
import com.simibubi.create.AllItems;
|
import com.simibubi.create.AllItems;
|
||||||
|
import com.simibubi.create.networking.PacketSchematicTableContainer;
|
||||||
|
import com.simibubi.create.networking.Packets;
|
||||||
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
import net.minecraft.inventory.IInventory;
|
import net.minecraft.inventory.IInventory;
|
||||||
import net.minecraft.inventory.Inventory;
|
import net.minecraft.inventory.Inventory;
|
||||||
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.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import net.minecraftforge.fml.network.PacketDistributor;
|
||||||
|
|
||||||
public class SchematicTableContainer extends Container {
|
public class SchematicTableContainer extends Container {
|
||||||
|
|
||||||
|
@ -23,6 +29,12 @@ public class SchematicTableContainer extends Container {
|
||||||
private SchematicTableTileEntity te;
|
private SchematicTableTileEntity te;
|
||||||
private Slot inputSlot;
|
private Slot inputSlot;
|
||||||
private Slot outputSlot;
|
private Slot outputSlot;
|
||||||
|
private PlayerEntity player;
|
||||||
|
|
||||||
|
public String schematicUploading;
|
||||||
|
public boolean isUploading;
|
||||||
|
public float progress;
|
||||||
|
public boolean sendSchematicUpdate;
|
||||||
|
|
||||||
public SchematicTableContainer(int id, PlayerInventory inv) {
|
public SchematicTableContainer(int id, PlayerInventory inv) {
|
||||||
this(id, inv, null);
|
this(id, inv, null);
|
||||||
|
@ -30,6 +42,7 @@ public class SchematicTableContainer extends Container {
|
||||||
|
|
||||||
public SchematicTableContainer(int id, PlayerInventory inv, SchematicTableTileEntity te) {
|
public SchematicTableContainer(int id, PlayerInventory inv, SchematicTableTileEntity te) {
|
||||||
super(AllContainers.SchematicTable.type, id);
|
super(AllContainers.SchematicTable.type, id);
|
||||||
|
this.player = inv.player;
|
||||||
this.te = te;
|
this.te = te;
|
||||||
|
|
||||||
inputSlot = new Slot(tableInventory, 0, 31, 15) {
|
inputSlot = new Slot(tableInventory, 0, 31, 15) {
|
||||||
|
@ -51,6 +64,10 @@ public class SchematicTableContainer extends Container {
|
||||||
|
|
||||||
updateContent();
|
updateContent();
|
||||||
|
|
||||||
|
if (te != null) {
|
||||||
|
this.addListener(te);
|
||||||
|
}
|
||||||
|
|
||||||
// player Slots
|
// player Slots
|
||||||
tableInventory.openInventory(inv.player);
|
tableInventory.openInventory(inv.player);
|
||||||
for (int l = 0; l < 3; ++l) {
|
for (int l = 0; l < 3; ++l) {
|
||||||
|
@ -64,6 +81,12 @@ public class SchematicTableContainer extends Container {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void detectAndSendChanges() {
|
||||||
|
super.detectAndSendChanges();
|
||||||
|
sendSchematicInfo();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean canWrite() {
|
public boolean canWrite() {
|
||||||
return inputSlot.getHasStack() && !outputSlot.getHasStack();
|
return inputSlot.getHasStack() && !outputSlot.getHasStack();
|
||||||
}
|
}
|
||||||
|
@ -103,9 +126,36 @@ public class SchematicTableContainer extends Container {
|
||||||
if (te != null) {
|
if (te != null) {
|
||||||
inputSlot.putStack(te.inputStack);
|
inputSlot.putStack(te.inputStack);
|
||||||
outputSlot.putStack(te.outputStack);
|
outputSlot.putStack(te.outputStack);
|
||||||
|
schematicUploading = te.uploadingSchematic;
|
||||||
|
progress = te.uploadingProgress;
|
||||||
|
sendSchematicUpdate = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendSchematicInfo() {
|
||||||
|
if (player instanceof ServerPlayerEntity) {
|
||||||
|
if (sendSchematicUpdate) {
|
||||||
|
Packets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player),
|
||||||
|
new PacketSchematicTableContainer(schematicUploading, progress));
|
||||||
|
sendSchematicUpdate = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void receiveSchematicInfo(String schematic, float progress) {
|
||||||
|
if (schematic.isEmpty()) {
|
||||||
|
this.schematicUploading = null;
|
||||||
|
this.isUploading = false;
|
||||||
|
this.progress = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isUploading = true;
|
||||||
|
this.schematicUploading = schematic;
|
||||||
|
this.progress = .5f;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContainerClosed(PlayerEntity playerIn) {
|
public void onContainerClosed(PlayerEntity playerIn) {
|
||||||
if (te != null) {
|
if (te != null) {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
import net.minecraft.inventory.ItemStackHelper;
|
import net.minecraft.inventory.ItemStackHelper;
|
||||||
import net.minecraft.inventory.container.Container;
|
import net.minecraft.inventory.container.Container;
|
||||||
|
import net.minecraft.inventory.container.IContainerListener;
|
||||||
import net.minecraft.inventory.container.INamedContainerProvider;
|
import net.minecraft.inventory.container.INamedContainerProvider;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
@ -16,11 +17,14 @@ import net.minecraft.util.NonNullList;
|
||||||
import net.minecraft.util.text.ITextComponent;
|
import net.minecraft.util.text.ITextComponent;
|
||||||
import net.minecraft.util.text.StringTextComponent;
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
|
|
||||||
public class SchematicTableTileEntity extends TileEntitySynced implements ITickableTileEntity, INamedContainerProvider {
|
public class SchematicTableTileEntity extends TileEntitySynced implements ITickableTileEntity, INamedContainerProvider, IContainerListener {
|
||||||
|
|
||||||
public ItemStack inputStack;
|
public ItemStack inputStack;
|
||||||
public ItemStack outputStack;
|
public ItemStack outputStack;
|
||||||
|
|
||||||
|
public String uploadingSchematic;
|
||||||
|
public float uploadingProgress;
|
||||||
|
|
||||||
public SchematicTableTileEntity() {
|
public SchematicTableTileEntity() {
|
||||||
this(AllTileEntities.SchematicTable.type);
|
this(AllTileEntities.SchematicTable.type);
|
||||||
}
|
}
|
||||||
|
@ -70,4 +74,24 @@ public class SchematicTableTileEntity extends TileEntitySynced implements ITicka
|
||||||
return new StringTextComponent(getType().getRegistryName().toString());
|
return new StringTextComponent(getType().getRegistryName().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendAllContents(Container containerToSend, NonNullList<ItemStack> itemsList) {
|
||||||
|
inputStack = itemsList.get(0);
|
||||||
|
outputStack = itemsList.get(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendSlotContents(Container containerToSend, int slotInd, ItemStack stack) {
|
||||||
|
if (slotInd == 0) {
|
||||||
|
inputStack = stack;
|
||||||
|
}
|
||||||
|
if (slotInd == 1) {
|
||||||
|
outputStack = stack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendWindowProperty(Container containerIn, int varToUpdate, int newValue) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,12 @@ package com.simibubi.create.block;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.BlockRayTraceResult;
|
|
||||||
import net.minecraft.util.text.StringTextComponent;
|
|
||||||
import net.minecraft.world.IBlockReader;
|
import net.minecraft.world.IBlockReader;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.IWorld;
|
||||||
|
import net.minecraft.world.IWorldReader;
|
||||||
|
|
||||||
public class SchematicannonBlock extends Block {
|
public class SchematicannonBlock extends Block {
|
||||||
|
|
||||||
|
@ -29,17 +27,16 @@ public class SchematicannonBlock extends Block {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
|
public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn,
|
||||||
BlockRayTraceResult hit) {
|
BlockPos currentPos, BlockPos facingPos) {
|
||||||
TileEntity tileEntity = worldIn.getTileEntity(pos);
|
((SchematicannonTileEntity) worldIn.getTileEntity(currentPos)).findInventories();
|
||||||
if (worldIn.isRemote)
|
return stateIn;
|
||||||
return true;
|
}
|
||||||
|
|
||||||
if (tileEntity == null)
|
@Override
|
||||||
return false;
|
public void onNeighborChange(BlockState state, IWorldReader world, BlockPos pos, BlockPos neighbor) {
|
||||||
|
((SchematicannonTileEntity) world.getTileEntity(pos)).findInventories();
|
||||||
player.sendMessage(new StringTextComponent("" + ((SchematicannonTileEntity) tileEntity).getTest()));
|
super.onNeighborChange(state, world, pos, neighbor);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +1,155 @@
|
||||||
package com.simibubi.create.block;
|
package com.simibubi.create.block;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
|
import com.simibubi.create.ServerSchematicLoader;
|
||||||
|
import com.simibubi.create.schematic.Cuboid;
|
||||||
|
import com.simibubi.create.schematic.SchematicWorld;
|
||||||
import com.simibubi.create.utility.TileEntitySynced;
|
import com.simibubi.create.utility.TileEntitySynced;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.item.BlockItem;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.CompressedStreamTools;
|
||||||
import net.minecraft.tileentity.ITickableTileEntity;
|
import net.minecraft.tileentity.ITickableTileEntity;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.tileentity.TileEntityType;
|
import net.minecraft.tileentity.TileEntityType;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.gen.feature.template.PlacementSettings;
|
||||||
|
import net.minecraft.world.gen.feature.template.Template;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
import net.minecraftforge.items.CapabilityItemHandler;
|
||||||
|
import net.minecraftforge.items.IItemHandler;
|
||||||
|
|
||||||
public class SchematicannonTileEntity extends TileEntitySynced implements ITickableTileEntity {
|
public class SchematicannonTileEntity extends TileEntitySynced implements ITickableTileEntity {
|
||||||
|
|
||||||
private int test = 0;
|
public static final int PLACEMENT_DELAY = 2;
|
||||||
|
|
||||||
|
private SchematicWorld reader;
|
||||||
|
private BlockPos currentPos;
|
||||||
|
public BlockPos anchor;
|
||||||
|
public String schematicToPrint;
|
||||||
|
public boolean missingBlock;
|
||||||
|
|
||||||
|
public List<IItemHandler> attachedInventories;
|
||||||
|
|
||||||
|
private int cooldown;
|
||||||
|
|
||||||
public SchematicannonTileEntity() {
|
public SchematicannonTileEntity() {
|
||||||
super(AllTileEntities.Schematicannon.type);
|
this(AllTileEntities.Schematicannon.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SchematicannonTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
public SchematicannonTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
||||||
super(tileEntityTypeIn);
|
super(tileEntityTypeIn);
|
||||||
|
attachedInventories = new LinkedList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void findInventories() {
|
||||||
|
for (Direction facing : Direction.values()) {
|
||||||
|
TileEntity tileEntity = world.getTileEntity(pos.offset(facing));
|
||||||
|
if (tileEntity != null) {
|
||||||
|
LazyOptional<IItemHandler> capability = tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite());
|
||||||
|
if (capability.isPresent()) {
|
||||||
|
attachedInventories.add(capability.orElse(null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(CompoundNBT compound) {
|
public void read(CompoundNBT compound) {
|
||||||
super.read(compound);
|
super.read(compound);
|
||||||
test = compound.getInt("Test");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundNBT write(CompoundNBT compound) {
|
public CompoundNBT write(CompoundNBT compound) {
|
||||||
compound.putInt("Test", test);
|
|
||||||
return super.write(compound);
|
return super.write(compound);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTest() {
|
|
||||||
return test;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTest(int test) {
|
|
||||||
this.test = test;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
test++;
|
if (world.isRemote)
|
||||||
|
return;
|
||||||
|
if (schematicToPrint == null)
|
||||||
|
return;
|
||||||
|
if (cooldown-- > 0)
|
||||||
|
return;
|
||||||
|
cooldown = PLACEMENT_DELAY;
|
||||||
|
|
||||||
|
if (reader == null) {
|
||||||
|
currentPos = BlockPos.ZERO;
|
||||||
|
currentPos = currentPos.offset(Direction.WEST);
|
||||||
|
|
||||||
|
String filepath = ServerSchematicLoader.PATH + "/" + schematicToPrint;
|
||||||
|
Template activeTemplate = new Template();
|
||||||
|
|
||||||
|
InputStream stream = null;
|
||||||
|
try {
|
||||||
|
stream = Files.newInputStream(Paths.get(filepath), StandardOpenOption.READ);
|
||||||
|
CompoundNBT nbt = CompressedStreamTools.readCompressed(stream);
|
||||||
|
activeTemplate.read(nbt);
|
||||||
|
reader = new SchematicWorld(new HashMap<>(), new Cuboid(BlockPos.ZERO, 0, 0, 0), anchor);
|
||||||
|
activeTemplate.addBlocksToWorld(reader, anchor, new PlacementSettings());
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (stream != null)
|
||||||
|
IOUtils.closeQuietly(stream);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockPos size = reader.getBounds().getSize();
|
||||||
|
BlockState state;
|
||||||
|
do {
|
||||||
|
if (!missingBlock)
|
||||||
|
currentPos = currentPos.offset(Direction.EAST);
|
||||||
|
if (currentPos.getX() > size.getX()) {
|
||||||
|
currentPos = new BlockPos(0, currentPos.getY(), currentPos.getZ() + 1);
|
||||||
|
}
|
||||||
|
if (currentPos.getZ() > size.getZ()) {
|
||||||
|
currentPos = new BlockPos(currentPos.getX(), currentPos.getY() + 1, 0);
|
||||||
|
}
|
||||||
|
if (currentPos.getY() > size.getY()) {
|
||||||
|
schematicToPrint = null;
|
||||||
|
currentPos = null;
|
||||||
|
anchor = null;
|
||||||
|
reader = null;
|
||||||
|
missingBlock = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state = reader.getBlockState(anchor.add(currentPos));
|
||||||
|
} while (state.getBlock() == Blocks.AIR);
|
||||||
|
|
||||||
|
missingBlock = true;
|
||||||
|
ItemStack requiredItem = new ItemStack(BlockItem.BLOCK_TO_ITEM.getOrDefault(state.getBlock(), Items.AIR));
|
||||||
|
for (IItemHandler iItemHandler : attachedInventories) {
|
||||||
|
for (int slot = 0; slot < iItemHandler.getSlots(); slot++) {
|
||||||
|
ItemStack stackInSlot = iItemHandler.getStackInSlot(slot);
|
||||||
|
if (!stackInSlot.isItemEqual(requiredItem))
|
||||||
|
continue;
|
||||||
|
iItemHandler.extractItem(slot, 1, false);
|
||||||
|
world.setBlockState(currentPos.add(anchor), state);
|
||||||
|
missingBlock = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,6 @@ public class SchematicTableScreen extends ContainerScreen<SchematicTableContaine
|
||||||
private SimiButton button;
|
private SimiButton button;
|
||||||
private DynamicLabel label;
|
private DynamicLabel label;
|
||||||
|
|
||||||
private boolean isUploading;
|
|
||||||
private String uploadingSchematic;
|
|
||||||
private float progress;
|
private float progress;
|
||||||
private float lastProgress;
|
private float lastProgress;
|
||||||
|
|
||||||
|
@ -75,7 +73,10 @@ public class SchematicTableScreen extends ContainerScreen<SchematicTableContaine
|
||||||
GuiResources.SCHEMATIC_TABLE.draw(this, xMainWindow, yMainWindow);
|
GuiResources.SCHEMATIC_TABLE.draw(this, xMainWindow, yMainWindow);
|
||||||
GuiResources.PLAYER_INVENTORY.draw(this, x, y + 20);
|
GuiResources.PLAYER_INVENTORY.draw(this, x, y + 20);
|
||||||
|
|
||||||
font.drawString("Choose a Schematic", xMainWindow + 50, yMainWindow + 10, GuiResources.FONT_COLOR);
|
if (container.isUploading)
|
||||||
|
font.drawString("Uploading...", xMainWindow + 76, yMainWindow + 10, GuiResources.FONT_COLOR);
|
||||||
|
else
|
||||||
|
font.drawString("Choose a Schematic", xMainWindow + 50, yMainWindow + 10, GuiResources.FONT_COLOR);
|
||||||
font.drawString("Inventory", x + 7, y + 26, 0x666666);
|
font.drawString("Inventory", x + 7, y + 26, 0x666666);
|
||||||
|
|
||||||
if (schematics == null) {
|
if (schematics == null) {
|
||||||
|
@ -111,9 +112,17 @@ public class SchematicTableScreen extends ContainerScreen<SchematicTableContaine
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
if (isUploading) {
|
if (container.isUploading) {
|
||||||
lastProgress = progress;
|
lastProgress = progress;
|
||||||
progress = Create.cSchematicLoader.getProgress(uploadingSchematic);
|
progress = Create.cSchematicLoader.getProgress(container.schematicUploading);
|
||||||
|
label.colored(0xCCDDFF);
|
||||||
|
button.active = false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
progress = 0;
|
||||||
|
lastProgress = 0;
|
||||||
|
label.colored(0xFFFFFF);
|
||||||
|
button.active = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,9 +135,8 @@ public class SchematicTableScreen extends ContainerScreen<SchematicTableContaine
|
||||||
|
|
||||||
List<String> availableSchematics = Create.cSchematicLoader.getAvailableSchematics();
|
List<String> availableSchematics = Create.cSchematicLoader.getAvailableSchematics();
|
||||||
lastProgress = progress = 0;
|
lastProgress = progress = 0;
|
||||||
uploadingSchematic = availableSchematics.get(schematics.getState());
|
String schematic = availableSchematics.get(schematics.getState());
|
||||||
isUploading = true;
|
Create.cSchematicLoader.startNewUpload(schematic);
|
||||||
Create.cSchematicLoader.startNewUpload(uploadingSchematic);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.mouseClicked(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_);
|
return super.mouseClicked(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_);
|
||||||
|
|
102
src/main/java/com/simibubi/create/item/ItemBlueprint.java
Normal file
102
src/main/java/com/simibubi/create/item/ItemBlueprint.java
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
package com.simibubi.create.item;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.block.SchematicannonTileEntity;
|
||||||
|
import com.simibubi.create.schematic.SchematicHologram;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.inventory.EquipmentSlotType;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.ItemUseContext;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.CompressedStreamTools;
|
||||||
|
import net.minecraft.nbt.NBTUtil;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
import net.minecraft.util.ActionResultType;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.gen.feature.template.Template;
|
||||||
|
|
||||||
|
public class ItemBlueprint extends Item {
|
||||||
|
|
||||||
|
public ItemBlueprint(Properties properties) {
|
||||||
|
super(properties.maxStackSize(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionResultType onItemUse(ItemUseContext context) {
|
||||||
|
|
||||||
|
World world = context.getWorld();
|
||||||
|
|
||||||
|
CompoundNBT tag = context.getItem().getTag();
|
||||||
|
if (tag.contains("File")) {
|
||||||
|
|
||||||
|
BlockPos pos = context.getPos();
|
||||||
|
BlockState blockState = world.getBlockState(pos);
|
||||||
|
if (AllBlocks.SCHEMATICANNON.typeOf(blockState)) {
|
||||||
|
if (world.isRemote) {
|
||||||
|
SchematicHologram.reset();
|
||||||
|
return ActionResultType.SUCCESS;
|
||||||
|
}
|
||||||
|
if (!tag.contains("Anchor"))
|
||||||
|
return ActionResultType.FAIL;
|
||||||
|
|
||||||
|
SchematicannonTileEntity te = (SchematicannonTileEntity) world.getTileEntity(pos);
|
||||||
|
te.schematicToPrint = tag.getString("Owner") + "/" + tag.getString("File");
|
||||||
|
te.anchor = NBTUtil.readBlockPos(tag.getCompound("Anchor"));
|
||||||
|
context.getPlayer().setItemStackToSlot(EquipmentSlotType.MAINHAND, ItemStack.EMPTY);
|
||||||
|
return ActionResultType.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag.put("Anchor", NBTUtil.writeBlockPos(pos.offset(context.getFace())));
|
||||||
|
|
||||||
|
if (!world.isRemote) {
|
||||||
|
return ActionResultType.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(context.getPlayer().getName().getFormattedText().equals(tag.getString("Owner")))) {
|
||||||
|
context.getPlayer()
|
||||||
|
.sendStatusMessage(new StringTextComponent("You are not the Owner of this Schematic."), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
String filepath = "schematics/" + tag.getString("File");
|
||||||
|
Template t = new Template();
|
||||||
|
|
||||||
|
InputStream stream = null;
|
||||||
|
try {
|
||||||
|
stream = Files.newInputStream(Paths.get(filepath), StandardOpenOption.READ);
|
||||||
|
CompoundNBT nbt = CompressedStreamTools.readCompressed(stream);
|
||||||
|
t.read(nbt);
|
||||||
|
new SchematicHologram().startHologram(t, pos.offset(context.getFace()));
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (stream != null)
|
||||||
|
IOUtils.closeQuietly(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
context.getPlayer().getCooldownTracker().setCooldown(this, 10);
|
||||||
|
return ActionResultType.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {
|
||||||
|
return super.onItemRightClick(worldIn, playerIn, handIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.simibubi.create.networking;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.simibubi.create.block.SchematicTableContainer;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.inventory.container.Container;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import net.minecraftforge.fml.network.NetworkEvent.Context;
|
||||||
|
|
||||||
|
public class PacketSchematicTableContainer {
|
||||||
|
|
||||||
|
public String schematic;
|
||||||
|
public float progress;
|
||||||
|
|
||||||
|
public PacketSchematicTableContainer(String schematicToUpload, float progress) {
|
||||||
|
this.schematic = schematicToUpload;
|
||||||
|
if (this.schematic == null)
|
||||||
|
this.schematic = "";
|
||||||
|
this.progress = progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketSchematicTableContainer(PacketBuffer buffer) {
|
||||||
|
this.schematic = buffer.readString();
|
||||||
|
this.progress = buffer.readFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toBytes(PacketBuffer buffer) {
|
||||||
|
buffer.writeString(schematic);
|
||||||
|
buffer.writeFloat(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void handle(Supplier<Context> context) {
|
||||||
|
context.get().enqueueWork(() -> {
|
||||||
|
Container c = Minecraft.getInstance().player.openContainer;
|
||||||
|
if (c != null && c instanceof SchematicTableContainer) {
|
||||||
|
((SchematicTableContainer) c).receiveSchematicInfo(schematic, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,12 +17,13 @@ public class Packets {
|
||||||
public static void registerPackets() {
|
public static void registerPackets() {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
channel.registerMessage(i++, PacketNbt.class, PacketNbt::toBytes, PacketNbt::new,
|
channel.registerMessage(i++, PacketNbt.class, PacketNbt::toBytes, PacketNbt::new, PacketNbt::handle);
|
||||||
PacketNbt::handle);
|
channel.registerMessage(i++, PacketSchematicTableContainer.class, PacketSchematicTableContainer::toBytes,
|
||||||
channel.registerMessage(i++, PacketSchematicUpload.class, PacketSchematicUpload::toBytes, PacketSchematicUpload::new,
|
PacketSchematicTableContainer::new, PacketSchematicTableContainer::handle);
|
||||||
PacketSchematicUpload::handle);
|
channel.registerMessage(i++, PacketSchematicUpload.class, PacketSchematicUpload::toBytes,
|
||||||
channel.registerMessage(i++, PacketSymmetryEffect.class, PacketSymmetryEffect::toBytes, PacketSymmetryEffect::new,
|
PacketSchematicUpload::new, PacketSchematicUpload::handle);
|
||||||
PacketSymmetryEffect::handle);
|
channel.registerMessage(i++, PacketSymmetryEffect.class, PacketSymmetryEffect::toBytes,
|
||||||
|
PacketSymmetryEffect::new, PacketSymmetryEffect::handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
71
src/main/java/com/simibubi/create/schematic/Cuboid.java
Normal file
71
src/main/java/com/simibubi/create/schematic/Cuboid.java
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
package com.simibubi.create.schematic;
|
||||||
|
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
|
public class Cuboid {
|
||||||
|
|
||||||
|
public int x;
|
||||||
|
public int y;
|
||||||
|
public int z;
|
||||||
|
public int width;
|
||||||
|
public int height;
|
||||||
|
public int length;
|
||||||
|
|
||||||
|
public Cuboid(BlockPos origin, BlockPos size) {
|
||||||
|
this(origin, size.getX(), size.getY(), size.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cuboid(BlockPos origin, int width, int height, int length) {
|
||||||
|
this.x = origin.getX() + ((width < 0) ? width : 0);
|
||||||
|
this.y = origin.getY() + ((height < 0) ? height : 0);
|
||||||
|
this.z = origin.getZ() + ((length < 0) ? length : 0);
|
||||||
|
this.width = Math.abs(width);
|
||||||
|
this.height = Math.abs(height);
|
||||||
|
this.length = Math.abs(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockPos getOrigin() {
|
||||||
|
return new BlockPos(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockPos getSize() {
|
||||||
|
return new BlockPos(width, height, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cuboid clone() {
|
||||||
|
return new Cuboid(new BlockPos(x, y, z), width, height, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void move(int x, int y, int z) {
|
||||||
|
this.x += x;
|
||||||
|
this.y += y;
|
||||||
|
this.z += z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void centerHorizontallyOn(BlockPos pos) {
|
||||||
|
x = pos.getX() - (width / 2);
|
||||||
|
y = pos.getY();
|
||||||
|
z = pos.getZ() - (length / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean intersects(Cuboid other) {
|
||||||
|
return !(other.x >= x + width || other.z >= z + length || other.x + other.width <= x
|
||||||
|
|| other.z + other.length <= z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(BlockPos pos) {
|
||||||
|
return (pos.getX() >= x && pos.getX() < x + width) && (pos.getY() >= y && pos.getY() < y + height)
|
||||||
|
&& (pos.getZ() >= z && pos.getZ() < z + length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockPos getCenter() {
|
||||||
|
return getOrigin().add(width / 2, height / 2, length / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
return obj instanceof Cuboid && ((Cuboid) obj).getOrigin().equals(getOrigin())
|
||||||
|
&& ((Cuboid) obj).getSize().equals(getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,210 @@
|
||||||
|
package com.simibubi.create.schematic;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||||
|
import net.minecraft.client.renderer.BlockRendererDispatcher;
|
||||||
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
|
import net.minecraft.client.renderer.RegionRenderCacheBuilder;
|
||||||
|
import net.minecraft.client.renderer.texture.AtlasTexture;
|
||||||
|
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.renderer.vertex.VertexFormatElement.Usage;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.util.BlockRenderLayer;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.gen.feature.template.PlacementSettings;
|
||||||
|
import net.minecraft.world.gen.feature.template.Template;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.client.ForgeHooksClient;
|
||||||
|
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||||
|
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||||
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||||
|
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||||
|
import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent;
|
||||||
|
|
||||||
|
@EventBusSubscriber(Dist.CLIENT)
|
||||||
|
public class SchematicHologram {
|
||||||
|
|
||||||
|
// These buffers are large enough for an entire chunk, consider using
|
||||||
|
// smaller buffers
|
||||||
|
private static final RegionRenderCacheBuilder bufferCache = new RegionRenderCacheBuilder();
|
||||||
|
private static final boolean[] usedBlockRenderLayers = new boolean[BlockRenderLayer.values().length];
|
||||||
|
private static final boolean[] startedBufferBuilders = new boolean[BlockRenderLayer.values().length];
|
||||||
|
|
||||||
|
private static SchematicHologram instance;
|
||||||
|
private boolean active;
|
||||||
|
private boolean changed;
|
||||||
|
private SchematicWorld schematic;
|
||||||
|
private BlockPos anchor;
|
||||||
|
|
||||||
|
public SchematicHologram() {
|
||||||
|
instance = this;
|
||||||
|
changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startHologram(Template schematic, BlockPos anchor) {
|
||||||
|
this.schematic = new SchematicWorld(new HashMap<>(), new Cuboid(BlockPos.ZERO, BlockPos.ZERO), anchor);
|
||||||
|
this.anchor = anchor;
|
||||||
|
schematic.addBlocksToWorld(this.schematic, anchor, new PlacementSettings());
|
||||||
|
active = true;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SchematicHologram getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static void display(Schematic schematic) {
|
||||||
|
// instance = new SchematicHologram();
|
||||||
|
// instance.startHologram(schematic);
|
||||||
|
// }
|
||||||
|
|
||||||
|
public static void reset() {
|
||||||
|
instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void schematicChanged() {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onClientTickEvent(final ClientTickEvent event) {
|
||||||
|
if (instance != null && instance.active) {
|
||||||
|
final Minecraft minecraft = Minecraft.getInstance();
|
||||||
|
if (event.phase != TickEvent.Phase.END)
|
||||||
|
return;
|
||||||
|
if (minecraft.world == null)
|
||||||
|
return;
|
||||||
|
if (minecraft.player == null)
|
||||||
|
return;
|
||||||
|
if (instance.changed) {
|
||||||
|
redraw(minecraft);
|
||||||
|
instance.changed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void redraw(final Minecraft minecraft) {
|
||||||
|
Arrays.fill(usedBlockRenderLayers, false);
|
||||||
|
Arrays.fill(startedBufferBuilders, false);
|
||||||
|
|
||||||
|
final SchematicWorld blockAccess = instance.schematic;
|
||||||
|
final BlockRendererDispatcher blockRendererDispatcher = minecraft.getBlockRendererDispatcher();
|
||||||
|
|
||||||
|
List<BlockState> blockstates = new LinkedList<>();
|
||||||
|
|
||||||
|
for (BlockPos localPos : BlockPos.getAllInBoxMutable(blockAccess.getBounds().getOrigin(),
|
||||||
|
blockAccess.getBounds().getOrigin().add(blockAccess.getBounds().getSize()))) {
|
||||||
|
BlockPos pos = localPos.add(instance.anchor);
|
||||||
|
final BlockState state = blockAccess.getBlockState(pos);
|
||||||
|
for (BlockRenderLayer blockRenderLayer : BlockRenderLayer.values()) {
|
||||||
|
if (!state.getBlock().canRenderInLayer(state, blockRenderLayer)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ForgeHooksClient.setRenderLayer(blockRenderLayer);
|
||||||
|
final int blockRenderLayerId = blockRenderLayer.ordinal();
|
||||||
|
final BufferBuilder bufferBuilder = bufferCache.getBuilder(blockRenderLayerId);
|
||||||
|
if (!startedBufferBuilders[blockRenderLayerId]) {
|
||||||
|
startedBufferBuilders[blockRenderLayerId] = true;
|
||||||
|
// Copied from RenderChunk
|
||||||
|
{
|
||||||
|
bufferBuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// OptiFine Shaders compatibility
|
||||||
|
// if (Config.isShaders()) SVertexBuilder.pushEntity(state, pos,
|
||||||
|
// blockAccess, bufferBuilder);
|
||||||
|
usedBlockRenderLayers[blockRenderLayerId] |= blockRendererDispatcher.renderBlock(state, pos,
|
||||||
|
blockAccess, bufferBuilder, minecraft.world.rand, EmptyModelData.INSTANCE);
|
||||||
|
blockstates.add(state);
|
||||||
|
// if (Config.isShaders())
|
||||||
|
// SVertexBuilder.popEntity(bufferBuilder);
|
||||||
|
}
|
||||||
|
ForgeHooksClient.setRenderLayer(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// finishDrawing
|
||||||
|
for (int blockRenderLayerId = 0; blockRenderLayerId < usedBlockRenderLayers.length; blockRenderLayerId++) {
|
||||||
|
if (!startedBufferBuilders[blockRenderLayerId]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bufferCache.getBuilder(blockRenderLayerId).finishDrawing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onRenderWorldLastEvent(final RenderWorldLastEvent event) {
|
||||||
|
if (instance != null && instance.active) {
|
||||||
|
final Entity entity = Minecraft.getInstance().getRenderViewEntity();
|
||||||
|
|
||||||
|
if (entity == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveRenderInfo renderInfo = Minecraft.getInstance().gameRenderer.getActiveRenderInfo();
|
||||||
|
Vec3d view = renderInfo.getProjectedView();
|
||||||
|
double renderPosX = view.x;
|
||||||
|
double renderPosY = view.y;
|
||||||
|
double renderPosZ = view.z;
|
||||||
|
|
||||||
|
GlStateManager.enableAlphaTest();
|
||||||
|
GlStateManager.enableBlend();
|
||||||
|
Minecraft.getInstance().getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
|
||||||
|
|
||||||
|
for (int blockRenderLayerId = 0; blockRenderLayerId < usedBlockRenderLayers.length; blockRenderLayerId++) {
|
||||||
|
if (!usedBlockRenderLayers[blockRenderLayerId]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final BufferBuilder bufferBuilder = bufferCache.getBuilder(blockRenderLayerId);
|
||||||
|
GlStateManager.pushMatrix();
|
||||||
|
GlStateManager.translated(-renderPosX, -renderPosY, -renderPosZ);
|
||||||
|
drawBuffer(bufferBuilder);
|
||||||
|
GlStateManager.popMatrix();
|
||||||
|
}
|
||||||
|
GlStateManager.disableAlphaTest();
|
||||||
|
GlStateManager.disableBlend();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Coppied from the Tesselator's vboUploader - Draw everything but don't
|
||||||
|
// reset the buffer
|
||||||
|
private static void drawBuffer(final BufferBuilder bufferBuilder) {
|
||||||
|
if (bufferBuilder.getVertexCount() > 0) {
|
||||||
|
|
||||||
|
VertexFormat vertexformat = bufferBuilder.getVertexFormat();
|
||||||
|
int size = vertexformat.getSize();
|
||||||
|
ByteBuffer bytebuffer = bufferBuilder.getByteBuffer();
|
||||||
|
List<VertexFormatElement> list = vertexformat.getElements();
|
||||||
|
|
||||||
|
for (int index = 0; index < list.size(); ++index) {
|
||||||
|
VertexFormatElement vertexformatelement = list.get(index);
|
||||||
|
Usage usage = vertexformatelement.getUsage();
|
||||||
|
bytebuffer.position(vertexformat.getOffset(index));
|
||||||
|
usage.preDraw(vertexformat, index, size, bytebuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
GlStateManager.drawArrays(bufferBuilder.getDrawMode(), 0, bufferBuilder.getVertexCount());
|
||||||
|
|
||||||
|
for (int index = 0; index < list.size(); ++index) {
|
||||||
|
VertexFormatElement vertexformatelement = list.get(index);
|
||||||
|
Usage usage = vertexformatelement.getUsage();
|
||||||
|
usage.postDraw(vertexformat, index, size, bytebuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
282
src/main/java/com/simibubi/create/schematic/SchematicWorld.java
Normal file
282
src/main/java/com/simibubi/create/schematic/SchematicWorld.java
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
package com.simibubi.create.schematic;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.fluid.Fluid;
|
||||||
|
import net.minecraft.fluid.FluidState;
|
||||||
|
import net.minecraft.fluid.Fluids;
|
||||||
|
import net.minecraft.fluid.IFluidState;
|
||||||
|
import net.minecraft.particles.IParticleData;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.util.SoundCategory;
|
||||||
|
import net.minecraft.util.SoundEvent;
|
||||||
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.DifficultyInstance;
|
||||||
|
import net.minecraft.world.EmptyTickList;
|
||||||
|
import net.minecraft.world.ITickList;
|
||||||
|
import net.minecraft.world.IWorld;
|
||||||
|
import net.minecraft.world.LightType;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.biome.Biome;
|
||||||
|
import net.minecraft.world.biome.Biomes;
|
||||||
|
import net.minecraft.world.border.WorldBorder;
|
||||||
|
import net.minecraft.world.chunk.AbstractChunkProvider;
|
||||||
|
import net.minecraft.world.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.chunk.IChunk;
|
||||||
|
import net.minecraft.world.dimension.Dimension;
|
||||||
|
import net.minecraft.world.gen.Heightmap.Type;
|
||||||
|
import net.minecraft.world.storage.WorldInfo;
|
||||||
|
|
||||||
|
public class SchematicWorld implements IWorld {
|
||||||
|
|
||||||
|
private Map<BlockPos, BlockState> blocks;
|
||||||
|
private Cuboid bounds;
|
||||||
|
private BlockPos anchor;
|
||||||
|
|
||||||
|
public SchematicWorld(Map<BlockPos, BlockState> blocks, Cuboid bounds, BlockPos anchor) {
|
||||||
|
this.blocks = blocks;
|
||||||
|
this.setBounds(bounds);
|
||||||
|
this.anchor = anchor;
|
||||||
|
updateBlockstates();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateBlockstates() {
|
||||||
|
Set<BlockPos> keySet = new HashSet<>(blocks.keySet());
|
||||||
|
keySet.forEach(pos -> {
|
||||||
|
BlockState blockState = blocks.get(pos);
|
||||||
|
if (blockState == null)
|
||||||
|
return;
|
||||||
|
blockState.updateNeighbors(this, pos.add(anchor), 16);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<BlockPos> getAllPositions() {
|
||||||
|
return blocks.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TileEntity getTileEntity(BlockPos pos) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getBlockState(BlockPos globalPos) {
|
||||||
|
BlockPos pos = globalPos.subtract(anchor);
|
||||||
|
if (getBounds().contains(pos) && blocks.containsKey(pos)) {
|
||||||
|
return blocks.get(pos);
|
||||||
|
} else {
|
||||||
|
return Blocks.AIR.getDefaultState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<BlockPos, BlockState> getBlockMap() {
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IFluidState getFluidState(BlockPos pos) {
|
||||||
|
return new FluidState(Fluids.EMPTY, ImmutableMap.of());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Biome getBiome(BlockPos pos) {
|
||||||
|
return Biomes.THE_VOID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLightFor(LightType type, BlockPos pos) {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Entity> getEntitiesInAABBexcluding(Entity arg0, AxisAlignedBB arg1, Predicate<? super Entity> arg2) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends Entity> List<T> getEntitiesWithinAABB(Class<? extends T> arg0, AxisAlignedBB arg1,
|
||||||
|
Predicate<? super T> arg2) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends PlayerEntity> getPlayers() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLightSubtracted(BlockPos pos, int amount) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IChunk getChunk(int x, int z, ChunkStatus requiredStatus, boolean nonnull) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockPos getHeight(Type heightmapType, BlockPos pos) {
|
||||||
|
return BlockPos.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight(Type heightmapType, int x, int z) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSkylightSubtracted() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorldBorder getWorldBorder() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRemote() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSeaLevel() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension getDimension() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasBlockState(BlockPos pos, Predicate<BlockState> predicate) {
|
||||||
|
return predicate.test(getBlockState(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean destroyBlock(BlockPos arg0, boolean arg1) {
|
||||||
|
return setBlockState(arg0, Blocks.AIR.getDefaultState(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeBlock(BlockPos arg0, boolean arg1) {
|
||||||
|
return setBlockState(arg0, Blocks.AIR.getDefaultState(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setBlockState(BlockPos pos, BlockState arg1, int arg2) {
|
||||||
|
pos = pos.subtract(anchor);
|
||||||
|
if (pos.getX() < bounds.x) {
|
||||||
|
bounds.width += bounds.x - pos.getX();
|
||||||
|
bounds.x = pos.getX();
|
||||||
|
}
|
||||||
|
if (pos.getY() < bounds.y) {
|
||||||
|
bounds.height += bounds.y - pos.getY();
|
||||||
|
bounds.y = pos.getY();
|
||||||
|
}
|
||||||
|
if (pos.getZ() < bounds.z) {
|
||||||
|
bounds.length += bounds.z - pos.getZ();
|
||||||
|
bounds.z = pos.getZ();
|
||||||
|
}
|
||||||
|
BlockPos boundsMax = bounds.getOrigin().add(bounds.getSize());
|
||||||
|
if (boundsMax.getX() <= pos.getX()) {
|
||||||
|
bounds.width += pos.getX() - boundsMax.getX() + 1;
|
||||||
|
}
|
||||||
|
if (boundsMax.getY() <= pos.getY()) {
|
||||||
|
bounds.height += pos.getY() - boundsMax.getY() + 1;
|
||||||
|
}
|
||||||
|
if (boundsMax.getZ() <= pos.getZ()) {
|
||||||
|
bounds.length += pos.getZ() - boundsMax.getZ() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
blocks.put(pos, arg1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getSeed() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ITickList<Block> getPendingBlockTicks() {
|
||||||
|
return EmptyTickList.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ITickList<Fluid> getPendingFluidTicks() {
|
||||||
|
return EmptyTickList.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public World getWorld() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorldInfo getWorldInfo() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DifficultyInstance getDifficultyForLocation(BlockPos pos) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractChunkProvider getChunkProvider() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Random getRandom() {
|
||||||
|
return new Random();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyNeighbors(BlockPos pos, Block blockIn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockPos getSpawnPoint() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playSound(PlayerEntity player, BlockPos pos, SoundEvent soundIn, SoundCategory category, float volume,
|
||||||
|
float pitch) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addParticle(IParticleData particleData, double x, double y, double z, double xSpeed, double ySpeed,
|
||||||
|
double zSpeed) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playEvent(PlayerEntity player, int type, BlockPos pos, int data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cuboid getBounds() {
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBounds(Cuboid bounds) {
|
||||||
|
this.bounds = bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue