Schematics Mega Polish
- Schematicannon makes less obnoxious noises - Schematic Table Container and Gui Improved - Made New Additions Server Proof - Server side Schematic handler is less trusting - Added a Material Checklist for blueprints loaded in the schematicannon - Added more safety checks regarding Schematics & Chunkloading, Filesystem and Distance - Added new option for Schematicannon to not replace tileentities - Schematic upload progress is now handled on the server
This commit is contained in:
parent
8372a1eb43
commit
a34034379f
19 changed files with 772 additions and 402 deletions
|
@ -1,5 +1,7 @@
|
||||||
package com.simibubi.create;
|
package com.simibubi.create;
|
||||||
|
|
||||||
|
import static com.simibubi.create.ServerSchematicLoader.MAX_PACKET_SIZE;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
@ -19,6 +21,7 @@ import com.simibubi.create.networking.Packets;
|
||||||
import com.simibubi.create.utility.FilesHelper;
|
import com.simibubi.create.utility.FilesHelper;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
@ -26,39 +29,28 @@ import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
public class ClientSchematicLoader {
|
public class ClientSchematicLoader {
|
||||||
|
|
||||||
public static final int PACKET_DELAY = 10;
|
public static final int PACKET_DELAY = 10;
|
||||||
public static final int PACKET_SIZE = 2048;
|
|
||||||
|
|
||||||
private List<String> availableSchematics;
|
private List<String> availableSchematics;
|
||||||
private Map<String, InputStream> activeUploads;
|
private Map<String, InputStream> activeUploads;
|
||||||
private Map<String, ReadProgress> progress;
|
|
||||||
private int packetCycle;
|
private int packetCycle;
|
||||||
|
|
||||||
public ClientSchematicLoader() {
|
public ClientSchematicLoader() {
|
||||||
availableSchematics = new ArrayList<>();
|
availableSchematics = new ArrayList<>();
|
||||||
activeUploads = new HashMap<>();
|
activeUploads = new HashMap<>();
|
||||||
progress = new HashMap<>();
|
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tick() {
|
public void tick() {
|
||||||
if (activeUploads.isEmpty())
|
if (activeUploads.isEmpty())
|
||||||
return;
|
return;
|
||||||
if (packetCycle-- > 0)
|
if (packetCycle-- > 0)
|
||||||
return;
|
return;
|
||||||
packetCycle = PACKET_DELAY;
|
packetCycle = PACKET_DELAY;
|
||||||
|
|
||||||
for (String schematic : new HashSet<>(activeUploads.keySet())) {
|
for (String schematic : new HashSet<>(activeUploads.keySet())) {
|
||||||
continueUpload(schematic);
|
continueUpload(schematic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getProgress(String schematic) {
|
|
||||||
if (progress.containsKey(schematic)) {
|
|
||||||
return progress.get(schematic).getProgress();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startNewUpload(String schematic) {
|
public void startNewUpload(String schematic) {
|
||||||
Path path = Paths.get("schematics", schematic);
|
Path path = Paths.get("schematics", schematic);
|
||||||
|
@ -67,15 +59,24 @@ public class ClientSchematicLoader {
|
||||||
Create.logger.fatal("Missing Schematic file: " + path.toString());
|
Create.logger.fatal("Missing Schematic file: " + path.toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputStream in;
|
InputStream in;
|
||||||
try {
|
try {
|
||||||
|
long size = Files.size(path);
|
||||||
|
|
||||||
|
// Too big
|
||||||
|
if (size > ServerSchematicLoader.MAX_SCHEMATIC_FILE_SIZE) {
|
||||||
|
Minecraft.getInstance().player
|
||||||
|
.sendMessage(new StringTextComponent("Your schematic is too large (" + size / 1024 + " KB)."));
|
||||||
|
Minecraft.getInstance().player
|
||||||
|
.sendMessage(new StringTextComponent("The maximum allowed schematic file size is: "
|
||||||
|
+ ServerSchematicLoader.MAX_SCHEMATIC_FILE_SIZE / 1024 + " KB"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
in = Files.newInputStream(path, StandardOpenOption.READ);
|
in = Files.newInputStream(path, StandardOpenOption.READ);
|
||||||
activeUploads.put(schematic, in);
|
activeUploads.put(schematic, in);
|
||||||
ReadProgress tracker = new ReadProgress();
|
Packets.channel.sendToServer(PacketSchematicUpload.begin(schematic, size));
|
||||||
tracker.length = Files.size(path);
|
|
||||||
progress.put(schematic, tracker);
|
|
||||||
Packets.channel.sendToServer(PacketSchematicUpload.begin(schematic));
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -83,24 +84,21 @@ public class ClientSchematicLoader {
|
||||||
|
|
||||||
private void continueUpload(String schematic) {
|
private void continueUpload(String schematic) {
|
||||||
if (activeUploads.containsKey(schematic)) {
|
if (activeUploads.containsKey(schematic)) {
|
||||||
byte[] data = new byte[PACKET_SIZE];
|
byte[] data = new byte[MAX_PACKET_SIZE];
|
||||||
try {
|
try {
|
||||||
int status = activeUploads.get(schematic).read(data);
|
int status = activeUploads.get(schematic).read(data);
|
||||||
|
if (status < MAX_PACKET_SIZE) {
|
||||||
progress.get(schematic).progress += status;
|
|
||||||
|
|
||||||
if (status < PACKET_SIZE) {
|
|
||||||
data = Arrays.copyOf(data, status);
|
data = Arrays.copyOf(data, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Minecraft.getInstance().world != null)
|
if (Minecraft.getInstance().world != null)
|
||||||
Packets.channel.sendToServer(PacketSchematicUpload.write(schematic, data));
|
Packets.channel.sendToServer(PacketSchematicUpload.write(schematic, data));
|
||||||
else {
|
else {
|
||||||
activeUploads.remove(schematic);
|
activeUploads.remove(schematic);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status < PACKET_SIZE)
|
if (status < MAX_PACKET_SIZE)
|
||||||
finishUpload(schematic);
|
finishUpload(schematic);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -114,17 +112,17 @@ public class ClientSchematicLoader {
|
||||||
activeUploads.remove(schematic);
|
activeUploads.remove(schematic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
FilesHelper.createFolderIfMissing("schematics");
|
FilesHelper.createFolderIfMissing("schematics");
|
||||||
availableSchematics.clear();
|
availableSchematics.clear();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Files.list(Paths.get("schematics/"))
|
Files.list(Paths.get("schematics/"))
|
||||||
.forEach(path -> {
|
.filter(f -> !Files.isDirectory(f) && f.getFileName().toString().endsWith(".nbt")).forEach(path -> {
|
||||||
if (Files.isDirectory(path))
|
if (Files.isDirectory(path))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
availableSchematics.add(path.getFileName().toString());
|
availableSchematics.add(path.getFileName().toString());
|
||||||
});
|
});
|
||||||
} catch (NoSuchFileException e) {
|
} catch (NoSuchFileException e) {
|
||||||
|
@ -142,13 +140,5 @@ public class ClientSchematicLoader {
|
||||||
public Path getPath(String name) {
|
public Path getPath(String name) {
|
||||||
return Paths.get("schematics", name + ".nbt");
|
return Paths.get("schematics", name + ".nbt");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ReadProgress {
|
|
||||||
public long length;
|
|
||||||
public long progress;
|
|
||||||
public float getProgress() {
|
|
||||||
return (float) (progress * 1d / length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,10 @@ import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
|
||||||
import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent;
|
import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent;
|
||||||
|
import net.minecraftforge.fml.common.gameevent.TickEvent.ServerTickEvent;
|
||||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||||
|
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
|
||||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||||
|
|
||||||
@EventBusSubscriber(bus = Bus.FORGE)
|
@EventBusSubscriber(bus = Bus.FORGE)
|
||||||
|
@ -73,6 +75,16 @@ public class Create {
|
||||||
sSchematicLoader = new ServerSchematicLoader();
|
sSchematicLoader = new ServerSchematicLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onTick(ServerTickEvent event) {
|
||||||
|
sSchematicLoader.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onServerClose(FMLServerStoppingEvent event) {
|
||||||
|
sSchematicLoader.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onClientTick(ClientTickEvent event) {
|
public static void onClientTick(ClientTickEvent event) {
|
||||||
|
|
|
@ -3,12 +3,17 @@ package com.simibubi.create;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import com.simibubi.create.block.SchematicTableContainer;
|
|
||||||
import com.simibubi.create.block.SchematicTableTileEntity;
|
import com.simibubi.create.block.SchematicTableTileEntity;
|
||||||
import com.simibubi.create.item.ItemBlueprint;
|
import com.simibubi.create.item.ItemBlueprint;
|
||||||
import com.simibubi.create.networking.PacketSchematicUpload.DimensionPos;
|
import com.simibubi.create.networking.PacketSchematicUpload.DimensionPos;
|
||||||
|
@ -17,80 +22,196 @@ import com.simibubi.create.utility.FilesHelper;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
|
|
||||||
public class ServerSchematicLoader {
|
public class ServerSchematicLoader {
|
||||||
|
|
||||||
public static final String PATH = "schematics/uploaded";
|
public static final String PATH = "schematics/uploaded";
|
||||||
private Map<String, OutputStream> activeDownloads;
|
public static final int IDLE_TIMEOUT = 600;
|
||||||
private Map<String, DimensionPos> activeTables;
|
public static final int MAX_PACKET_SIZE = 1024;
|
||||||
|
public static final int MAX_SCHEMATICS_PER_PLAYER = 10;
|
||||||
|
public static final int MAX_SCHEMATIC_FILE_SIZE = 256 * 1024; // 256 kiB
|
||||||
|
|
||||||
|
private Map<String, SchematicUploadEntry> activeUploads;
|
||||||
|
|
||||||
|
public class SchematicUploadEntry {
|
||||||
|
public OutputStream stream;
|
||||||
|
public long bytesUploaded;
|
||||||
|
public long totalBytes;
|
||||||
|
public DimensionPos tablePos;
|
||||||
|
public int idleTime;
|
||||||
|
|
||||||
|
public SchematicUploadEntry(OutputStream stream, long totalBytes, DimensionPos tablePos) {
|
||||||
|
this.stream = stream;
|
||||||
|
this.totalBytes = totalBytes;
|
||||||
|
this.tablePos = tablePos;
|
||||||
|
this.bytesUploaded = 0;
|
||||||
|
this.idleTime = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ServerSchematicLoader() {
|
public ServerSchematicLoader() {
|
||||||
activeDownloads = new HashMap<>();
|
activeUploads = new HashMap<>();
|
||||||
activeTables = new HashMap<>();
|
|
||||||
FilesHelper.createFolderIfMissing("schematics");
|
FilesHelper.createFolderIfMissing("schematics");
|
||||||
FilesHelper.createFolderIfMissing(PATH);
|
FilesHelper.createFolderIfMissing(PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleNewUpload(ServerPlayerEntity player, String schematic, DimensionPos dimPos) {
|
public void tick() {
|
||||||
|
// Detect Timed out Uploads
|
||||||
|
Set<String> deadEntries = new HashSet<>();
|
||||||
|
for (String upload : activeUploads.keySet()) {
|
||||||
|
SchematicUploadEntry entry = activeUploads.get(upload);
|
||||||
|
|
||||||
|
if (entry.idleTime++ > IDLE_TIMEOUT) {
|
||||||
|
Create.logger.warn("Schematic Upload timed out: " + upload);
|
||||||
|
deadEntries.add(upload);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove Timed out Uploads
|
||||||
|
deadEntries.forEach(this::cancelUpload);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
// Close open streams
|
||||||
|
new HashSet<>(activeUploads.keySet()).forEach(this::cancelUpload);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleNewUpload(ServerPlayerEntity player, String schematic, long size, DimensionPos dimPos) {
|
||||||
String playerPath = PATH + "/" + player.getName().getFormattedText();
|
String playerPath = PATH + "/" + player.getName().getFormattedText();
|
||||||
String playerSchematicId = player.getName().getFormattedText() + "/" + schematic;
|
String playerSchematicId = player.getName().getFormattedText() + "/" + schematic;
|
||||||
|
|
||||||
FilesHelper.createFolderIfMissing(playerPath);
|
FilesHelper.createFolderIfMissing(playerPath);
|
||||||
|
|
||||||
if (activeDownloads.containsKey(playerSchematicId))
|
// Unsupported Format
|
||||||
|
if (!schematic.endsWith(".nbt")) {
|
||||||
|
Create.logger.warn("Attempted Schematic Upload with non-supported Format: " + playerSchematicId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Too big
|
||||||
|
if (size > MAX_SCHEMATIC_FILE_SIZE) {
|
||||||
|
player.sendMessage(new StringTextComponent("Your schematic is too large (" + size/1024 + " KB)."));
|
||||||
|
player.sendMessage(new StringTextComponent(
|
||||||
|
"The maximum allowed schematic file size is: " + MAX_SCHEMATIC_FILE_SIZE/1024 + " KB"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip existing Uploads
|
||||||
|
if (activeUploads.containsKey(playerSchematicId))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Validate Referenced Block
|
||||||
|
BlockState blockState = dimPos.world.getBlockState(dimPos.pos);
|
||||||
|
if (!AllBlocks.SCHEMATIC_TABLE.typeOf(blockState))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Delete schematic with same name
|
||||||
Files.deleteIfExists(Paths.get(PATH, playerSchematicId));
|
Files.deleteIfExists(Paths.get(PATH, playerSchematicId));
|
||||||
|
|
||||||
|
// Too many Schematics
|
||||||
|
Stream<Path> list = Files.list(Paths.get(playerPath));
|
||||||
|
if (list.count() >= MAX_SCHEMATICS_PER_PLAYER) {
|
||||||
|
Stream<Path> list2 = Files.list(Paths.get(playerPath));
|
||||||
|
Optional<Path> lastFilePath = list2.filter(f -> !Files.isDirectory(f))
|
||||||
|
.min(Comparator.comparingLong(f -> f.toFile().lastModified()));
|
||||||
|
list2.close();
|
||||||
|
if (lastFilePath.isPresent()) {
|
||||||
|
Files.deleteIfExists(lastFilePath.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list.close();
|
||||||
|
|
||||||
|
// Open Stream
|
||||||
OutputStream writer = Files.newOutputStream(Paths.get(PATH, playerSchematicId),
|
OutputStream writer = Files.newOutputStream(Paths.get(PATH, playerSchematicId),
|
||||||
StandardOpenOption.CREATE_NEW);
|
StandardOpenOption.CREATE_NEW);
|
||||||
Create.logger.info("Receiving New Schematic: " + playerSchematicId);
|
activeUploads.put(playerSchematicId, new SchematicUploadEntry(writer, size, dimPos));
|
||||||
activeDownloads.put(playerSchematicId, writer);
|
|
||||||
activeTables.put(playerSchematicId, dimPos);
|
|
||||||
|
|
||||||
SchematicTableTileEntity tileEntity = (SchematicTableTileEntity) dimPos.world
|
// Notify Tile Entity
|
||||||
.getTileEntity(dimPos.pos);
|
SchematicTableTileEntity tileEntity = (SchematicTableTileEntity) dimPos.world.getTileEntity(dimPos.pos);
|
||||||
tileEntity.uploadingSchematic = schematic;
|
tileEntity.startUpload(schematic);
|
||||||
tileEntity.uploadingProgress = 0;
|
|
||||||
BlockState blockState = dimPos.world.getBlockState(dimPos.pos);
|
|
||||||
dimPos.world.notifyBlockUpdate(dimPos.pos, blockState, blockState, 6);
|
|
||||||
|
|
||||||
if (player.openContainer instanceof SchematicTableContainer) {
|
|
||||||
SchematicTableContainer c = (SchematicTableContainer) player.openContainer;
|
|
||||||
c.sendSchematicUpdate = true;
|
|
||||||
c.detectAndSendChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
Create.logger.error("Exception Thrown when starting Upload: " + playerSchematicId);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (activeUploads.containsKey(playerSchematicId)) {
|
||||||
|
SchematicUploadEntry entry = activeUploads.get(playerSchematicId);
|
||||||
|
entry.bytesUploaded += data.length;
|
||||||
|
|
||||||
|
// Size Validations
|
||||||
|
if (data.length > MAX_PACKET_SIZE) {
|
||||||
|
Create.logger.warn("Oversized Upload Packet received: " + playerSchematicId);
|
||||||
|
cancelUpload(playerSchematicId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.bytesUploaded > entry.totalBytes) {
|
||||||
|
Create.logger.warn("Received more data than Expected: " + playerSchematicId);
|
||||||
|
cancelUpload(playerSchematicId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
activeDownloads.get(playerSchematicId).write(data);
|
entry.stream.write(data);
|
||||||
Create.logger.info("Writing to Schematic: " + playerSchematicId);
|
entry.idleTime = 0;
|
||||||
|
BlockState blockState = entry.tablePos.world.getBlockState(entry.tablePos.pos);
|
||||||
|
if (!AllBlocks.SCHEMATIC_TABLE.typeOf(blockState))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SchematicTableTileEntity tileEntity = (SchematicTableTileEntity) entry.tablePos.world
|
||||||
|
.getTileEntity(entry.tablePos.pos);
|
||||||
|
tileEntity.uploadingProgress = (float) ((double) entry.bytesUploaded / entry.totalBytes);
|
||||||
|
tileEntity.sendUpdate = true;
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
Create.logger.error("Exception Thrown when uploading Schematic: " + playerSchematicId);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
activeDownloads.remove(playerSchematicId);
|
cancelUpload(playerSchematicId);
|
||||||
activeTables.remove(playerSchematicId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void cancelUpload(String playerSchematicId) {
|
||||||
|
if (!activeUploads.containsKey(playerSchematicId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SchematicUploadEntry entry = activeUploads.remove(playerSchematicId);
|
||||||
|
try {
|
||||||
|
entry.stream.close();
|
||||||
|
Files.deleteIfExists(Paths.get(PATH, playerSchematicId));
|
||||||
|
Create.logger.warn("Cancelled Schematic Upload: " + playerSchematicId);
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
Create.logger.error("Exception Thrown when cancelling Upload: " + playerSchematicId);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
DimensionPos dimpos = entry.tablePos;
|
||||||
|
if (dimpos == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BlockState blockState = dimpos.world.getBlockState(dimpos.pos);
|
||||||
|
if (!AllBlocks.SCHEMATIC_TABLE.typeOf(blockState))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SchematicTableTileEntity tileEntity = (SchematicTableTileEntity) dimpos.world.getTileEntity(dimpos.pos);
|
||||||
|
tileEntity.finishUpload();
|
||||||
|
}
|
||||||
|
|
||||||
public void handleFinishedUpload(ServerPlayerEntity player, String schematic) {
|
public void handleFinishedUpload(ServerPlayerEntity player, String schematic) {
|
||||||
String playerSchematicId = player.getName().getFormattedText() + "/" + schematic;
|
String playerSchematicId = player.getName().getFormattedText() + "/" + schematic;
|
||||||
|
|
||||||
if (activeDownloads.containsKey(playerSchematicId)) {
|
if (activeUploads.containsKey(playerSchematicId)) {
|
||||||
try {
|
try {
|
||||||
activeDownloads.get(playerSchematicId).close();
|
activeUploads.get(playerSchematicId).stream.close();
|
||||||
activeDownloads.remove(playerSchematicId);
|
DimensionPos dimpos = activeUploads.remove(playerSchematicId).tablePos;
|
||||||
Create.logger.info("Finished receiving Schematic: " + playerSchematicId);
|
Create.logger.info("New Schematic Uploaded: " + playerSchematicId);
|
||||||
|
|
||||||
DimensionPos dimpos = activeTables.remove(playerSchematicId);
|
|
||||||
|
|
||||||
if (dimpos == null)
|
if (dimpos == null)
|
||||||
return;
|
return;
|
||||||
|
@ -100,21 +221,13 @@ public class ServerSchematicLoader {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SchematicTableTileEntity tileEntity = (SchematicTableTileEntity) dimpos.world.getTileEntity(dimpos.pos);
|
SchematicTableTileEntity tileEntity = (SchematicTableTileEntity) dimpos.world.getTileEntity(dimpos.pos);
|
||||||
|
tileEntity.finishUpload();
|
||||||
tileEntity.inventory.setStackInSlot(0, ItemStack.EMPTY);
|
tileEntity.inventory.setStackInSlot(0, ItemStack.EMPTY);
|
||||||
tileEntity.inventory.setStackInSlot(1,
|
tileEntity.inventory.setStackInSlot(1,
|
||||||
ItemBlueprint.create(schematic, player.getName().getFormattedText()));
|
ItemBlueprint.create(schematic, player.getName().getFormattedText()));
|
||||||
tileEntity.uploadingSchematic = null;
|
|
||||||
tileEntity.uploadingProgress = 0;
|
|
||||||
dimpos.world.notifyBlockUpdate(dimpos.pos, blockState, blockState, 3);
|
|
||||||
|
|
||||||
if (player.openContainer instanceof SchematicTableContainer) {
|
|
||||||
SchematicTableContainer c = (SchematicTableContainer) player.openContainer;
|
|
||||||
c.sendSchematicUpdate = true;
|
|
||||||
c.detectAndSendChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
Create.logger.error("Exception Thrown when finishing Upload: " + playerSchematicId);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,21 +2,15 @@ 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.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
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.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.minecraft.network.PacketBuffer;
|
import net.minecraft.network.PacketBuffer;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
|
||||||
import net.minecraftforge.fml.network.PacketDistributor;
|
|
||||||
import net.minecraftforge.items.SlotItemHandler;
|
import net.minecraftforge.items.SlotItemHandler;
|
||||||
|
|
||||||
public class SchematicTableContainer extends Container {
|
public class SchematicTableContainer extends Container {
|
||||||
|
@ -26,11 +20,6 @@ public class SchematicTableContainer extends Container {
|
||||||
private Slot outputSlot;
|
private Slot outputSlot;
|
||||||
private PlayerEntity player;
|
private PlayerEntity player;
|
||||||
|
|
||||||
public String schematicUploading;
|
|
||||||
public boolean isUploading;
|
|
||||||
public float progress;
|
|
||||||
public boolean sendSchematicUpdate;
|
|
||||||
|
|
||||||
public SchematicTableContainer(int id, PlayerInventory inv, PacketBuffer extraData) {
|
public SchematicTableContainer(int id, PlayerInventory inv, PacketBuffer extraData) {
|
||||||
super(AllContainers.SchematicTable.type, id);
|
super(AllContainers.SchematicTable.type, id);
|
||||||
player = inv.player;
|
player = inv.player;
|
||||||
|
@ -68,32 +57,17 @@ public class SchematicTableContainer extends Container {
|
||||||
// player Slots
|
// player Slots
|
||||||
for (int row = 0; row < 3; ++row) {
|
for (int row = 0; row < 3; ++row) {
|
||||||
for (int col = 0; col < 9; ++col) {
|
for (int col = 0; col < 9; ++col) {
|
||||||
this.addSlot(new Slot(player.inventory, col + row * 9 + 9, -8 + col * 18, 102 + row * 18));
|
this.addSlot(new Slot(player.inventory, col + row * 9 + 9, 12 + col * 18, 102 + row * 18));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) {
|
for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) {
|
||||||
this.addSlot(new Slot(player.inventory, hotbarSlot, -8 + hotbarSlot * 18, 160));
|
this.addSlot(new Slot(player.inventory, hotbarSlot, 12 + hotbarSlot * 18, 160));
|
||||||
}
|
}
|
||||||
|
|
||||||
detectAndSendChanges();
|
detectAndSendChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void detectAndSendChanges() {
|
|
||||||
if (te.uploadingSchematic != null) {
|
|
||||||
schematicUploading = te.uploadingSchematic;
|
|
||||||
progress = te.uploadingProgress;
|
|
||||||
isUploading = true;
|
|
||||||
} else {
|
|
||||||
schematicUploading = null;
|
|
||||||
progress = 0;
|
|
||||||
isUploading = false;
|
|
||||||
}
|
|
||||||
super.detectAndSendChanges();
|
|
||||||
sendSchematicInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canWrite() {
|
public boolean canWrite() {
|
||||||
return inputSlot.getHasStack() && !outputSlot.getHasStack();
|
return inputSlot.getHasStack() && !outputSlot.getHasStack();
|
||||||
}
|
}
|
||||||
|
@ -110,54 +84,14 @@ public class SchematicTableContainer extends Container {
|
||||||
return ItemStack.EMPTY;
|
return ItemStack.EMPTY;
|
||||||
|
|
||||||
ItemStack stack = clickedSlot.getStack();
|
ItemStack stack = clickedSlot.getStack();
|
||||||
if (clickedSlot == inputSlot || clickedSlot == outputSlot) {
|
if (index < 2)
|
||||||
int indexToPut = playerIn.inventory.getFirstEmptyStack();
|
mergeItemStack(stack, 2, inventorySlots.size(), false);
|
||||||
|
else
|
||||||
if (indexToPut == -1)
|
mergeItemStack(stack, 0, 1, false);
|
||||||
return ItemStack.EMPTY;
|
|
||||||
|
|
||||||
playerIn.inventory.setInventorySlotContents(indexToPut, stack);
|
|
||||||
clickedSlot.putStack(ItemStack.EMPTY);
|
|
||||||
return ItemStack.EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AllItems.EMPTY_BLUEPRINT.typeOf(stack) && !inputSlot.getHasStack()) {
|
|
||||||
clickedSlot.putStack(ItemStack.EMPTY);
|
|
||||||
inputSlot.putStack(stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ItemStack.EMPTY;
|
return ItemStack.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
public void onContainerClosed(PlayerEntity playerIn) {
|
|
||||||
super.onContainerClosed(playerIn);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SchematicTableTileEntity getTileEntity() {
|
public SchematicTableTileEntity getTileEntity() {
|
||||||
return te;
|
return te;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,63 +18,97 @@ import net.minecraftforge.items.ItemStackHandler;
|
||||||
public class SchematicTableTileEntity extends TileEntitySynced implements ITickableTileEntity, INamedContainerProvider {
|
public class SchematicTableTileEntity extends TileEntitySynced implements ITickableTileEntity, INamedContainerProvider {
|
||||||
|
|
||||||
public SchematicTableInventory inventory;
|
public SchematicTableInventory inventory;
|
||||||
|
public boolean isUploading;
|
||||||
public String uploadingSchematic;
|
public String uploadingSchematic;
|
||||||
public float uploadingProgress;
|
public float uploadingProgress;
|
||||||
|
public boolean sendUpdate;
|
||||||
|
|
||||||
public class SchematicTableInventory extends ItemStackHandler {
|
public class SchematicTableInventory extends ItemStackHandler {
|
||||||
public SchematicTableInventory() {
|
public SchematicTableInventory() {
|
||||||
super(2);
|
super(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onContentsChanged(int slot) {
|
protected void onContentsChanged(int slot) {
|
||||||
super.onContentsChanged(slot);
|
super.onContentsChanged(slot);
|
||||||
markDirty();
|
markDirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SchematicTableTileEntity() {
|
public SchematicTableTileEntity() {
|
||||||
this(AllTileEntities.SchematicTable.type);
|
this(AllTileEntities.SchematicTable.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SchematicTableTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
public SchematicTableTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
||||||
super(tileEntityTypeIn);
|
super(tileEntityTypeIn);
|
||||||
inventory = new SchematicTableInventory();
|
inventory = new SchematicTableInventory();
|
||||||
uploadingSchematic = null;
|
uploadingSchematic = null;
|
||||||
uploadingProgress = 0;
|
uploadingProgress = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendToContainer(PacketBuffer buffer) {
|
public void sendToContainer(PacketBuffer buffer) {
|
||||||
buffer.writeBlockPos(getPos());
|
buffer.writeBlockPos(getPos());
|
||||||
buffer.writeCompoundTag(getUpdateTag());
|
buffer.writeCompoundTag(getUpdateTag());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(CompoundNBT compound) {
|
public void read(CompoundNBT compound) {
|
||||||
inventory.deserializeNBT(compound.getCompound("Inventory"));
|
inventory.deserializeNBT(compound.getCompound("Inventory"));
|
||||||
if (compound.contains("Schematic")) {
|
readClientUpdate(compound);
|
||||||
|
super.read(compound);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readClientUpdate(CompoundNBT compound) {
|
||||||
|
if (compound.contains("Uploading")) {
|
||||||
|
isUploading = true;
|
||||||
uploadingSchematic = compound.getString("Schematic");
|
uploadingSchematic = compound.getString("Schematic");
|
||||||
uploadingProgress = compound.getFloat("Progress");
|
uploadingProgress = compound.getFloat("Progress");
|
||||||
} else {
|
} else {
|
||||||
|
isUploading = false;
|
||||||
uploadingSchematic = null;
|
uploadingSchematic = null;
|
||||||
uploadingProgress = 0;
|
uploadingProgress = 0;
|
||||||
}
|
}
|
||||||
super.read(compound);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundNBT write(CompoundNBT compound) {
|
public CompoundNBT write(CompoundNBT compound) {
|
||||||
compound.put("Inventory", inventory.serializeNBT());
|
compound.put("Inventory", inventory.serializeNBT());
|
||||||
if (uploadingSchematic != null) {
|
writeToClient(compound);
|
||||||
compound.putString("Schematic", uploadingSchematic);
|
|
||||||
compound.putFloat("Progress", uploadingProgress);
|
|
||||||
}
|
|
||||||
return super.write(compound);
|
return super.write(compound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompoundNBT writeToClient(CompoundNBT compound) {
|
||||||
|
if (isUploading) {
|
||||||
|
compound.putBoolean("Uploading", true);
|
||||||
|
compound.putString("Schematic", uploadingSchematic);
|
||||||
|
compound.putFloat("Progress", uploadingProgress);
|
||||||
|
}
|
||||||
|
return compound;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
// Update Client Tile
|
||||||
|
if (sendUpdate) {
|
||||||
|
sendUpdate = false;
|
||||||
|
world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startUpload(String schematic) {
|
||||||
|
isUploading = true;
|
||||||
|
uploadingProgress = 0;
|
||||||
|
uploadingSchematic = schematic;
|
||||||
|
sendUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finishUpload() {
|
||||||
|
isUploading = false;
|
||||||
|
uploadingProgress = 0;
|
||||||
|
uploadingSchematic = null;
|
||||||
|
sendUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
package com.simibubi.create.block;
|
package com.simibubi.create.block;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.texture.AtlasTexture;
|
import net.minecraft.client.renderer.texture.AtlasTexture;
|
||||||
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
|
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
|
||||||
|
import net.minecraft.particles.ParticleTypes;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
@ -50,7 +53,7 @@ public class SchematicannonRenderer extends TileEntityRenderer<SchematicannonTil
|
||||||
|
|
||||||
if (block.ticksRemaining == 0)
|
if (block.ticksRemaining == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Calculate position of flying block
|
// Calculate position of flying block
|
||||||
Vec3d start = new Vec3d(tileEntityIn.getPos().add(.5f, 1, .5f));
|
Vec3d start = new Vec3d(tileEntityIn.getPos().add(.5f, 1, .5f));
|
||||||
Vec3d target = new Vec3d(block.target).add(-.5, 0, 1);
|
Vec3d target = new Vec3d(block.target).add(-.5, 0, 1);
|
||||||
|
@ -84,13 +87,27 @@ public class SchematicannonRenderer extends TileEntityRenderer<SchematicannonTil
|
||||||
Minecraft.getInstance().getBlockRendererDispatcher().renderBlockBrightness(block.state, 1);
|
Minecraft.getInstance().getBlockRendererDispatcher().renderBlockBrightness(block.state, 1);
|
||||||
GlStateManager.popMatrix();
|
GlStateManager.popMatrix();
|
||||||
|
|
||||||
// Minecraft.getInstance().world.addParticle(ParticleTypes.END_ROD, blockLocation.x, blockLocation.y,
|
|
||||||
// blockLocation.z, 0, 0, 0);
|
|
||||||
|
|
||||||
// Apply Recoil if block was just launched
|
// Apply Recoil if block was just launched
|
||||||
if ((block.ticksRemaining + 1 - partialTicks) > block.totalTicks - 10) {
|
if ((block.ticksRemaining + 1 - partialTicks) > block.totalTicks - 10) {
|
||||||
recoil = Math.max(recoil, (block.ticksRemaining + 1 - partialTicks) - block.totalTicks + 10);
|
recoil = Math.max(recoil, (block.ticksRemaining + 1 - partialTicks) - block.totalTicks + 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Render particles for launch
|
||||||
|
if (block.ticksRemaining == block.totalTicks && tileEntityIn.firstRenderTick) {
|
||||||
|
tileEntityIn.firstRenderTick = false;
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
Random r = tileEntityIn.getWorld().getRandom();
|
||||||
|
double sX = cannonOffset.x * .01f;
|
||||||
|
double sY = (cannonOffset.y + 1) * .01f;
|
||||||
|
double sZ = cannonOffset.z * .01f;
|
||||||
|
double rX = r.nextFloat() - sX * 40;
|
||||||
|
double rY = r.nextFloat() - sY * 40;
|
||||||
|
double rZ = r.nextFloat() - sZ * 40;
|
||||||
|
tileEntityIn.getWorld().addParticle(ParticleTypes.CLOUD, start.x + rX, start.y + rY, start.z + rZ,
|
||||||
|
sX, sY, sZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,12 @@ import com.simibubi.create.AllItems;
|
||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
import com.simibubi.create.item.ItemBlueprint;
|
import com.simibubi.create.item.ItemBlueprint;
|
||||||
import com.simibubi.create.schematic.Cuboid;
|
import com.simibubi.create.schematic.Cuboid;
|
||||||
|
import com.simibubi.create.schematic.MaterialChecklist;
|
||||||
import com.simibubi.create.schematic.SchematicWorld;
|
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.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
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.inventory.container.Container;
|
import net.minecraft.inventory.container.Container;
|
||||||
|
@ -35,10 +35,8 @@ import net.minecraft.util.SoundEvents;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
import net.minecraft.util.text.ITextComponent;
|
import net.minecraft.util.text.ITextComponent;
|
||||||
import net.minecraft.util.text.StringTextComponent;
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
import net.minecraft.world.Explosion;
|
|
||||||
import net.minecraft.world.gen.feature.template.Template;
|
import net.minecraft.world.gen.feature.template.Template;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
@ -49,9 +47,12 @@ import net.minecraftforge.items.ItemStackHandler;
|
||||||
|
|
||||||
public class SchematicannonTileEntity extends TileEntitySynced implements ITickableTileEntity, INamedContainerProvider {
|
public class SchematicannonTileEntity extends TileEntitySynced implements ITickableTileEntity, INamedContainerProvider {
|
||||||
|
|
||||||
|
public static final int NEIGHBOUR_CHECKING = 100;
|
||||||
public static final int PLACEMENT_DELAY = 10;
|
public static final int PLACEMENT_DELAY = 10;
|
||||||
public static final float FUEL_PER_GUNPOWDER = .2f;
|
public static final float FUEL_PER_GUNPOWDER = .2f;
|
||||||
public static final float FUEL_USAGE_RATE = .0001f;
|
public static final float FUEL_USAGE_RATE = .0005f;
|
||||||
|
public static final int SKIPS_PER_TICK = 10;
|
||||||
|
public static final int MAX_ANCHOR_DISTANCE = 256;
|
||||||
|
|
||||||
public enum State {
|
public enum State {
|
||||||
STOPPED, PAUSED, RUNNING;
|
STOPPED, PAUSED, RUNNING;
|
||||||
|
@ -62,6 +63,8 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
|
|
||||||
// Sync
|
// Sync
|
||||||
public boolean sendUpdate;
|
public boolean sendUpdate;
|
||||||
|
public boolean dontUpdateChecklist;
|
||||||
|
public int neighbourCheckCooldown;
|
||||||
|
|
||||||
// Printer
|
// Printer
|
||||||
private SchematicWorld blockReader;
|
private SchematicWorld blockReader;
|
||||||
|
@ -69,26 +72,35 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
public BlockPos schematicAnchor;
|
public BlockPos schematicAnchor;
|
||||||
public boolean schematicLoaded;
|
public boolean schematicLoaded;
|
||||||
public boolean missingBlock;
|
public boolean missingBlock;
|
||||||
|
public boolean blockNotLoaded;
|
||||||
public boolean hasCreativeCrate;
|
public boolean hasCreativeCrate;
|
||||||
private int printerCooldown;
|
private int printerCooldown;
|
||||||
|
private int skipsLeft;
|
||||||
|
private boolean blockSkipped;
|
||||||
|
|
||||||
public BlockPos target;
|
public BlockPos target;
|
||||||
public BlockPos previousTarget;
|
public BlockPos previousTarget;
|
||||||
public List<IItemHandler> attachedInventories;
|
public List<IItemHandler> attachedInventories;
|
||||||
public List<LaunchedBlock> flyingBlocks;
|
public List<LaunchedBlock> flyingBlocks;
|
||||||
|
public MaterialChecklist checklist;
|
||||||
|
|
||||||
// Gui information
|
// Gui information
|
||||||
public float fuelLevel;
|
public float fuelLevel;
|
||||||
public float paperPrintingProgress;
|
public float bookPrintingProgress;
|
||||||
public float schematicProgress;
|
public float schematicProgress;
|
||||||
public String statusMsg;
|
public String statusMsg;
|
||||||
public State state;
|
public State state;
|
||||||
|
public int blocksPlaced;
|
||||||
|
public int blocksToPlace;
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
public int replaceMode;
|
public int replaceMode;
|
||||||
public boolean skipMissing;
|
public boolean skipMissing;
|
||||||
public boolean replaceTileEntities;
|
public boolean replaceTileEntities;
|
||||||
|
|
||||||
|
// Render
|
||||||
|
public boolean firstRenderTick;
|
||||||
|
|
||||||
public class SchematicannonInventory extends ItemStackHandler {
|
public class SchematicannonInventory extends ItemStackHandler {
|
||||||
public SchematicannonInventory() {
|
public SchematicannonInventory() {
|
||||||
super(5);
|
super(5);
|
||||||
|
@ -107,8 +119,8 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
return AllItems.BLUEPRINT.typeOf(stack);
|
return AllItems.BLUEPRINT.typeOf(stack);
|
||||||
case 1: // Blueprint output
|
case 1: // Blueprint output
|
||||||
return false;
|
return false;
|
||||||
case 2: // Paper input
|
case 2: // Book input
|
||||||
return stack.getItem() == Items.PAPER;
|
return stack.getItem() == Items.BOOK || stack.getItem() == Items.WRITTEN_BOOK;
|
||||||
case 3: // Material List output
|
case 3: // Material List output
|
||||||
return false;
|
return false;
|
||||||
case 4: // Gunpowder
|
case 4: // Gunpowder
|
||||||
|
@ -168,12 +180,18 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
statusMsg = "Idle";
|
statusMsg = "Idle";
|
||||||
state = State.STOPPED;
|
state = State.STOPPED;
|
||||||
replaceMode = 2;
|
replaceMode = 2;
|
||||||
|
neighbourCheckCooldown = NEIGHBOUR_CHECKING;
|
||||||
|
checklist = new MaterialChecklist();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void findInventories() {
|
public void findInventories() {
|
||||||
hasCreativeCrate = false;
|
hasCreativeCrate = false;
|
||||||
|
attachedInventories.clear();
|
||||||
for (Direction facing : Direction.values()) {
|
for (Direction facing : Direction.values()) {
|
||||||
|
|
||||||
|
if (!world.isBlockPresent(pos.offset(facing)))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (AllBlocks.CREATIVE_CRATE.typeOf(world.getBlockState(pos.offset(facing)))) {
|
if (AllBlocks.CREATIVE_CRATE.typeOf(world.getBlockState(pos.offset(facing)))) {
|
||||||
hasCreativeCrate = true;
|
hasCreativeCrate = true;
|
||||||
}
|
}
|
||||||
|
@ -192,19 +210,13 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
@Override
|
@Override
|
||||||
public void read(CompoundNBT compound) {
|
public void read(CompoundNBT compound) {
|
||||||
inventory.deserializeNBT(compound.getCompound("Inventory"));
|
inventory.deserializeNBT(compound.getCompound("Inventory"));
|
||||||
|
|
||||||
if (compound.contains("Running"))
|
if (compound.contains("Running"))
|
||||||
currentPos = NBTUtil.readBlockPos(compound.getCompound("CurrentPos"));
|
currentPos = NBTUtil.readBlockPos(compound.getCompound("CurrentPos"));
|
||||||
|
|
||||||
readClientUpdate(compound);
|
readClientUpdate(compound);
|
||||||
super.read(compound);
|
super.read(compound);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoad() {
|
|
||||||
findInventories();
|
|
||||||
super.onLoad();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readClientUpdate(CompoundNBT compound) {
|
public void readClientUpdate(CompoundNBT compound) {
|
||||||
|
@ -212,9 +224,11 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
// Gui information
|
// Gui information
|
||||||
statusMsg = compound.getString("Status");
|
statusMsg = compound.getString("Status");
|
||||||
schematicProgress = compound.getFloat("Progress");
|
schematicProgress = compound.getFloat("Progress");
|
||||||
paperPrintingProgress = compound.getFloat("PaperProgress");
|
bookPrintingProgress = compound.getFloat("PaperProgress");
|
||||||
fuelLevel = compound.getFloat("Fuel");
|
fuelLevel = compound.getFloat("Fuel");
|
||||||
state = State.valueOf(compound.getString("State"));
|
state = State.valueOf(compound.getString("State"));
|
||||||
|
blocksPlaced = compound.getInt("AmountPlaced");
|
||||||
|
blocksToPlace = compound.getInt("AmountToPlace");
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
CompoundNBT options = compound.getCompound("Options");
|
CompoundNBT options = compound.getCompound("Options");
|
||||||
|
@ -271,12 +285,12 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
@Override
|
@Override
|
||||||
public CompoundNBT write(CompoundNBT compound) {
|
public CompoundNBT write(CompoundNBT compound) {
|
||||||
compound.put("Inventory", inventory.serializeNBT());
|
compound.put("Inventory", inventory.serializeNBT());
|
||||||
|
|
||||||
if (state == State.RUNNING) {
|
if (state == State.RUNNING) {
|
||||||
compound.putBoolean("Running", true);
|
compound.putBoolean("Running", true);
|
||||||
compound.put("CurrentPos", NBTUtil.writeBlockPos(currentPos));
|
compound.put("CurrentPos", NBTUtil.writeBlockPos(currentPos));
|
||||||
}
|
}
|
||||||
|
|
||||||
writeToClient(compound);
|
writeToClient(compound);
|
||||||
return super.write(compound);
|
return super.write(compound);
|
||||||
}
|
}
|
||||||
|
@ -286,10 +300,12 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
|
|
||||||
// Gui information
|
// Gui information
|
||||||
compound.putFloat("Progress", schematicProgress);
|
compound.putFloat("Progress", schematicProgress);
|
||||||
compound.putFloat("PaperProgress", paperPrintingProgress);
|
compound.putFloat("PaperProgress", bookPrintingProgress);
|
||||||
compound.putFloat("Fuel", fuelLevel);
|
compound.putFloat("Fuel", fuelLevel);
|
||||||
compound.putString("Status", statusMsg);
|
compound.putString("Status", statusMsg);
|
||||||
compound.putString("State", state.name());
|
compound.putString("State", state.name());
|
||||||
|
compound.putInt("AmountPlaced", blocksPlaced);
|
||||||
|
compound.putInt("AmountToPlace", blocksToPlace);
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
CompoundNBT options = new CompoundNBT();
|
CompoundNBT options = new CompoundNBT();
|
||||||
|
@ -317,6 +333,12 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
if (neighbourCheckCooldown-- <= 0) {
|
||||||
|
neighbourCheckCooldown = NEIGHBOUR_CHECKING;
|
||||||
|
findInventories();
|
||||||
|
}
|
||||||
|
|
||||||
|
firstRenderTick = true;
|
||||||
previousTarget = target;
|
previousTarget = target;
|
||||||
tickFlyingBlocks();
|
tickFlyingBlocks();
|
||||||
|
|
||||||
|
@ -328,7 +350,15 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
refillFuelIfPossible();
|
refillFuelIfPossible();
|
||||||
|
|
||||||
// Update Printer
|
// Update Printer
|
||||||
tickPrinter();
|
skipsLeft = SKIPS_PER_TICK;
|
||||||
|
blockSkipped = true;
|
||||||
|
|
||||||
|
while (blockSkipped && skipsLeft-- > 0)
|
||||||
|
tickPrinter();
|
||||||
|
|
||||||
|
schematicProgress = 0;
|
||||||
|
if (blocksToPlace > 0)
|
||||||
|
schematicProgress = (float) blocksPlaced / blocksToPlace;
|
||||||
|
|
||||||
// Update Client Tile
|
// Update Client Tile
|
||||||
if (sendUpdate) {
|
if (sendUpdate) {
|
||||||
|
@ -339,6 +369,7 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
|
|
||||||
protected void tickPrinter() {
|
protected void tickPrinter() {
|
||||||
ItemStack blueprint = inventory.getStackInSlot(0);
|
ItemStack blueprint = inventory.getStackInSlot(0);
|
||||||
|
blockSkipped = false;
|
||||||
|
|
||||||
// Skip if not Active
|
// Skip if not Active
|
||||||
if (state == State.STOPPED) {
|
if (state == State.STOPPED) {
|
||||||
|
@ -346,8 +377,6 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
resetPrinter();
|
resetPrinter();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (state == State.PAUSED && !missingBlock && fuelLevel > FUEL_USAGE_RATE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (blueprint.isEmpty()) {
|
if (blueprint.isEmpty()) {
|
||||||
state = State.STOPPED;
|
state = State.STOPPED;
|
||||||
|
@ -356,31 +385,12 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state == State.PAUSED && !blockNotLoaded && !missingBlock && fuelLevel > FUEL_USAGE_RATE)
|
||||||
|
return;
|
||||||
|
|
||||||
// Initialize Printer
|
// Initialize Printer
|
||||||
if (!schematicLoaded) {
|
if (!schematicLoaded) {
|
||||||
if (!blueprint.hasTag()) {
|
initializePrinter(blueprint);
|
||||||
state = State.STOPPED;
|
|
||||||
statusMsg = "Invalid Blueprint";
|
|
||||||
sendUpdate = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!blueprint.getTag().getBoolean("Deployed")) {
|
|
||||||
state = State.STOPPED;
|
|
||||||
statusMsg = "Blueprint not Deployed";
|
|
||||||
sendUpdate = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentPos = currentPos != null ? currentPos.west() : BlockPos.ZERO.west();
|
|
||||||
schematicAnchor = NBTUtil.readBlockPos(blueprint.getTag().getCompound("Anchor"));
|
|
||||||
|
|
||||||
// Load blocks into reader
|
|
||||||
Template activeTemplate = ItemBlueprint.getSchematic(blueprint);
|
|
||||||
blockReader = new SchematicWorld(new HashMap<>(), new Cuboid(), schematicAnchor);
|
|
||||||
activeTemplate.addBlocksToWorld(blockReader, schematicAnchor, ItemBlueprint.getSettings(blueprint));
|
|
||||||
schematicLoaded = true;
|
|
||||||
sendUpdate = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,7 +410,13 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update Target
|
// Update Target
|
||||||
if (!missingBlock) {
|
if (hasCreativeCrate) {
|
||||||
|
if (missingBlock) {
|
||||||
|
missingBlock = false;
|
||||||
|
state = State.RUNNING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!missingBlock && !blockNotLoaded) {
|
||||||
advanceCurrentPos();
|
advanceCurrentPos();
|
||||||
|
|
||||||
// End reached
|
// End reached
|
||||||
|
@ -412,15 +428,31 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check block
|
// Check block
|
||||||
BlockState blockState = blockReader.getBlockState(target);
|
if (!getWorld().isAreaLoaded(target, 0)) {
|
||||||
if (!shouldPlace(target, blockState))
|
blockNotLoaded = true;
|
||||||
|
statusMsg = "Block is not loaded";
|
||||||
|
state = State.PAUSED;
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
if (blockNotLoaded) {
|
||||||
|
blockNotLoaded = false;
|
||||||
|
state = State.RUNNING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockState blockState = blockReader.getBlockState(target);
|
||||||
|
if (!shouldPlace(target, blockState)) {
|
||||||
|
statusMsg = "Searching";
|
||||||
|
blockSkipped = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Find Item
|
// Find Item
|
||||||
ItemStack requiredItem = getItemForBlock(blockState);
|
ItemStack requiredItem = getItemForBlock(blockState);
|
||||||
if (!findItemInAttachedInventories(requiredItem)) {
|
if (!findItemInAttachedInventories(requiredItem)) {
|
||||||
if (skipMissing) {
|
if (skipMissing) {
|
||||||
statusMsg = "Skipping";
|
statusMsg = "Skipping";
|
||||||
|
blockSkipped = true;
|
||||||
if (missingBlock) {
|
if (missingBlock) {
|
||||||
missingBlock = false;
|
missingBlock = false;
|
||||||
state = State.RUNNING;
|
state = State.RUNNING;
|
||||||
|
@ -436,7 +468,10 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
state = State.RUNNING;
|
state = State.RUNNING;
|
||||||
statusMsg = "Running...";
|
if (blockState.getBlock() != Blocks.AIR)
|
||||||
|
statusMsg = "Placing: " + blocksPlaced + " / " + blocksToPlace;
|
||||||
|
else
|
||||||
|
statusMsg = "Clearing Blocks";
|
||||||
launchBlock(target, blockState);
|
launchBlock(target, blockState);
|
||||||
printerCooldown = PLACEMENT_DELAY;
|
printerCooldown = PLACEMENT_DELAY;
|
||||||
fuelLevel -= FUEL_USAGE_RATE;
|
fuelLevel -= FUEL_USAGE_RATE;
|
||||||
|
@ -444,6 +479,51 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
missingBlock = false;
|
missingBlock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void initializePrinter(ItemStack blueprint) {
|
||||||
|
if (!blueprint.hasTag()) {
|
||||||
|
state = State.STOPPED;
|
||||||
|
statusMsg = "Invalid Blueprint";
|
||||||
|
sendUpdate = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!blueprint.getTag().getBoolean("Deployed")) {
|
||||||
|
state = State.STOPPED;
|
||||||
|
statusMsg = "Blueprint not Deployed";
|
||||||
|
sendUpdate = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load blocks into reader
|
||||||
|
Template activeTemplate = ItemBlueprint.getSchematic(blueprint);
|
||||||
|
BlockPos anchor = NBTUtil.readBlockPos(blueprint.getTag().getCompound("Anchor"));
|
||||||
|
|
||||||
|
if (activeTemplate.getSize().equals(BlockPos.ZERO)) {
|
||||||
|
state = State.STOPPED;
|
||||||
|
statusMsg = "Schematic File Expired";
|
||||||
|
inventory.setStackInSlot(0, ItemStack.EMPTY);
|
||||||
|
inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_BLUEPRINT.get()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!anchor.withinDistance(getPos(), MAX_ANCHOR_DISTANCE)) {
|
||||||
|
state = State.STOPPED;
|
||||||
|
statusMsg = "Target too Far Away";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
schematicAnchor = anchor;
|
||||||
|
blockReader = new SchematicWorld(new HashMap<>(), new Cuboid(), schematicAnchor);
|
||||||
|
activeTemplate.addBlocksToWorld(blockReader, schematicAnchor, ItemBlueprint.getSettings(blueprint));
|
||||||
|
schematicLoaded = true;
|
||||||
|
state = State.PAUSED;
|
||||||
|
statusMsg = "Ready";
|
||||||
|
updateChecklist();
|
||||||
|
sendUpdate = true;
|
||||||
|
blocksToPlace += blocksPlaced;
|
||||||
|
currentPos = currentPos != null ? currentPos.west() : blockReader.getBounds().getOrigin().west();
|
||||||
|
}
|
||||||
|
|
||||||
protected ItemStack getItemForBlock(BlockState blockState) {
|
protected ItemStack getItemForBlock(BlockState blockState) {
|
||||||
return new ItemStack(BlockItem.BLOCK_TO_ITEM.getOrDefault(blockState.getBlock(), Items.AIR));
|
return new ItemStack(BlockItem.BLOCK_TO_ITEM.getOrDefault(blockState.getBlock(), Items.AIR));
|
||||||
}
|
}
|
||||||
|
@ -467,18 +547,18 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
protected void advanceCurrentPos() {
|
protected void advanceCurrentPos() {
|
||||||
BlockPos size = blockReader.getBounds().getSize();
|
BlockPos size = blockReader.getBounds().getSize();
|
||||||
currentPos = currentPos.offset(Direction.EAST);
|
currentPos = currentPos.offset(Direction.EAST);
|
||||||
|
BlockPos posInBounds = currentPos.subtract(blockReader.getBounds().getOrigin());
|
||||||
|
|
||||||
schematicProgress += 1d / (size.getX() * size.getY() * size.getZ());
|
if (posInBounds.getX() > size.getX())
|
||||||
|
currentPos = new BlockPos(blockReader.getBounds().x, currentPos.getY(), currentPos.getZ() + 1).west();
|
||||||
if (currentPos.getX() > size.getX())
|
if (posInBounds.getZ() > size.getZ())
|
||||||
currentPos = new BlockPos(0, currentPos.getY(), currentPos.getZ() + 1);
|
currentPos = new BlockPos(currentPos.getX(), currentPos.getY() + 1, blockReader.getBounds().z).west();
|
||||||
if (currentPos.getZ() > size.getZ())
|
|
||||||
currentPos = new BlockPos(currentPos.getX(), currentPos.getY() + 1, 0);
|
|
||||||
|
|
||||||
// End reached
|
// End reached
|
||||||
if (currentPos.getY() > size.getY()) {
|
if (currentPos.getY() > size.getY()) {
|
||||||
inventory.setStackInSlot(0, ItemStack.EMPTY);
|
inventory.setStackInSlot(0, ItemStack.EMPTY);
|
||||||
inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_BLUEPRINT.get()));
|
inventory.setStackInSlot(1,
|
||||||
|
new ItemStack(AllItems.EMPTY_BLUEPRINT.get(), inventory.getStackInSlot(1).getCount() + 1));
|
||||||
state = State.STOPPED;
|
state = State.STOPPED;
|
||||||
statusMsg = "Finished";
|
statusMsg = "Finished";
|
||||||
resetPrinter();
|
resetPrinter();
|
||||||
|
@ -498,6 +578,8 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
missingBlock = false;
|
missingBlock = false;
|
||||||
sendUpdate = true;
|
sendUpdate = true;
|
||||||
schematicProgress = 0;
|
schematicProgress = 0;
|
||||||
|
blocksPlaced = 0;
|
||||||
|
blocksToPlace = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean shouldPlace(BlockPos pos, BlockState state) {
|
protected boolean shouldPlace(BlockPos pos, BlockState state) {
|
||||||
|
@ -548,37 +630,52 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void tickPaperPrinter() {
|
protected void tickPaperPrinter() {
|
||||||
int PaperInput = 2;
|
int BookInput = 2;
|
||||||
int PaperOutput = 3;
|
int BookOutput = 3;
|
||||||
|
|
||||||
ItemStack paper = inventory.extractItem(PaperInput, 1, true);
|
ItemStack blueprint = inventory.getStackInSlot(0);
|
||||||
boolean outputFull = inventory.getStackInSlot(PaperOutput).getCount() == inventory.getSlotLimit(PaperOutput);
|
ItemStack paper = inventory.extractItem(BookInput, 1, true);
|
||||||
|
boolean outputFull = inventory.getStackInSlot(BookOutput).getCount() == inventory.getSlotLimit(BookOutput);
|
||||||
|
|
||||||
if (paper.isEmpty() || outputFull) {
|
if (paper.isEmpty() || outputFull) {
|
||||||
if (paperPrintingProgress != 0)
|
if (bookPrintingProgress != 0)
|
||||||
sendUpdate = true;
|
sendUpdate = true;
|
||||||
paperPrintingProgress = 0;
|
bookPrintingProgress = 0;
|
||||||
|
dontUpdateChecklist = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (paperPrintingProgress >= 1) {
|
if (!schematicLoaded) {
|
||||||
paperPrintingProgress = 0;
|
if (!blueprint.isEmpty())
|
||||||
inventory.extractItem(PaperInput, 1, false);
|
initializePrinter(blueprint);
|
||||||
inventory.setStackInSlot(PaperOutput,
|
return;
|
||||||
new ItemStack(Items.PAPER, inventory.getStackInSlot(PaperOutput).getCount() + 1));
|
}
|
||||||
|
|
||||||
|
if (bookPrintingProgress >= 1) {
|
||||||
|
bookPrintingProgress = 0;
|
||||||
|
|
||||||
|
if (!dontUpdateChecklist)
|
||||||
|
updateChecklist();
|
||||||
|
|
||||||
|
dontUpdateChecklist = true;
|
||||||
|
inventory.extractItem(BookInput, 1, false);
|
||||||
|
ItemStack stack = checklist.createItem();
|
||||||
|
stack.setCount(inventory.getStackInSlot(BookOutput).getCount() + 1);
|
||||||
|
inventory.setStackInSlot(BookOutput, stack);
|
||||||
sendUpdate = true;
|
sendUpdate = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
paperPrintingProgress += 0.05f;
|
bookPrintingProgress += 0.05f;
|
||||||
sendUpdate = true;
|
sendUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void launchBlock(BlockPos target, BlockState state) {
|
protected void launchBlock(BlockPos target, BlockState state) {
|
||||||
|
if (state.getBlock() != Blocks.AIR)
|
||||||
|
blocksPlaced++;
|
||||||
flyingBlocks.add(new LaunchedBlock(target, state));
|
flyingBlocks.add(new LaunchedBlock(target, state));
|
||||||
Vec3d explosionPos = new Vec3d(pos).add(new Vec3d(target.subtract(pos)).normalize());
|
world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), SoundEvents.ENTITY_GENERIC_EXPLODE, SoundCategory.BLOCKS,
|
||||||
this.world.createExplosion((Entity) null, explosionPos.x, explosionPos.y + 1.5f, explosionPos.z, 0,
|
.1f, 1.1f);
|
||||||
Explosion.Mode.NONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendToContainer(PacketBuffer buffer) {
|
public void sendToContainer(PacketBuffer buffer) {
|
||||||
|
@ -596,4 +693,36 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka
|
||||||
return new StringTextComponent(getType().getRegistryName().toString());
|
return new StringTextComponent(getType().getRegistryName().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateChecklist() {
|
||||||
|
checklist.required.clear();
|
||||||
|
checklist.blocksNotLoaded = false;
|
||||||
|
|
||||||
|
if (schematicLoaded) {
|
||||||
|
blocksToPlace = blocksPlaced;
|
||||||
|
for (BlockPos pos : blockReader.getAllPositions()) {
|
||||||
|
BlockState required = blockReader.getBlockState(pos.add(schematicAnchor));
|
||||||
|
|
||||||
|
if (!getWorld().isAreaLoaded(pos.add(schematicAnchor), 0)) {
|
||||||
|
checklist.warnBlockNotLoaded();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!shouldPlace(pos.add(schematicAnchor), required))
|
||||||
|
continue;
|
||||||
|
ItemStack requiredItem = getItemForBlock(required);
|
||||||
|
checklist.require(requiredItem.getItem());
|
||||||
|
blocksToPlace++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checklist.gathered.clear();
|
||||||
|
for (IItemHandler inventory : attachedInventories) {
|
||||||
|
for (int slot = 0; slot < inventory.getSlots(); slot++) {
|
||||||
|
ItemStack stackInSlot = inventory.getStackInSlot(slot);
|
||||||
|
if (inventory.extractItem(slot, 1, true).isEmpty())
|
||||||
|
continue;
|
||||||
|
checklist.collect(stackInSlot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sendUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,8 +45,8 @@ public enum GuiResources {
|
||||||
ICON_TARGET("icons.png", 48, 0, 16, 16),
|
ICON_TARGET("icons.png", 48, 0, 16, 16),
|
||||||
ICON_CONFIRM("icons.png", 0, 16, 16, 16),
|
ICON_CONFIRM("icons.png", 0, 16, 16, 16),
|
||||||
|
|
||||||
ICON_NORMAL_ROOF("icons.png", 32, 16, 16, 16),
|
ICON_OPEN_FOLDER("icons.png", 32, 16, 16, 16),
|
||||||
ICON_FLAT_ROOF("icons.png", 48, 16, 16, 16),
|
ICON_REFRESH("icons.png", 48, 16, 16, 16),
|
||||||
|
|
||||||
ICON_DONT_REPLACE("icons.png", 0, 32, 16, 16),
|
ICON_DONT_REPLACE("icons.png", 0, 32, 16, 16),
|
||||||
ICON_REPLACE_SOLID("icons.png", 16, 32, 16, 16),
|
ICON_REPLACE_SOLID("icons.png", 16, 32, 16, 16),
|
||||||
|
@ -55,6 +55,7 @@ public enum GuiResources {
|
||||||
|
|
||||||
ICON_TOOL_DEPLOY("icons.png", 0, 48, 16, 16),
|
ICON_TOOL_DEPLOY("icons.png", 0, 48, 16, 16),
|
||||||
ICON_SKIP_MISSING("icons.png", 16, 48, 16, 16),
|
ICON_SKIP_MISSING("icons.png", 16, 48, 16, 16),
|
||||||
|
ICON_SKIP_TILES("icons.png", 32, 48, 16, 16),
|
||||||
|
|
||||||
ICON_TOOL_MOVE_XZ("icons.png", 0, 64, 16, 16),
|
ICON_TOOL_MOVE_XZ("icons.png", 0, 64, 16, 16),
|
||||||
ICON_TOOL_MOVE_Y("icons.png", 16, 64, 16, 16),
|
ICON_TOOL_MOVE_Y("icons.png", 16, 64, 16, 16),
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package com.simibubi.create.gui;
|
package com.simibubi.create.gui;
|
||||||
|
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.block.SchematicTableContainer;
|
import com.simibubi.create.block.SchematicTableContainer;
|
||||||
import com.simibubi.create.gui.widgets.AbstractSimiWidget;
|
|
||||||
import com.simibubi.create.gui.widgets.DynamicLabel;
|
import com.simibubi.create.gui.widgets.DynamicLabel;
|
||||||
import com.simibubi.create.gui.widgets.OptionScrollArea;
|
import com.simibubi.create.gui.widgets.OptionScrollArea;
|
||||||
import com.simibubi.create.gui.widgets.ScrollArea;
|
import com.simibubi.create.gui.widgets.ScrollArea;
|
||||||
|
@ -14,29 +14,25 @@ import com.simibubi.create.gui.widgets.SimiButton;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.IHasContainer;
|
import net.minecraft.client.gui.IHasContainer;
|
||||||
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
|
|
||||||
import net.minecraft.client.gui.widget.Widget;
|
|
||||||
import net.minecraft.client.renderer.RenderHelper;
|
import net.minecraft.client.renderer.RenderHelper;
|
||||||
import net.minecraft.client.renderer.texture.AtlasTexture;
|
import net.minecraft.client.renderer.texture.AtlasTexture;
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
import net.minecraft.util.Util;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.text.ITextComponent;
|
import net.minecraft.util.text.ITextComponent;
|
||||||
|
|
||||||
public class SchematicTableScreen extends ContainerScreen<SchematicTableContainer>
|
public class SchematicTableScreen extends AbstractSimiContainerScreen<SchematicTableContainer>
|
||||||
implements IHasContainer<SchematicTableContainer> {
|
implements IHasContainer<SchematicTableContainer> {
|
||||||
|
|
||||||
private ScrollArea schematics;
|
private ScrollArea schematicsArea;
|
||||||
private SimiButton button;
|
private SimiButton confirmButton;
|
||||||
private DynamicLabel label;
|
private SimiButton folderButton;
|
||||||
|
private SimiButton refreshButton;
|
||||||
|
private DynamicLabel schematicsLabel;
|
||||||
|
|
||||||
private float progress;
|
private float progress;
|
||||||
private float lastProgress;
|
private float chasingProgress;
|
||||||
|
private float lastChasingProgress;
|
||||||
private int xTopLeft;
|
|
||||||
private int yTopLeft;
|
|
||||||
|
|
||||||
private int xMainWindow;
|
|
||||||
private int yMainWindow;
|
|
||||||
|
|
||||||
public SchematicTableScreen(SchematicTableContainer container, PlayerInventory playerInventory,
|
public SchematicTableScreen(SchematicTableContainer container, PlayerInventory playerInventory,
|
||||||
ITextComponent title) {
|
ITextComponent title) {
|
||||||
|
@ -45,63 +41,71 @@ public class SchematicTableScreen extends ContainerScreen<SchematicTableContaine
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init() {
|
protected void init() {
|
||||||
|
setWindowSize(GuiResources.SCHEMATIC_TABLE.width, GuiResources.SCHEMATIC_TABLE.height + 50);
|
||||||
super.init();
|
super.init();
|
||||||
xTopLeft = (width - GuiResources.SCHEMATIC_TABLE.width) / 2;
|
widgets.clear();
|
||||||
yTopLeft = (height - GuiResources.SCHEMATIC_TABLE.height + 50) / 2;
|
|
||||||
xMainWindow = xTopLeft - 40;
|
int mainLeft = guiLeft - 56;
|
||||||
yMainWindow = yTopLeft - 80;
|
int mainTop = guiTop - 16;
|
||||||
buttons.clear();
|
|
||||||
|
|
||||||
Create.cSchematicLoader.refresh();
|
Create.cSchematicLoader.refresh();
|
||||||
List<String> availableSchematics = Create.cSchematicLoader.getAvailableSchematics();
|
List<String> availableSchematics = Create.cSchematicLoader.getAvailableSchematics();
|
||||||
|
|
||||||
if (!availableSchematics.isEmpty()) {
|
if (!availableSchematics.isEmpty()) {
|
||||||
label = new DynamicLabel(xMainWindow + 36, yMainWindow + 26, "").withShadow();
|
schematicsLabel = new DynamicLabel(mainLeft + 36, mainTop + 26, "").withShadow();
|
||||||
schematics = new OptionScrollArea(xMainWindow + 33, yMainWindow + 23, 134, 14)
|
schematicsArea = new OptionScrollArea(mainLeft + 33, mainTop + 23, 134, 14).forOptions(availableSchematics)
|
||||||
.forOptions(availableSchematics).titled("Available Schematics").writingTo(label);
|
.titled("Available Schematics").writingTo(schematicsLabel);
|
||||||
buttons.add(schematics);
|
widgets.add(schematicsArea);
|
||||||
buttons.add(label);
|
widgets.add(schematicsLabel);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
}
|
confirmButton = new SimiButton(mainLeft + 69, mainTop + 55, GuiResources.ICON_CONFIRM);
|
||||||
|
folderButton = new SimiButton(mainLeft + 204, mainTop + 6, GuiResources.ICON_OPEN_FOLDER);
|
||||||
button = new SimiButton(xMainWindow + 69, yMainWindow + 55, GuiResources.ICON_CONFIRM);
|
refreshButton = new SimiButton(mainLeft + 204, mainTop + 26, GuiResources.ICON_REFRESH);
|
||||||
buttons.add(button);
|
widgets.add(confirmButton);
|
||||||
|
widgets.add(folderButton);
|
||||||
|
widgets.add(refreshButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
|
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
|
||||||
int x = xTopLeft;
|
super.drawGuiContainerBackgroundLayer(partialTicks, mouseX, mouseY);
|
||||||
int y = yTopLeft;
|
|
||||||
|
|
||||||
GuiResources.SCHEMATIC_TABLE.draw(this, xMainWindow, yMainWindow);
|
|
||||||
GuiResources.PLAYER_INVENTORY.draw(this, x, y + 20);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (schematics == null) {
|
|
||||||
font.drawStringWithShadow(" No Schematics Saved ", xMainWindow + 39, yMainWindow + 26, 0xFFDD44);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(int mouseX, int mouseY, float pt) {
|
protected void renderWindow(int mouseX, int mouseY, float partialTicks) {
|
||||||
renderBackground();
|
|
||||||
super.render(mouseX, mouseY, pt);
|
int x = guiLeft + 20;
|
||||||
|
int y = guiTop;
|
||||||
|
|
||||||
|
int mainLeft = guiLeft - 56;
|
||||||
|
int mainTop = guiTop - 16;
|
||||||
|
|
||||||
|
GuiResources.PLAYER_INVENTORY.draw(this, x- 16, y + 70 + 14);
|
||||||
|
font.drawString("Inventory", x - 15 + 7, y + 64 + 26, 0x666666);
|
||||||
|
|
||||||
|
GuiResources.SCHEMATIC_TABLE.draw(this, mainLeft, mainTop);
|
||||||
|
if (container.getTileEntity().isUploading)
|
||||||
|
font.drawString("Uploading...", mainLeft + 76, mainTop + 10, GuiResources.FONT_COLOR);
|
||||||
|
else if (container.getSlot(1).getHasStack())
|
||||||
|
font.drawString("Upload Finished!", mainLeft + 60, mainTop + 10, GuiResources.FONT_COLOR);
|
||||||
|
else
|
||||||
|
font.drawString("Schematic Table", mainLeft + 60, mainTop + 10, GuiResources.FONT_COLOR);
|
||||||
|
|
||||||
|
if (schematicsArea == null) {
|
||||||
|
font.drawStringWithShadow(" No Schematics Saved ", mainLeft + 39, mainTop + 26, 0xFFDD44);
|
||||||
|
}
|
||||||
|
|
||||||
minecraft.getTextureManager().bindTexture(GuiResources.SCHEMATIC_TABLE_PROGRESS.location);
|
minecraft.getTextureManager().bindTexture(GuiResources.SCHEMATIC_TABLE_PROGRESS.location);
|
||||||
int width = (int) (GuiResources.SCHEMATIC_TABLE_PROGRESS.width * MathHelper.lerp(pt, lastProgress, progress));
|
int width = (int) (GuiResources.SCHEMATIC_TABLE_PROGRESS.width
|
||||||
|
* MathHelper.lerp(partialTicks, lastChasingProgress, chasingProgress));
|
||||||
int height = GuiResources.SCHEMATIC_TABLE_PROGRESS.height;
|
int height = GuiResources.SCHEMATIC_TABLE_PROGRESS.height;
|
||||||
GlStateManager.disableLighting();
|
GlStateManager.disableLighting();
|
||||||
blit(xMainWindow + 94, yMainWindow + 56, GuiResources.SCHEMATIC_TABLE_PROGRESS.startX,
|
blit(mainLeft + 94, mainTop + 56, GuiResources.SCHEMATIC_TABLE_PROGRESS.startX,
|
||||||
GuiResources.SCHEMATIC_TABLE_PROGRESS.startY, width, height);
|
GuiResources.SCHEMATIC_TABLE_PROGRESS.startY, width, height);
|
||||||
|
|
||||||
GlStateManager.pushLightingAttributes();
|
|
||||||
GlStateManager.pushMatrix();
|
GlStateManager.pushMatrix();
|
||||||
|
|
||||||
GlStateManager.enableBlend();
|
GlStateManager.enableBlend();
|
||||||
|
@ -112,73 +116,81 @@ public class SchematicTableScreen extends ContainerScreen<SchematicTableContaine
|
||||||
GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
|
GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||||
GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
|
GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||||
|
|
||||||
GlStateManager.translated(xTopLeft + 220, yTopLeft + 30, 200);
|
GlStateManager.translated(mainLeft + 270, mainTop + 100, 200);
|
||||||
GlStateManager.rotatef(50, -.5f, 1, -.2f);
|
GlStateManager.rotatef(50, -.5f, 1, -.2f);
|
||||||
GlStateManager.scaled(50, -50, 50);
|
GlStateManager.scaled(50, -50, 50);
|
||||||
|
|
||||||
Minecraft.getInstance().getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
|
Minecraft.getInstance().getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
|
||||||
minecraft.getBlockRendererDispatcher().renderBlockBrightness(AllBlocks.SCHEMATIC_TABLE.get().getDefaultState(), 1);
|
minecraft.getBlockRendererDispatcher().renderBlockBrightness(AllBlocks.SCHEMATIC_TABLE.get().getDefaultState(),
|
||||||
|
1);
|
||||||
|
|
||||||
GlStateManager.disableAlphaTest();
|
GlStateManager.disableAlphaTest();
|
||||||
GlStateManager.disableRescaleNormal();
|
GlStateManager.disableRescaleNormal();
|
||||||
|
|
||||||
GlStateManager.popMatrix();
|
GlStateManager.popMatrix();
|
||||||
GlStateManager.popAttributes();
|
|
||||||
|
|
||||||
renderHoveredToolTip(mouseX, mouseY);
|
|
||||||
for (Widget w : buttons) {
|
|
||||||
if (w instanceof AbstractSimiWidget && w.isHovered()) {
|
|
||||||
List<String> toolTip = ((AbstractSimiWidget) w).getToolTip();
|
|
||||||
renderTooltip(toolTip, mouseX, mouseY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPauseScreen() {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
if (container.isUploading) {
|
boolean finished = container.getSlot(1).getHasStack();
|
||||||
lastProgress = progress;
|
|
||||||
progress = Create.cSchematicLoader.getProgress(container.schematicUploading);
|
if (container.getTileEntity().isUploading || finished) {
|
||||||
label.colored(0xCCDDFF);
|
if (finished) {
|
||||||
button.active = false;
|
chasingProgress = lastChasingProgress = progress = 1;
|
||||||
schematics.visible = false;
|
} else {
|
||||||
|
lastChasingProgress = chasingProgress;
|
||||||
|
progress = container.getTileEntity().uploadingProgress;
|
||||||
|
chasingProgress += (progress - chasingProgress) * .5f;
|
||||||
|
}
|
||||||
|
confirmButton.active = false;
|
||||||
|
|
||||||
|
if (schematicsLabel != null) {
|
||||||
|
schematicsLabel.colored(0xCCDDFF);
|
||||||
|
schematicsLabel.text = container.getTileEntity().uploadingSchematic;
|
||||||
|
}
|
||||||
|
if (schematicsArea != null)
|
||||||
|
schematicsArea.visible = false;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
progress = 0;
|
progress = 0;
|
||||||
lastProgress = 0;
|
chasingProgress = lastChasingProgress = 0;
|
||||||
label.colored(0xFFFFFF);
|
confirmButton.active = true;
|
||||||
button.active = true;
|
|
||||||
schematics.visible = true;
|
if (schematicsLabel != null)
|
||||||
|
schematicsLabel.colored(0xFFFFFF);
|
||||||
|
if (schematicsArea != null) {
|
||||||
|
schematicsArea.writingTo(schematicsLabel);
|
||||||
|
schematicsArea.visible = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) {
|
public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) {
|
||||||
if (button.active && button.isHovered() && ((SchematicTableContainer) container).canWrite() && schematics != null) {
|
if (confirmButton.active && confirmButton.isHovered() && ((SchematicTableContainer) container).canWrite()
|
||||||
|
&& schematicsArea != null) {
|
||||||
lastProgress = progress = 0;
|
|
||||||
|
lastChasingProgress = chasingProgress = progress = 0;
|
||||||
List<String> availableSchematics = Create.cSchematicLoader.getAvailableSchematics();
|
List<String> availableSchematics = Create.cSchematicLoader.getAvailableSchematics();
|
||||||
String schematic = availableSchematics.get(schematics.getState());
|
String schematic = availableSchematics.get(schematicsArea.getState());
|
||||||
Create.cSchematicLoader.startNewUpload(schematic);
|
Create.cSchematicLoader.startNewUpload(schematic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (folderButton.isHovered()) {
|
||||||
|
Util.getOSType().openFile(Paths.get("schematics/").toFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refreshButton.isHovered()) {
|
||||||
|
Create.cSchematicLoader.refresh();
|
||||||
|
List<String> availableSchematics = Create.cSchematicLoader.getAvailableSchematics();
|
||||||
|
widgets.remove(schematicsArea);
|
||||||
|
schematicsArea = new OptionScrollArea(guiLeft - 56 + 33, guiTop - 16 + 23, 134, 14).forOptions(availableSchematics)
|
||||||
|
.titled("Available Schematics").writingTo(schematicsLabel);
|
||||||
|
widgets.add(schematicsArea);
|
||||||
|
}
|
||||||
|
|
||||||
return super.mouseClicked(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_);
|
return super.mouseClicked(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean mouseScrolled(double p_mouseScrolled_1_, double p_mouseScrolled_3_, double p_mouseScrolled_5_) {
|
|
||||||
boolean b = false;
|
|
||||||
for (Widget w : buttons) {
|
|
||||||
if (w.mouseScrolled(p_mouseScrolled_1_, p_mouseScrolled_3_, p_mouseScrolled_5_))
|
|
||||||
b = true;
|
|
||||||
}
|
|
||||||
return b || super.mouseScrolled(p_mouseScrolled_1_, p_mouseScrolled_3_, p_mouseScrolled_5_);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
|
||||||
|
|
||||||
protected SimiButton skipMissingButton;
|
protected SimiButton skipMissingButton;
|
||||||
protected GuiIndicator skipMissingIndicator;
|
protected GuiIndicator skipMissingIndicator;
|
||||||
|
protected SimiButton skipTilesButton;
|
||||||
|
protected GuiIndicator skipTilesIndicator;
|
||||||
|
|
||||||
protected SimiButton playButton;
|
protected SimiButton playButton;
|
||||||
protected GuiIndicator playIndicator;
|
protected GuiIndicator playIndicator;
|
||||||
|
@ -54,12 +56,12 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
|
||||||
widgets.clear();
|
widgets.clear();
|
||||||
|
|
||||||
// Play Pause Stop
|
// Play Pause Stop
|
||||||
playButton = new SimiButton(x + 69, y + 55, GuiResources.ICON_PLAY);
|
playButton = new SimiButton(x + 70, y + 55, GuiResources.ICON_PLAY);
|
||||||
playIndicator = new GuiIndicator(x + 69, y + 50, "");
|
playIndicator = new GuiIndicator(x + 70, y + 50, "");
|
||||||
pauseButton = new SimiButton(x + 88, y + 55, GuiResources.ICON_PAUSE);
|
pauseButton = new SimiButton(x + 88, y + 55, GuiResources.ICON_PAUSE);
|
||||||
pauseIndicator = new GuiIndicator(x + 88, y + 50, "");
|
pauseIndicator = new GuiIndicator(x + 88, y + 50, "");
|
||||||
resetButton = new SimiButton(x + 107, y + 55, GuiResources.ICON_STOP);
|
resetButton = new SimiButton(x + 106, y + 55, GuiResources.ICON_STOP);
|
||||||
resetIndicator = new GuiIndicator(x + 107, y + 50, "Not Running");
|
resetIndicator = new GuiIndicator(x + 106, y + 50, "Not Running");
|
||||||
resetIndicator.state = State.RED;
|
resetIndicator.state = State.RED;
|
||||||
Collections.addAll(widgets, playButton, playIndicator, pauseButton, pauseIndicator, resetButton,
|
Collections.addAll(widgets, playButton, playIndicator, pauseButton, pauseIndicator, resetButton,
|
||||||
resetIndicator);
|
resetIndicator);
|
||||||
|
@ -73,18 +75,23 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
|
||||||
"Replace Solid with Any", "Replace Solid with Empty");
|
"Replace Solid with Any", "Replace Solid with Empty");
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
replaceLevelIndicators.add(new GuiIndicator(x + 12 + i * 18, y + 96, ""));
|
replaceLevelIndicators.add(new GuiIndicator(x + 16 + i * 18, y + 96, ""));
|
||||||
replaceLevelButtons.add(new SimiButton(x + 12 + i * 18, y + 101, icons.get(i)));
|
replaceLevelButtons.add(new SimiButton(x + 16 + i * 18, y + 101, icons.get(i)));
|
||||||
replaceLevelButtons.get(i).setToolTip(toolTips.get(i));
|
replaceLevelButtons.get(i).setToolTip(toolTips.get(i));
|
||||||
}
|
}
|
||||||
widgets.addAll(replaceLevelButtons);
|
widgets.addAll(replaceLevelButtons);
|
||||||
widgets.addAll(replaceLevelIndicators);
|
widgets.addAll(replaceLevelIndicators);
|
||||||
|
|
||||||
// Other Settings
|
// Other Settings
|
||||||
skipMissingButton = new SimiButton(x + 107, y + 101, GuiResources.ICON_SKIP_MISSING);
|
skipMissingButton = new SimiButton(x + 106, y + 101, GuiResources.ICON_SKIP_MISSING);
|
||||||
skipMissingButton.setToolTip("Skip missing Blocks");
|
skipMissingButton.setToolTip("Skip missing Blocks");
|
||||||
skipMissingIndicator = new GuiIndicator(x + 107, y + 96, "");
|
skipMissingIndicator = new GuiIndicator(x + 106, y + 96, "");
|
||||||
Collections.addAll(widgets, skipMissingButton, skipMissingIndicator);
|
Collections.addAll(widgets, skipMissingButton, skipMissingIndicator);
|
||||||
|
|
||||||
|
skipTilesButton = new SimiButton(x + 124, y + 101, GuiResources.ICON_SKIP_TILES);
|
||||||
|
skipTilesButton.setToolTip("Protect Tile Entities");
|
||||||
|
skipTilesIndicator = new GuiIndicator(x + 124, y + 96, "");
|
||||||
|
Collections.addAll(widgets, skipTilesButton, skipTilesIndicator);
|
||||||
|
|
||||||
tick();
|
tick();
|
||||||
}
|
}
|
||||||
|
@ -97,6 +104,7 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
|
||||||
replaceLevelIndicators.get(replaceMode).state = replaceMode <= te.replaceMode ? State.ON : State.OFF;
|
replaceLevelIndicators.get(replaceMode).state = replaceMode <= te.replaceMode ? State.ON : State.OFF;
|
||||||
|
|
||||||
skipMissingIndicator.state = te.skipMissing ? State.ON : State.OFF;
|
skipMissingIndicator.state = te.skipMissing ? State.ON : State.OFF;
|
||||||
|
skipTilesIndicator.state = !te.replaceTileEntities ? State.ON : State.OFF;
|
||||||
|
|
||||||
playIndicator.state = State.OFF;
|
playIndicator.state = State.OFF;
|
||||||
pauseIndicator.state = State.OFF;
|
pauseIndicator.state = State.OFF;
|
||||||
|
@ -149,6 +157,14 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
|
||||||
tip.add(TextFormatting.GRAY + "a required Block for placement, it");
|
tip.add(TextFormatting.GRAY + "a required Block for placement, it");
|
||||||
tip.add(TextFormatting.GRAY + "will continue at the next Location.");
|
tip.add(TextFormatting.GRAY + "will continue at the next Location.");
|
||||||
}
|
}
|
||||||
|
if (skipTilesButton.isHovered()) {
|
||||||
|
List<String> tip = skipTilesButton.getToolTip();
|
||||||
|
tip.remove(1);
|
||||||
|
tip.add(TextFormatting.BLUE
|
||||||
|
+ (skipTilesIndicator.state == State.ON ? "Currently Enabled" : "Currently Disabled"));
|
||||||
|
tip.add(TextFormatting.GRAY + "The Schematicannon will avoid replacing");
|
||||||
|
tip.add(TextFormatting.GRAY + "data holding blocks such as Chests.");
|
||||||
|
}
|
||||||
if (replaceLevelButtons.get(0).isHovered()) {
|
if (replaceLevelButtons.get(0).isHovered()) {
|
||||||
List<String> tip = replaceLevelButtons.get(0).getToolTip();
|
List<String> tip = replaceLevelButtons.get(0).getToolTip();
|
||||||
tip.remove(1);
|
tip.remove(1);
|
||||||
|
@ -199,7 +215,7 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
|
||||||
SchematicannonTileEntity te = container.getTileEntity();
|
SchematicannonTileEntity te = container.getTileEntity();
|
||||||
renderPrintingProgress(te.schematicProgress);
|
renderPrintingProgress(te.schematicProgress);
|
||||||
renderFuelBar(te.fuelLevel);
|
renderFuelBar(te.fuelLevel);
|
||||||
renderChecklistPrinterProgress(te.paperPrintingProgress);
|
renderChecklistPrinterProgress(te.bookPrintingProgress);
|
||||||
|
|
||||||
if (!te.inventory.getStackInSlot(0).isEmpty())
|
if (!te.inventory.getStackInSlot(0).isEmpty())
|
||||||
renderBlueprintHighlight();
|
renderBlueprintHighlight();
|
||||||
|
@ -241,6 +257,7 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void renderPrintingProgress(float progress) {
|
protected void renderPrintingProgress(float progress) {
|
||||||
|
progress = Math.min(progress, 1);
|
||||||
GuiResources sprite = GuiResources.SCHEMATICANNON_PROGRESS;
|
GuiResources sprite = GuiResources.SCHEMATICANNON_PROGRESS;
|
||||||
minecraft.getTextureManager().bindTexture(sprite.location);
|
minecraft.getTextureManager().bindTexture(sprite.location);
|
||||||
blit(guiLeft + 20 + 39, guiTop + 36, sprite.startX, sprite.startY, (int) (sprite.width * progress),
|
blit(guiLeft + 20 + 39, guiTop + 36, sprite.startX, sprite.startY, (int) (sprite.width * progress),
|
||||||
|
@ -299,6 +316,8 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
|
||||||
|
|
||||||
if (skipMissingButton.isHovered())
|
if (skipMissingButton.isHovered())
|
||||||
sendOptionUpdate(Option.SKIP_MISSING, !container.getTileEntity().skipMissing);
|
sendOptionUpdate(Option.SKIP_MISSING, !container.getTileEntity().skipMissing);
|
||||||
|
if (skipTilesButton.isHovered())
|
||||||
|
sendOptionUpdate(Option.SKIP_TILES, !container.getTileEntity().replaceTileEntities);
|
||||||
|
|
||||||
if (playButton.isHovered() && playButton.active)
|
if (playButton.isHovered() && playButton.active)
|
||||||
sendOptionUpdate(Option.PLAY, true);
|
sendOptionUpdate(Option.PLAY, true);
|
||||||
|
|
|
@ -31,6 +31,7 @@ import net.minecraft.world.World;
|
||||||
import net.minecraft.world.gen.feature.template.PlacementSettings;
|
import net.minecraft.world.gen.feature.template.PlacementSettings;
|
||||||
import net.minecraft.world.gen.feature.template.Template;
|
import net.minecraft.world.gen.feature.template.Template;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
import net.minecraftforge.fml.DistExecutor;
|
import net.minecraftforge.fml.DistExecutor;
|
||||||
import net.minecraftforge.fml.common.thread.SidedThreadGroups;
|
import net.minecraftforge.fml.common.thread.SidedThreadGroups;
|
||||||
|
|
||||||
|
@ -95,7 +96,7 @@ public class ItemBlueprint extends Item {
|
||||||
t.read(nbt);
|
t.read(nbt);
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
// Player/Server doesnt have schematic saved
|
||||||
} finally {
|
} finally {
|
||||||
if (stream != null)
|
if (stream != null)
|
||||||
IOUtils.closeQuietly(stream);
|
IOUtils.closeQuietly(stream);
|
||||||
|
@ -108,7 +109,7 @@ public class ItemBlueprint extends Item {
|
||||||
public ActionResultType onItemUse(ItemUseContext context) {
|
public ActionResultType onItemUse(ItemUseContext context) {
|
||||||
if (context.isPlacerSneaking() && context.getHand() == Hand.MAIN_HAND) {
|
if (context.isPlacerSneaking() && context.getHand() == Hand.MAIN_HAND) {
|
||||||
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
|
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
|
||||||
GuiOpener.open(new BlueprintEditScreen());
|
displayBlueprintScreen();
|
||||||
});
|
});
|
||||||
return ActionResultType.SUCCESS;
|
return ActionResultType.SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -116,11 +117,16 @@ public class ItemBlueprint extends Item {
|
||||||
return super.onItemUse(context);
|
return super.onItemUse(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OnlyIn(value = Dist.CLIENT)
|
||||||
|
protected void displayBlueprintScreen() {
|
||||||
|
GuiOpener.open(new BlueprintEditScreen());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {
|
public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {
|
||||||
if (playerIn.isSneaking() && handIn == Hand.MAIN_HAND) {
|
if (playerIn.isSneaking() && handIn == Hand.MAIN_HAND) {
|
||||||
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
|
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
|
||||||
GuiOpener.open(new BlueprintEditScreen());
|
displayBlueprintScreen();
|
||||||
});
|
});
|
||||||
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, playerIn.getHeldItem(handIn));
|
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, playerIn.getHeldItem(handIn));
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ import net.minecraftforge.fml.network.NetworkEvent.Context;
|
||||||
public class PacketConfigureSchematicannon {
|
public class PacketConfigureSchematicannon {
|
||||||
|
|
||||||
public static enum Option {
|
public static enum Option {
|
||||||
DONT_REPLACE, REPLACE_SOLID, REPLACE_ANY, REPLACE_EMPTY, SKIP_MISSING, PLAY, PAUSE, STOP;
|
DONT_REPLACE, REPLACE_SOLID, REPLACE_ANY, REPLACE_EMPTY, SKIP_MISSING, SKIP_TILES, PLAY, PAUSE, STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Option option;
|
private Option option;
|
||||||
|
@ -66,6 +66,9 @@ public class PacketConfigureSchematicannon {
|
||||||
case SKIP_MISSING:
|
case SKIP_MISSING:
|
||||||
te.skipMissing = set;
|
te.skipMissing = set;
|
||||||
break;
|
break;
|
||||||
|
case SKIP_TILES:
|
||||||
|
te.replaceTileEntities = set;
|
||||||
|
break;
|
||||||
|
|
||||||
case PLAY:
|
case PLAY:
|
||||||
te.state = State.RUNNING;
|
te.state = State.RUNNING;
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
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.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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -18,6 +18,7 @@ public class PacketSchematicUpload {
|
||||||
public static final int FINISH = 2;
|
public static final int FINISH = 2;
|
||||||
|
|
||||||
private int code;
|
private int code;
|
||||||
|
private long size;
|
||||||
private String schematic;
|
private String schematic;
|
||||||
private byte[] data;
|
private byte[] data;
|
||||||
|
|
||||||
|
@ -26,8 +27,9 @@ public class PacketSchematicUpload {
|
||||||
this.schematic = schematic;
|
this.schematic = schematic;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PacketSchematicUpload begin(String schematic) {
|
public static PacketSchematicUpload begin(String schematic, long size) {
|
||||||
PacketSchematicUpload pkt = new PacketSchematicUpload(BEGIN, schematic);
|
PacketSchematicUpload pkt = new PacketSchematicUpload(BEGIN, schematic);
|
||||||
|
pkt.size = size;
|
||||||
return pkt;
|
return pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +47,8 @@ public class PacketSchematicUpload {
|
||||||
code = buffer.readInt();
|
code = buffer.readInt();
|
||||||
schematic = buffer.readString(256);
|
schematic = buffer.readString(256);
|
||||||
|
|
||||||
|
if (code == BEGIN)
|
||||||
|
size = buffer.readLong();
|
||||||
if (code == WRITE)
|
if (code == WRITE)
|
||||||
data = buffer.readByteArray();
|
data = buffer.readByteArray();
|
||||||
}
|
}
|
||||||
|
@ -53,6 +57,8 @@ public class PacketSchematicUpload {
|
||||||
buffer.writeInt(code);
|
buffer.writeInt(code);
|
||||||
buffer.writeString(schematic);
|
buffer.writeString(schematic);
|
||||||
|
|
||||||
|
if (code == BEGIN)
|
||||||
|
buffer.writeLong(size);
|
||||||
if (code == WRITE)
|
if (code == WRITE)
|
||||||
buffer.writeByteArray(data);
|
buffer.writeByteArray(data);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +68,7 @@ public class PacketSchematicUpload {
|
||||||
ServerPlayerEntity player = context.get().getSender();
|
ServerPlayerEntity player = context.get().getSender();
|
||||||
if (code == BEGIN) {
|
if (code == BEGIN) {
|
||||||
BlockPos pos = ((SchematicTableContainer) player.openContainer).getTileEntity().getPos();
|
BlockPos pos = ((SchematicTableContainer) player.openContainer).getTileEntity().getPos();
|
||||||
Create.sSchematicLoader.handleNewUpload(player, schematic, new DimensionPos(player, pos));
|
Create.sSchematicLoader.handleNewUpload(player, schematic, size, new DimensionPos(player, pos));
|
||||||
}
|
}
|
||||||
if (code == WRITE) {
|
if (code == WRITE) {
|
||||||
Create.sSchematicLoader.handleWriteRequest(player, schematic, data);
|
Create.sSchematicLoader.handleWriteRequest(player, schematic, data);
|
||||||
|
|
|
@ -21,8 +21,6 @@ public class Packets {
|
||||||
channel.registerMessage(i++, PacketNbt.class, PacketNbt::toBytes, PacketNbt::new, PacketNbt::handle);
|
channel.registerMessage(i++, PacketNbt.class, PacketNbt::toBytes, PacketNbt::new, PacketNbt::handle);
|
||||||
channel.registerMessage(i++, PacketConfigureSchematicannon.class, PacketConfigureSchematicannon::toBytes,
|
channel.registerMessage(i++, PacketConfigureSchematicannon.class, PacketConfigureSchematicannon::toBytes,
|
||||||
PacketConfigureSchematicannon::new, PacketConfigureSchematicannon::handle);
|
PacketConfigureSchematicannon::new, PacketConfigureSchematicannon::handle);
|
||||||
channel.registerMessage(i++, PacketSchematicTableContainer.class, PacketSchematicTableContainer::toBytes,
|
|
||||||
PacketSchematicTableContainer::new, PacketSchematicTableContainer::handle);
|
|
||||||
channel.registerMessage(i++, PacketSchematicUpload.class, PacketSchematicUpload::toBytes,
|
channel.registerMessage(i++, PacketSchematicUpload.class, PacketSchematicUpload::toBytes,
|
||||||
PacketSchematicUpload::new, PacketSchematicUpload::handle);
|
PacketSchematicUpload::new, PacketSchematicUpload::handle);
|
||||||
channel.registerMessage(i++, PacketSymmetryEffect.class, PacketSymmetryEffect::toBytes,
|
channel.registerMessage(i++, PacketSymmetryEffect.class, PacketSymmetryEffect::toBytes,
|
||||||
|
|
|
@ -29,6 +29,7 @@ import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.text.StringTextComponent;
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
import net.minecraft.world.gen.feature.template.PlacementSettings;
|
import net.minecraft.world.gen.feature.template.PlacementSettings;
|
||||||
import net.minecraft.world.gen.feature.template.Template;
|
import net.minecraft.world.gen.feature.template.Template;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.client.event.InputEvent.KeyInputEvent;
|
import net.minecraftforge.client.event.InputEvent.KeyInputEvent;
|
||||||
import net.minecraftforge.client.event.InputEvent.MouseInputEvent;
|
import net.minecraftforge.client.event.InputEvent.MouseInputEvent;
|
||||||
import net.minecraftforge.client.event.RenderGameOverlayEvent;
|
import net.minecraftforge.client.event.RenderGameOverlayEvent;
|
||||||
|
@ -38,7 +39,7 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
|
||||||
import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent;
|
import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent;
|
||||||
|
|
||||||
@EventBusSubscriber(bus = Bus.FORGE)
|
@EventBusSubscriber(value = Dist.CLIENT, bus = Bus.FORGE)
|
||||||
public class BlueprintHandler {
|
public class BlueprintHandler {
|
||||||
|
|
||||||
public static BlueprintHandler instance;
|
public static BlueprintHandler instance;
|
||||||
|
@ -227,11 +228,15 @@ public class BlueprintHandler {
|
||||||
Packets.channel.sendToServer(new PacketNbt(item, slot));
|
Packets.channel.sendToServer(new PacketNbt(item, slot));
|
||||||
|
|
||||||
if (deployed) {
|
if (deployed) {
|
||||||
|
Template schematic = ItemBlueprint.getSchematic(item);
|
||||||
|
|
||||||
|
if (schematic.getSize().equals(BlockPos.ZERO))
|
||||||
|
return;
|
||||||
|
|
||||||
SchematicWorld w = new SchematicWorld(new HashMap<>(), new Cuboid(), anchor);
|
SchematicWorld w = new SchematicWorld(new HashMap<>(), new Cuboid(), anchor);
|
||||||
PlacementSettings settings = cachedSettings.copy();
|
PlacementSettings settings = cachedSettings.copy();
|
||||||
settings.setBoundingBox(null);
|
settings.setBoundingBox(null);
|
||||||
ItemBlueprint.getSchematic(item).addBlocksToWorld(w, anchor, settings);
|
schematic.addBlocksToWorld(w, anchor, settings);
|
||||||
|
|
||||||
new SchematicHologram().startHologram(w);
|
new SchematicHologram().startHologram(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
package com.simibubi.create.schematic;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.ListNBT;
|
||||||
|
import net.minecraft.nbt.StringNBT;
|
||||||
|
import net.minecraft.util.text.ITextComponent;
|
||||||
|
import net.minecraft.util.text.TextFormatting;
|
||||||
|
import net.minecraft.util.text.TranslationTextComponent;
|
||||||
|
|
||||||
|
public class MaterialChecklist {
|
||||||
|
|
||||||
|
public Map<Item, Integer> gathered;
|
||||||
|
public Map<Item, Integer> required;
|
||||||
|
public boolean blocksNotLoaded;
|
||||||
|
|
||||||
|
public MaterialChecklist() {
|
||||||
|
required = new HashMap<>();
|
||||||
|
gathered = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void warnBlockNotLoaded() {
|
||||||
|
blocksNotLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void require(Item item) {
|
||||||
|
if (required.containsKey(item))
|
||||||
|
required.put(item, required.get(item) + 1);
|
||||||
|
else
|
||||||
|
required.put(item, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void collect(ItemStack stack) {
|
||||||
|
Item item = stack.getItem();
|
||||||
|
if (required.containsKey(item))
|
||||||
|
if (gathered.containsKey(item))
|
||||||
|
gathered.put(item, gathered.get(item) + stack.getCount());
|
||||||
|
else
|
||||||
|
gathered.put(item, stack.getCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack createItem() {
|
||||||
|
ItemStack book = new ItemStack(Items.WRITTEN_BOOK);
|
||||||
|
|
||||||
|
CompoundNBT tag = book.getOrCreateTag();
|
||||||
|
ListNBT pages = new ListNBT();
|
||||||
|
|
||||||
|
int itemsWritten = 0;
|
||||||
|
StringBuilder string = new StringBuilder("{\"text\":\"");
|
||||||
|
|
||||||
|
if (blocksNotLoaded) {
|
||||||
|
string.append("\n" + TextFormatting.RED + "* Disclaimer *\n\n");
|
||||||
|
string.append("Material List may be inaccurate due to relevant chunks not being loaded.");
|
||||||
|
string.append("\"}");
|
||||||
|
pages.add(new StringNBT(string.toString()));
|
||||||
|
string = new StringBuilder("{\"text\":\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Item> keys = new ArrayList<>(required.keySet());
|
||||||
|
Collections.sort(keys, (item1, item2) -> {
|
||||||
|
String name1 = new TranslationTextComponent(((Item) item1).getTranslationKey()).getFormattedText().toLowerCase();
|
||||||
|
String name2 = new TranslationTextComponent(((Item) item2).getTranslationKey()).getFormattedText().toLowerCase();
|
||||||
|
return name1.compareTo(name2);
|
||||||
|
});
|
||||||
|
|
||||||
|
List<Item> completed = new ArrayList<>();
|
||||||
|
for (Item item : keys) {
|
||||||
|
int amount = required.get(item);
|
||||||
|
if (gathered.containsKey(item))
|
||||||
|
amount -= gathered.get(item);
|
||||||
|
|
||||||
|
if (amount <= 0) {
|
||||||
|
completed.add(item);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemsWritten == 6) {
|
||||||
|
itemsWritten = 0;
|
||||||
|
string.append("\"}");
|
||||||
|
pages.add(new StringNBT(string.toString()));
|
||||||
|
string = new StringBuilder("{\"text\":\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
itemsWritten++;
|
||||||
|
string.append(unfinishedEntry(new ItemStack(item), amount));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Item item : completed) {
|
||||||
|
if (itemsWritten == 6) {
|
||||||
|
itemsWritten = 0;
|
||||||
|
string.append("\"}");
|
||||||
|
pages.add(new StringNBT(string.toString()));
|
||||||
|
string = new StringBuilder("{\"text\":\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
itemsWritten++;
|
||||||
|
string.append(gatheredEntry(new ItemStack(item), required.get(item)));
|
||||||
|
}
|
||||||
|
|
||||||
|
string.append("\"}");
|
||||||
|
pages.add(new StringNBT(string.toString()));
|
||||||
|
|
||||||
|
tag.put("pages", pages);
|
||||||
|
tag.putString("author", "Schematicannon");
|
||||||
|
tag.putString("title", TextFormatting.BLUE + "Material Checklist");
|
||||||
|
book.setTag(tag);
|
||||||
|
|
||||||
|
return book;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String gatheredEntry(ItemStack item, int amount) {
|
||||||
|
int stacks = amount / 64;
|
||||||
|
int remainder = amount % 64;
|
||||||
|
ITextComponent tc = new TranslationTextComponent(item.getTranslationKey());
|
||||||
|
return TextFormatting.DARK_GREEN + tc.getFormattedText()
|
||||||
|
+ " \\u2714\n x" + amount + TextFormatting.GRAY + " | " + stacks + "\\u25A4 +" + remainder + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String unfinishedEntry(ItemStack item, int amount) {
|
||||||
|
int stacks = amount / 64;
|
||||||
|
int remainder = amount % 64;
|
||||||
|
ITextComponent tc = new TranslationTextComponent(item.getTranslationKey());
|
||||||
|
return TextFormatting.BLUE + tc.getFormattedText() + "\n x" + amount
|
||||||
|
+ TextFormatting.GRAY + " | " + stacks + "\\u25A4 +" + remainder + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.3 KiB |
Loading…
Reference in a new issue