mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-16 23:23:41 +01:00
Merge pull request #965 from Snownee/mc1.15/security-patches
Security patches
This commit is contained in:
commit
bed5a1d03a
22 changed files with 342 additions and 190 deletions
|
@ -23,6 +23,7 @@
|
|||
"create:redstone_link",
|
||||
"create:analog_lever",
|
||||
"create:adjustable_repeater",
|
||||
"create:adjustable_pulse_repeater"
|
||||
"create:adjustable_pulse_repeater",
|
||||
"#minecraft:signs"
|
||||
]
|
||||
}
|
|
@ -187,5 +187,7 @@ public class AllTags {
|
|||
AllBlockTags.FAN_TRANSPARENT.add(Blocks.IRON_BARS);
|
||||
|
||||
AllBlockTags.FAN_HEATERS.add(Blocks.MAGMA_BLOCK, Blocks.CAMPFIRE, Blocks.LAVA, Blocks.FIRE);
|
||||
|
||||
AllBlockTags.SAFE_NBT.includeAll(BlockTags.SIGNS);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.util.stream.Collectors;
|
|||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.compat.jei.category.animations.AnimatedCrafter;
|
||||
import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics;
|
||||
import com.simibubi.create.foundation.gui.AllGuiTextures;
|
||||
|
||||
import mezz.jei.api.constants.VanillaTypes;
|
||||
|
|
|
@ -52,6 +52,7 @@ import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
|
|||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
import com.simibubi.create.foundation.utility.NBTProcessors;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
|
||||
|
||||
|
@ -885,6 +886,8 @@ public abstract class Contraption {
|
|||
|
||||
TileEntity tileEntity = world.getTileEntity(targetPos);
|
||||
CompoundNBT tag = block.nbt;
|
||||
if (tileEntity != null)
|
||||
tag = NBTProcessors.process(tileEntity, tag, false);
|
||||
if (tileEntity != null && tag != null) {
|
||||
tag.putInt("x", targetPos.getX());
|
||||
tag.putInt("y", targetPos.getY());
|
||||
|
@ -915,9 +918,10 @@ public abstract class Contraption {
|
|||
}
|
||||
}
|
||||
for (BlockInfo block : blocks.values()) {
|
||||
BlockPos targetPos = transform.apply(block.pos);
|
||||
if (!shouldUpdateAfterMovement(block))
|
||||
continue;
|
||||
BlockPos targetPos = transform.apply(block.pos);
|
||||
BlockState state = world.getBlockState(targetPos);
|
||||
world.markAndNotifyBlock(targetPos, null, block.state, block.state,
|
||||
BlockFlags.IS_MOVING | BlockFlags.DEFAULT);
|
||||
}
|
||||
|
@ -1051,4 +1055,4 @@ public abstract class Contraption {
|
|||
mountedFluidStorage.updateFluid(containedFluid);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Abs
|
|||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.Direction;
|
||||
|
@ -45,22 +46,26 @@ public class ContraptionInteractionPacket extends SimplePacketBase {
|
|||
|
||||
@Override
|
||||
public void handle(Supplier<Context> context) {
|
||||
context.get()
|
||||
.enqueueWork(() -> {
|
||||
ServerPlayerEntity sender = context.get()
|
||||
.getSender();
|
||||
if (sender == null)
|
||||
return;
|
||||
Entity entityByID = sender.getServerWorld()
|
||||
.getEntityByID(target);
|
||||
if (!(entityByID instanceof AbstractContraptionEntity))
|
||||
return;
|
||||
AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID;
|
||||
if (contraptionEntity.handlePlayerInteraction(sender, localPos, face, interactionHand))
|
||||
sender.swingHand(interactionHand, true);
|
||||
});
|
||||
context.get()
|
||||
.setPacketHandled(true);
|
||||
context.get().enqueueWork(() -> {
|
||||
ServerPlayerEntity sender = context.get().getSender();
|
||||
if (sender == null)
|
||||
return;
|
||||
Entity entityByID = sender.getServerWorld().getEntityByID(target);
|
||||
if (!(entityByID instanceof AbstractContraptionEntity))
|
||||
return;
|
||||
AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID;
|
||||
double d = sender.getAttribute(PlayerEntity.REACH_DISTANCE).getValue();
|
||||
if (!sender.canEntityBeSeen(entityByID))
|
||||
d -= 3;
|
||||
d *= d;
|
||||
if (sender.getDistanceSq(entityByID) > d) {
|
||||
// TODO log?
|
||||
return;
|
||||
}
|
||||
if (contraptionEntity.handlePlayerInteraction(sender, localPos, face, interactionHand))
|
||||
sender.swingHand(interactionHand, true);
|
||||
});
|
||||
context.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,9 +21,7 @@ import com.simibubi.create.foundation.utility.VecHelper;
|
|||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.PotionItem;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.particles.BlockParticleData;
|
||||
import net.minecraft.particles.IParticleData;
|
||||
import net.minecraft.particles.ParticleTypes;
|
||||
import net.minecraft.potion.PotionUtils;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.Direction;
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.util.function.Supplier;
|
|||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.Hand;
|
||||
|
@ -53,25 +54,29 @@ public class ExtendoGripInteractionPacket extends SimplePacketBase {
|
|||
|
||||
@Override
|
||||
public void handle(Supplier<Context> context) {
|
||||
context.get()
|
||||
.enqueueWork(() -> {
|
||||
ServerPlayerEntity sender = context.get()
|
||||
.getSender();
|
||||
if (sender == null)
|
||||
context.get().enqueueWork(() -> {
|
||||
ServerPlayerEntity sender = context.get().getSender();
|
||||
if (sender == null)
|
||||
return;
|
||||
Entity entityByID = sender.getServerWorld().getEntityByID(target);
|
||||
if (entityByID != null && ExtendoGripItem.isHoldingExtendoGrip(sender)) {
|
||||
double d = sender.getAttribute(PlayerEntity.REACH_DISTANCE).getValue();
|
||||
if (!sender.canEntityBeSeen(entityByID))
|
||||
d -= 3;
|
||||
d *= d;
|
||||
if (sender.getDistanceSq(entityByID) > d) {
|
||||
// TODO log?
|
||||
return;
|
||||
Entity entityByID = sender.getServerWorld()
|
||||
.getEntityByID(target);
|
||||
if (entityByID != null && ExtendoGripItem.isHoldingExtendoGrip(sender)) {
|
||||
if (interactionHand == null)
|
||||
sender.attackTargetEntityWithCurrentItem(entityByID);
|
||||
else if (specificPoint == null)
|
||||
sender.interactOn(entityByID, interactionHand);
|
||||
else
|
||||
entityByID.applyPlayerInteraction(sender, specificPoint, interactionHand);
|
||||
}
|
||||
});
|
||||
context.get()
|
||||
.setPacketHandled(true);
|
||||
if (interactionHand == null)
|
||||
sender.attackTargetEntityWithCurrentItem(entityByID);
|
||||
else if (specificPoint == null)
|
||||
sender.interactOn(entityByID, interactionHand);
|
||||
else
|
||||
entityByID.applyPlayerInteraction(sender, specificPoint, interactionHand);
|
||||
}
|
||||
});
|
||||
context.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.simibubi.create.foundation.item.ItemDescription;
|
|||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.NBTProcessors;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
|
@ -115,7 +116,7 @@ public abstract class ZapperItem extends Item {
|
|||
});
|
||||
applyCooldown(player, item, false);
|
||||
}
|
||||
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item);
|
||||
return new ActionResult<>(ActionResultType.SUCCESS, item);
|
||||
}
|
||||
|
||||
boolean mainHand = hand == Hand.MAIN_HAND;
|
||||
|
@ -125,7 +126,7 @@ public abstract class ZapperItem extends Item {
|
|||
|
||||
// Pass To Offhand
|
||||
if (mainHand && isSwap && gunInOtherHand)
|
||||
return new ActionResult<ItemStack>(ActionResultType.FAIL, item);
|
||||
return new ActionResult<>(ActionResultType.FAIL, item);
|
||||
if (mainHand && !isSwap && gunInOtherHand)
|
||||
item.getTag()
|
||||
.putBoolean("_Swap", true);
|
||||
|
@ -144,7 +145,7 @@ public abstract class ZapperItem extends Item {
|
|||
world.playSound(player, player.getPosition(), AllSoundEvents.BLOCKZAPPER_DENY.get(), SoundCategory.BLOCKS,
|
||||
1f, 0.5f);
|
||||
player.sendStatusMessage(msg.applyTextStyle(TextFormatting.RED), true);
|
||||
return new ActionResult<ItemStack>(ActionResultType.FAIL, item);
|
||||
return new ActionResult<>(ActionResultType.FAIL, item);
|
||||
}
|
||||
|
||||
BlockState stateToUse = Blocks.AIR.getDefaultState();
|
||||
|
@ -169,7 +170,7 @@ public abstract class ZapperItem extends Item {
|
|||
// No target
|
||||
if (pos == null || stateReplaced.getBlock() == Blocks.AIR) {
|
||||
applyCooldown(player, item, gunInOtherHand);
|
||||
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item);
|
||||
return new ActionResult<>(ActionResultType.SUCCESS, item);
|
||||
}
|
||||
|
||||
// Find exact position of gun barrel for VFX
|
||||
|
@ -183,7 +184,7 @@ public abstract class ZapperItem extends Item {
|
|||
// Client side
|
||||
if (world.isRemote) {
|
||||
ZapperRenderHandler.dontAnimateItem(hand);
|
||||
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item);
|
||||
return new ActionResult<>(ActionResultType.SUCCESS, item);
|
||||
}
|
||||
|
||||
// Server side
|
||||
|
@ -195,7 +196,7 @@ public abstract class ZapperItem extends Item {
|
|||
new ZapperBeamPacket(barrelPos, raytrace.getHitVec(), hand, true));
|
||||
}
|
||||
|
||||
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item);
|
||||
return new ActionResult<>(ActionResultType.SUCCESS, item);
|
||||
}
|
||||
|
||||
public ITextComponent validateUsage(ItemStack item) {
|
||||
|
@ -240,10 +241,13 @@ public abstract class ZapperItem extends Item {
|
|||
return UseAction.NONE;
|
||||
}
|
||||
|
||||
public static void setTileData(World world, BlockPos pos, CompoundNBT data) {
|
||||
if (data != null) {
|
||||
public static void setTileData(World world, BlockPos pos, BlockState state, CompoundNBT data, PlayerEntity player) {
|
||||
if (data != null && AllBlockTags.SAFE_NBT.matches(state)) {
|
||||
TileEntity tile = world.getTileEntity(pos);
|
||||
if (tile != null && !tile.onlyOpsCanSetNbt()) {
|
||||
if (tile != null) {
|
||||
data = NBTProcessors.process(tile, data, !player.isCreative());
|
||||
if (data == null)
|
||||
return;
|
||||
data.putInt("x", pos.getX());
|
||||
data.putInt("y", pos.getY());
|
||||
data.putInt("z", pos.getZ());
|
||||
|
|
|
@ -135,7 +135,7 @@ public class BlockzapperItem extends ZapperItem {
|
|||
blocksnapshot.restore(true, false);
|
||||
return false;
|
||||
}
|
||||
setTileData(world, placed, data);
|
||||
setTileData(world, placed, state, data, player);
|
||||
|
||||
if (player instanceof ServerPlayerEntity && world instanceof ServerWorld) {
|
||||
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player;
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.simibubi.create.foundation.utility.Lang;
|
|||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
@ -36,7 +37,7 @@ public enum TerrainTools {
|
|||
return this != Clear && this != Flatten;
|
||||
}
|
||||
|
||||
public void run(World world, List<BlockPos> targetPositions, Direction facing, @Nullable BlockState paintedState, @Nullable CompoundNBT data) {
|
||||
public void run(World world, List<BlockPos> targetPositions, Direction facing, @Nullable BlockState paintedState, @Nullable CompoundNBT data, PlayerEntity player) {
|
||||
switch (this) {
|
||||
case Clear:
|
||||
targetPositions.forEach(p -> world.setBlockState(p, Blocks.AIR.getDefaultState()));
|
||||
|
@ -47,7 +48,7 @@ public enum TerrainTools {
|
|||
if (!isReplaceable(toReplace))
|
||||
return;
|
||||
world.setBlockState(p, paintedState);
|
||||
ZapperItem.setTileData(world, p, data);
|
||||
ZapperItem.setTileData(world, p, paintedState, data, player);
|
||||
});
|
||||
break;
|
||||
case Flatten:
|
||||
|
@ -67,13 +68,13 @@ public enum TerrainTools {
|
|||
if (!isReplaceable(toReplace))
|
||||
return;
|
||||
world.setBlockState(p, paintedState);
|
||||
ZapperItem.setTileData(world, p, data);
|
||||
ZapperItem.setTileData(world, p, paintedState, data, player);
|
||||
});
|
||||
break;
|
||||
case Place:
|
||||
targetPositions.forEach(p -> {
|
||||
world.setBlockState(p, paintedState);
|
||||
ZapperItem.setTileData(world, p, data);
|
||||
ZapperItem.setTileData(world, p, paintedState, data, player);
|
||||
});
|
||||
break;
|
||||
case Replace:
|
||||
|
@ -82,7 +83,7 @@ public enum TerrainTools {
|
|||
if (isReplaceable(toReplace))
|
||||
return;
|
||||
world.setBlockState(p, paintedState);
|
||||
ZapperItem.setTileData(world, p, data);
|
||||
ZapperItem.setTileData(world, p, paintedState, data, player);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ public class WorldshaperItem extends ZapperItem {
|
|||
for (BlockPos blockPos : brush.getIncludedPositions())
|
||||
affectedPositions.add(targetPos.add(blockPos));
|
||||
PlacementPatterns.applyPattern(affectedPositions, stack);
|
||||
tool.run(world, affectedPositions, raytrace.getFace(), stateToUse, data);
|
||||
tool.run(world, affectedPositions, raytrace.getFace(), stateToUse, data, player);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.simibubi.create.content.logistics.block.redstone;
|
|||
|
||||
import com.simibubi.create.AllShapes;
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
import com.simibubi.create.content.logistics.block.funnel.FunnelBlock;
|
||||
import com.simibubi.create.foundation.block.ITE;
|
||||
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package com.simibubi.create.content.schematics;
|
||||
|
||||
import com.mojang.datafixers.Dynamic;
|
||||
import com.mojang.datafixers.types.DynamicOps;
|
||||
import com.simibubi.create.foundation.utility.NBTProcessors;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IWorldReader;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.feature.template.IStructureProcessorType;
|
||||
import net.minecraft.world.gen.feature.template.PlacementSettings;
|
||||
import net.minecraft.world.gen.feature.template.StructureProcessor;
|
||||
import net.minecraft.world.gen.feature.template.Template;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Optional;
|
||||
|
||||
public class SchematicProcessor extends StructureProcessor {
|
||||
public static final SchematicProcessor INSTANCE = new SchematicProcessor();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Template.BlockInfo process(IWorldReader world, BlockPos pos, Template.BlockInfo rawInfo,
|
||||
Template.BlockInfo info, PlacementSettings settings, @Nullable Template template) {
|
||||
if (info.nbt != null) {
|
||||
TileEntity te = info.state.createTileEntity(world);
|
||||
if (te != null) {
|
||||
CompoundNBT nbt = NBTProcessors.process(te, info.nbt, false);
|
||||
if (nbt != info.nbt)
|
||||
return new Template.BlockInfo(info.pos, info.state, nbt);
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Template.EntityInfo processEntity(IWorldReader world, BlockPos pos, Template.EntityInfo rawInfo,
|
||||
Template.EntityInfo info, PlacementSettings settings, Template template) {
|
||||
return EntityType.readEntityType(info.nbt).flatMap(type -> {
|
||||
if (world instanceof World) {
|
||||
Entity e = type.create((World) world);
|
||||
if (e != null && !e.ignoreItemEntityData()) {
|
||||
return Optional.of(info);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IStructureProcessorType getType() {
|
||||
return dynamic -> INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> Dynamic<T> serialize0(DynamicOps<T> ops) {
|
||||
return new Dynamic<>(ops, ops.emptyMap());
|
||||
}
|
||||
}
|
|
@ -5,7 +5,6 @@ import java.io.OutputStream;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -14,8 +13,6 @@ import java.util.Optional;
|
|||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.Create;
|
||||
|
@ -91,10 +88,8 @@ public class ServerSchematicLoader {
|
|||
}
|
||||
|
||||
public void handleNewUpload(ServerPlayerEntity player, String schematic, long size, BlockPos pos) {
|
||||
String playerPath = getSchematicPath() + "/" + player.getName()
|
||||
.getFormattedText();
|
||||
String playerSchematicId = player.getName()
|
||||
.getFormattedText() + "/" + schematic;
|
||||
String playerPath = getSchematicPath() + "/" + player.getGameProfile().getName();
|
||||
String playerSchematicId = player.getGameProfile().getName() + "/" + schematic;
|
||||
FilesHelper.createFolderIfMissing(playerPath);
|
||||
|
||||
// Unsupported Format
|
||||
|
@ -103,6 +98,14 @@ public class ServerSchematicLoader {
|
|||
return;
|
||||
}
|
||||
|
||||
Path playerSchematicsPath = Paths.get(getSchematicPath(), player.getGameProfile().getName()).toAbsolutePath();
|
||||
|
||||
Path uploadPath = playerSchematicsPath.resolve(schematic).normalize();
|
||||
if (!uploadPath.startsWith(playerSchematicsPath)) {
|
||||
Create.logger.warn("Attempted Schematic Upload with directory escape: {}", playerSchematicId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Too big
|
||||
if (!validateSchematicSizeOnServer(player, size))
|
||||
return;
|
||||
|
@ -118,11 +121,15 @@ public class ServerSchematicLoader {
|
|||
return;
|
||||
|
||||
// Delete schematic with same name
|
||||
Files.deleteIfExists(Paths.get(getSchematicPath(), playerSchematicId));
|
||||
Files.deleteIfExists(uploadPath);
|
||||
|
||||
// Too many Schematics
|
||||
Stream<Path> list = Files.list(Paths.get(playerPath));
|
||||
if (list.count() >= getConfig().maxSchematics.get()) {
|
||||
long count;
|
||||
try (Stream<Path> list = Files.list(Paths.get(playerPath))) {
|
||||
count = list.count();
|
||||
}
|
||||
|
||||
if (count >= getConfig().maxSchematics.get()) {
|
||||
Stream<Path> list2 = Files.list(Paths.get(playerPath));
|
||||
Optional<Path> lastFilePath = list2.filter(f -> !Files.isDirectory(f))
|
||||
.min(Comparator.comparingLong(f -> f.toFile()
|
||||
|
@ -132,11 +139,9 @@ public class ServerSchematicLoader {
|
|||
Files.deleteIfExists(lastFilePath.get());
|
||||
}
|
||||
}
|
||||
list.close();
|
||||
|
||||
// Open Stream
|
||||
OutputStream writer =
|
||||
Files.newOutputStream(Paths.get(getSchematicPath(), playerSchematicId), StandardOpenOption.CREATE_NEW);
|
||||
OutputStream writer = Files.newOutputStream(uploadPath);
|
||||
activeUploads.put(playerSchematicId, new SchematicUploadEntry(writer, size, player.getServerWorld(), pos));
|
||||
|
||||
// Notify Tile Entity
|
||||
|
@ -165,8 +170,7 @@ public class ServerSchematicLoader {
|
|||
}
|
||||
|
||||
public void handleWriteRequest(ServerPlayerEntity player, String schematic, byte[] data) {
|
||||
String playerSchematicId = player.getName()
|
||||
.getFormattedText() + "/" + schematic;
|
||||
String playerSchematicId = player.getGameProfile().getName() + "/" + schematic;
|
||||
|
||||
if (activeUploads.containsKey(playerSchematicId)) {
|
||||
SchematicUploadEntry entry = activeUploads.get(playerSchematicId);
|
||||
|
@ -236,8 +240,7 @@ public class ServerSchematicLoader {
|
|||
}
|
||||
|
||||
public void handleFinishedUpload(ServerPlayerEntity player, String schematic) {
|
||||
String playerSchematicId = player.getName()
|
||||
.getFormattedText() + "/" + schematic;
|
||||
String playerSchematicId = player.getGameProfile().getName() + "/" + schematic;
|
||||
|
||||
if (activeUploads.containsKey(playerSchematicId)) {
|
||||
try {
|
||||
|
@ -258,8 +261,7 @@ public class ServerSchematicLoader {
|
|||
if (table == null)
|
||||
return;
|
||||
table.finishUpload();
|
||||
table.inventory.setStackInSlot(1, SchematicItem.create(schematic, player.getName()
|
||||
.getFormattedText()));
|
||||
table.inventory.setStackInSlot(1, SchematicItem.create(schematic, player.getGameProfile().getName()));
|
||||
|
||||
} catch (IOException e) {
|
||||
Create.logger.error("Exception Thrown when finishing Upload: " + playerSchematicId);
|
||||
|
@ -270,15 +272,21 @@ public class ServerSchematicLoader {
|
|||
|
||||
public void handleInstantSchematic(ServerPlayerEntity player, String schematic, World world, BlockPos pos,
|
||||
BlockPos bounds) {
|
||||
String playerPath = getSchematicPath() + "/" + player.getName()
|
||||
.getFormattedText();
|
||||
String playerSchematicId = player.getName()
|
||||
.getFormattedText() + "/" + schematic;
|
||||
String playerPath = getSchematicPath() + "/" + player.getGameProfile().getName();
|
||||
String playerSchematicId = player.getGameProfile().getName() + "/" + schematic;
|
||||
FilesHelper.createFolderIfMissing(playerPath);
|
||||
|
||||
// Unsupported Format
|
||||
if (!schematic.endsWith(".nbt")) {
|
||||
Create.logger.warn("Attempted Schematic Upload with non-supported Format: " + playerSchematicId);
|
||||
Create.logger.warn("Attempted Schematic Upload with non-supported Format: {}", playerSchematicId);
|
||||
return;
|
||||
}
|
||||
|
||||
Path schematicPath = Paths.get(getSchematicPath()).toAbsolutePath();
|
||||
|
||||
Path path = schematicPath.resolve(playerSchematicId).normalize();
|
||||
if (!path.startsWith(schematicPath)) {
|
||||
Create.logger.warn("Attempted Schematic Upload with directory escape: {}", playerSchematicId);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -288,38 +296,34 @@ public class ServerSchematicLoader {
|
|||
|
||||
try {
|
||||
// Delete schematic with same name
|
||||
Path path = Paths.get(getSchematicPath(), playerSchematicId);
|
||||
Files.deleteIfExists(path);
|
||||
|
||||
// Too many Schematics
|
||||
Stream<Path> list = Files.list(Paths.get(playerPath));
|
||||
if (list.count() >= getConfig().maxSchematics.get()) {
|
||||
long count;
|
||||
try (Stream<Path> list = Files.list(Paths.get(playerPath))) {
|
||||
count = list.count();
|
||||
}
|
||||
|
||||
if (count >= getConfig().maxSchematics.get()) {
|
||||
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())
|
||||
if (lastFilePath.isPresent())
|
||||
Files.deleteIfExists(lastFilePath.get());
|
||||
}
|
||||
list.close();
|
||||
|
||||
Template t = new Template();
|
||||
t.takeBlocksFromWorld(world, pos, bounds, true, Blocks.AIR);
|
||||
|
||||
OutputStream outputStream = null;
|
||||
try {
|
||||
outputStream = Files.newOutputStream(path, StandardOpenOption.CREATE);
|
||||
try (OutputStream outputStream = Files.newOutputStream(path)) {
|
||||
CompoundNBT nbttagcompound = t.writeToNBT(new CompoundNBT());
|
||||
CompressedStreamTools.writeCompressed(nbttagcompound, outputStream);
|
||||
player.setHeldItem(Hand.MAIN_HAND, SchematicItem.create(schematic, player.getName()
|
||||
.getFormattedText()));
|
||||
player.setHeldItem(Hand.MAIN_HAND, SchematicItem.create(schematic, player.getGameProfile().getName()));
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (outputStream != null)
|
||||
IOUtils.closeQuietly(outputStream);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Create.logger.error("Exception Thrown in direct Schematic Upload: " + playerSchematicId);
|
||||
|
|
|
@ -422,8 +422,7 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
|
|||
}
|
||||
|
||||
protected void sendOptionUpdate(Option option, boolean set) {
|
||||
AllPackets.channel.sendToServer(ConfigureSchematicannonPacket.setOption(container.getTileEntity()
|
||||
.getPos(), option, set));
|
||||
AllPackets.channel.sendToServer(new ConfigureSchematicannonPacket(option, set));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
|||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.NBTProcessors;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
|
@ -466,8 +467,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
CompoundNBT data = null;
|
||||
if (AllBlockTags.SAFE_NBT.matches(blockState)) {
|
||||
TileEntity tile = blockReader.getTileEntity(target);
|
||||
if (tile != null && !tile.onlyOpsCanSetNbt()) {
|
||||
if (tile != null) {
|
||||
data = tile.write(new CompoundNBT());
|
||||
data = NBTProcessors.process(tile, data, true);
|
||||
}
|
||||
}
|
||||
launchBlock(target, icon, blockState, data);
|
||||
|
|
|
@ -1,17 +1,22 @@
|
|||
package com.simibubi.create.content.schematics.item;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.List;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.content.schematics.SchematicProcessor;
|
||||
import com.simibubi.create.content.schematics.client.SchematicEditScreen;
|
||||
import com.simibubi.create.content.schematics.filtering.SchematicInstances;
|
||||
import com.simibubi.create.foundation.gui.ScreenOpener;
|
||||
|
@ -25,6 +30,7 @@ import net.minecraft.item.ItemStack;
|
|||
import net.minecraft.item.ItemUseContext;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.CompressedStreamTools;
|
||||
import net.minecraft.nbt.NBTSizeTracker;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
|
@ -46,6 +52,8 @@ import net.minecraftforge.fml.common.thread.SidedThreadGroups;
|
|||
|
||||
public class SchematicItem extends Item {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
public SchematicItem(Properties properties) {
|
||||
super(properties.maxStackSize(1));
|
||||
}
|
||||
|
@ -96,6 +104,7 @@ public class SchematicItem extends Item {
|
|||
PlacementSettings settings = new PlacementSettings();
|
||||
settings.setRotation(Rotation.valueOf(tag.getString("Rotation")));
|
||||
settings.setMirror(Mirror.valueOf(tag.getString("Mirror")));
|
||||
settings.addProcessor(SchematicProcessor.INSTANCE);
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
@ -106,25 +115,30 @@ public class SchematicItem extends Item {
|
|||
String schematic = blueprint.getTag()
|
||||
.getString("File");
|
||||
|
||||
String filepath = "";
|
||||
if (!schematic.endsWith(".nbt"))
|
||||
return t;
|
||||
|
||||
if (Thread.currentThread()
|
||||
.getThreadGroup() == SidedThreadGroups.SERVER)
|
||||
filepath = "schematics/uploaded/" + owner + "/" + schematic;
|
||||
else
|
||||
filepath = "schematics/" + schematic;
|
||||
Path dir;
|
||||
Path file;
|
||||
|
||||
InputStream stream = null;
|
||||
try {
|
||||
stream = Files.newInputStream(Paths.get(filepath), StandardOpenOption.READ);
|
||||
CompoundNBT nbt = CompressedStreamTools.readCompressed(stream);
|
||||
if (Thread.currentThread().getThreadGroup() == SidedThreadGroups.SERVER) {
|
||||
dir = Paths.get("schematics", "uploaded").toAbsolutePath();
|
||||
file = Paths.get(owner, schematic);
|
||||
} else {
|
||||
dir = Paths.get("schematics").toAbsolutePath();
|
||||
file = Paths.get(schematic);
|
||||
}
|
||||
|
||||
Path path = dir.resolve(file).normalize();
|
||||
if (!path.startsWith(dir))
|
||||
return t;
|
||||
|
||||
try (DataInputStream stream = new DataInputStream(new BufferedInputStream(
|
||||
new GZIPInputStream(Files.newInputStream(path, StandardOpenOption.READ))))) {
|
||||
CompoundNBT nbt = CompressedStreamTools.read(stream, new NBTSizeTracker(0x20000000L));
|
||||
t.read(nbt);
|
||||
|
||||
} catch (IOException e) {
|
||||
// Player/Server doesnt have schematic saved
|
||||
} finally {
|
||||
if (stream != null)
|
||||
IOUtils.closeQuietly(stream);
|
||||
LOGGER.warn("Failed to read schematic", e);
|
||||
}
|
||||
|
||||
return t;
|
||||
|
@ -142,7 +156,7 @@ public class SchematicItem extends Item {
|
|||
public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {
|
||||
if (!onItemUse(playerIn, handIn))
|
||||
return super.onItemRightClick(worldIn, playerIn, handIn);
|
||||
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, playerIn.getHeldItem(handIn));
|
||||
return new ActionResult<>(ActionResultType.SUCCESS, playerIn.getHeldItem(handIn));
|
||||
}
|
||||
|
||||
private boolean onItemUse(PlayerEntity player, Hand hand) {
|
||||
|
|
|
@ -2,15 +2,13 @@ package com.simibubi.create.content.schematics.packet;
|
|||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.content.schematics.block.SchematicannonContainer;
|
||||
import com.simibubi.create.content.schematics.block.SchematicannonTileEntity;
|
||||
import com.simibubi.create.content.schematics.block.SchematicannonTileEntity.State;
|
||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.network.NetworkEvent.Context;
|
||||
|
||||
public class ConfigureSchematicannonPacket extends SimplePacketBase {
|
||||
|
@ -21,45 +19,28 @@ public class ConfigureSchematicannonPacket extends SimplePacketBase {
|
|||
|
||||
private Option option;
|
||||
private boolean set;
|
||||
private BlockPos pos;
|
||||
|
||||
public static ConfigureSchematicannonPacket setOption(BlockPos pos, Option option, boolean set) {
|
||||
ConfigureSchematicannonPacket packet = new ConfigureSchematicannonPacket(pos);
|
||||
packet.option = option;
|
||||
packet.set = set;
|
||||
return packet;
|
||||
}
|
||||
|
||||
public ConfigureSchematicannonPacket(BlockPos pos) {
|
||||
this.pos = pos;
|
||||
public ConfigureSchematicannonPacket(Option option, boolean set) {
|
||||
this.option = option;
|
||||
this.set = set;
|
||||
}
|
||||
|
||||
public ConfigureSchematicannonPacket(PacketBuffer buffer) {
|
||||
pos = buffer.readBlockPos();
|
||||
option = Option.values()[buffer.readInt()];
|
||||
set = buffer.readBoolean();
|
||||
this(buffer.readEnumValue(Option.class), buffer.readBoolean());
|
||||
}
|
||||
|
||||
public void write(PacketBuffer buffer) {
|
||||
buffer.writeBlockPos(pos);
|
||||
buffer.writeInt(option.ordinal());
|
||||
buffer.writeEnumValue(option);
|
||||
buffer.writeBoolean(set);
|
||||
}
|
||||
|
||||
public void handle(Supplier<Context> context) {
|
||||
context.get().enqueueWork(() -> {
|
||||
ServerPlayerEntity player = context.get().getSender();
|
||||
if (player == null)
|
||||
return;
|
||||
World world = player.world;
|
||||
if (world == null || !world.isBlockPresent(pos))
|
||||
if (player == null || !(player.openContainer instanceof SchematicannonContainer))
|
||||
return;
|
||||
|
||||
TileEntity tileEntity = world.getTileEntity(pos);
|
||||
if (!(tileEntity instanceof SchematicannonTileEntity))
|
||||
return;
|
||||
|
||||
SchematicannonTileEntity te = (SchematicannonTileEntity) tileEntity;
|
||||
SchematicannonTileEntity te = ((SchematicannonContainer) player.openContainer).getTileEntity();
|
||||
switch (option) {
|
||||
case DONT_REPLACE:
|
||||
case REPLACE_ANY:
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.simibubi.create.content.schematics.packet;
|
|||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.content.schematics.SchematicProcessor;
|
||||
import com.simibubi.create.content.schematics.item.SchematicItem;
|
||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||
|
||||
|
@ -36,6 +37,8 @@ public class SchematicPlacePacket extends SimplePacketBase {
|
|||
return;
|
||||
Template t = SchematicItem.loadSchematic(stack);
|
||||
PlacementSettings settings = SchematicItem.getSettings(stack);
|
||||
if (player.canUseCommandBlock())
|
||||
settings.func_215220_b(SchematicProcessor.INSTANCE); // remove processor
|
||||
settings.setIgnoreEntities(false);
|
||||
t.addBlocksToWorld(player.getServerWorld(), NBTUtil.readBlockPos(stack.getTag().getCompound("Anchor")),
|
||||
settings);
|
||||
|
|
|
@ -39,48 +39,52 @@ import net.minecraft.network.PacketBuffer;
|
|||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.network.NetworkDirection;
|
||||
import net.minecraftforge.fml.network.NetworkEvent.Context;
|
||||
import net.minecraftforge.fml.network.NetworkRegistry;
|
||||
import net.minecraftforge.fml.network.PacketDistributor;
|
||||
import net.minecraftforge.fml.network.PacketDistributor.TargetPoint;
|
||||
import net.minecraftforge.fml.network.simple.SimpleChannel;
|
||||
|
||||
import static net.minecraftforge.fml.network.NetworkDirection.PLAY_TO_SERVER;
|
||||
import static net.minecraftforge.fml.network.NetworkDirection.PLAY_TO_CLIENT;
|
||||
|
||||
public enum AllPackets {
|
||||
|
||||
// Client to Server
|
||||
NBT(NbtPacket.class, NbtPacket::new),
|
||||
CONFIGURE_SCHEMATICANNON(ConfigureSchematicannonPacket.class, ConfigureSchematicannonPacket::new),
|
||||
CONFIGURE_FLEXCRATE(ConfigureFlexcratePacket.class, ConfigureFlexcratePacket::new),
|
||||
CONFIGURE_STOCKSWITCH(ConfigureStockswitchPacket.class, ConfigureStockswitchPacket::new),
|
||||
CONFIGURE_SEQUENCER(ConfigureSequencedGearshiftPacket.class, ConfigureSequencedGearshiftPacket::new),
|
||||
PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new),
|
||||
UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new),
|
||||
CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new),
|
||||
CONFIGURE_FILTERING_AMOUNT(FilteringCountUpdatePacket.class, FilteringCountUpdatePacket::new),
|
||||
CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new),
|
||||
EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new),
|
||||
CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new),
|
||||
CLIENT_MOTION(ClientMotionPacket.class, ClientMotionPacket::new),
|
||||
PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new),
|
||||
MINECART_COUPLING_CREATION(CouplingCreationPacket.class, CouplingCreationPacket::new),
|
||||
INSTANT_SCHEMATIC(InstantSchematicPacket.class, InstantSchematicPacket::new),
|
||||
SYNC_SCHEMATIC(SchematicSyncPacket.class, SchematicSyncPacket::new),
|
||||
LEFT_CLICK(LeftClickPacket.class, LeftClickPacket::new),
|
||||
NBT(NbtPacket.class, NbtPacket::new, PLAY_TO_SERVER),
|
||||
CONFIGURE_SCHEMATICANNON(ConfigureSchematicannonPacket.class, ConfigureSchematicannonPacket::new, PLAY_TO_SERVER),
|
||||
CONFIGURE_FLEXCRATE(ConfigureFlexcratePacket.class, ConfigureFlexcratePacket::new, PLAY_TO_SERVER),
|
||||
CONFIGURE_STOCKSWITCH(ConfigureStockswitchPacket.class, ConfigureStockswitchPacket::new, PLAY_TO_SERVER),
|
||||
CONFIGURE_SEQUENCER(ConfigureSequencedGearshiftPacket.class, ConfigureSequencedGearshiftPacket::new, PLAY_TO_SERVER),
|
||||
PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new, PLAY_TO_SERVER),
|
||||
UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new, PLAY_TO_SERVER),
|
||||
CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new, PLAY_TO_SERVER),
|
||||
CONFIGURE_FILTERING_AMOUNT(FilteringCountUpdatePacket.class, FilteringCountUpdatePacket::new, PLAY_TO_SERVER),
|
||||
CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new, PLAY_TO_SERVER),
|
||||
EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new, PLAY_TO_SERVER),
|
||||
CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new, PLAY_TO_SERVER),
|
||||
CLIENT_MOTION(ClientMotionPacket.class, ClientMotionPacket::new, PLAY_TO_SERVER),
|
||||
PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new, PLAY_TO_SERVER),
|
||||
MINECART_COUPLING_CREATION(CouplingCreationPacket.class, CouplingCreationPacket::new, PLAY_TO_SERVER),
|
||||
INSTANT_SCHEMATIC(InstantSchematicPacket.class, InstantSchematicPacket::new, PLAY_TO_SERVER),
|
||||
SYNC_SCHEMATIC(SchematicSyncPacket.class, SchematicSyncPacket::new, PLAY_TO_SERVER),
|
||||
LEFT_CLICK(LeftClickPacket.class, LeftClickPacket::new, PLAY_TO_SERVER),
|
||||
|
||||
// Server to Client
|
||||
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new),
|
||||
SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new),
|
||||
BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new),
|
||||
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new),
|
||||
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new),
|
||||
CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new),
|
||||
GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new),
|
||||
CONTRAPTION_SEAT_MAPPING(ContraptionSeatMappingPacket.class, ContraptionSeatMappingPacket::new),
|
||||
LIMBSWING_UPDATE(LimbSwingUpdatePacket.class, LimbSwingUpdatePacket::new),
|
||||
MINECART_CONTROLLER(MinecartControllerUpdatePacket.class, MinecartControllerUpdatePacket::new),
|
||||
FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new),
|
||||
CONTRAPTION_FLUID(ContraptionFluidPacket.class, ContraptionFluidPacket::new),
|
||||
GANTRY_UPDATE(GantryContraptionUpdatePacket.class, GantryContraptionUpdatePacket::new),
|
||||
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),
|
||||
SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new, PLAY_TO_CLIENT),
|
||||
BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new, PLAY_TO_CLIENT),
|
||||
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new, PLAY_TO_CLIENT),
|
||||
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new, PLAY_TO_CLIENT),
|
||||
CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new, PLAY_TO_CLIENT),
|
||||
GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new, PLAY_TO_CLIENT),
|
||||
CONTRAPTION_SEAT_MAPPING(ContraptionSeatMappingPacket.class, ContraptionSeatMappingPacket::new, PLAY_TO_CLIENT),
|
||||
LIMBSWING_UPDATE(LimbSwingUpdatePacket.class, LimbSwingUpdatePacket::new, PLAY_TO_CLIENT),
|
||||
MINECART_CONTROLLER(MinecartControllerUpdatePacket.class, MinecartControllerUpdatePacket::new, PLAY_TO_CLIENT),
|
||||
FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new, PLAY_TO_CLIENT),
|
||||
CONTRAPTION_FLUID(ContraptionFluidPacket.class, ContraptionFluidPacket::new, PLAY_TO_CLIENT),
|
||||
GANTRY_UPDATE(GantryContraptionUpdatePacket.class, GantryContraptionUpdatePacket::new, PLAY_TO_CLIENT),
|
||||
|
||||
;
|
||||
|
||||
|
@ -90,14 +94,14 @@ public enum AllPackets {
|
|||
|
||||
private LoadedPacket<?> packet;
|
||||
|
||||
private <T extends SimplePacketBase> AllPackets(Class<T> type, Function<PacketBuffer, T> factory) {
|
||||
packet = new LoadedPacket<>(type, factory);
|
||||
private <T extends SimplePacketBase> AllPackets(Class<T> type, Function<PacketBuffer, T> factory, NetworkDirection direction) {
|
||||
packet = new LoadedPacket<>(type, factory, direction);
|
||||
}
|
||||
|
||||
public static void registerPackets() {
|
||||
channel = NetworkRegistry.ChannelBuilder.named(CHANNEL_NAME)
|
||||
.serverAcceptedVersions(s -> true)
|
||||
.clientAcceptedVersions(s -> true)
|
||||
.serverAcceptedVersions(NETWORK_VERSION::equals)
|
||||
.clientAcceptedVersions(NETWORK_VERSION::equals)
|
||||
.networkProtocolVersion(() -> NETWORK_VERSION)
|
||||
.simpleChannel();
|
||||
for (AllPackets packet : values())
|
||||
|
@ -117,16 +121,18 @@ public enum AllPackets {
|
|||
Function<PacketBuffer, T> decoder;
|
||||
BiConsumer<T, Supplier<Context>> handler;
|
||||
Class<T> type;
|
||||
NetworkDirection direction;
|
||||
|
||||
private LoadedPacket(Class<T> type, Function<PacketBuffer, T> factory) {
|
||||
private LoadedPacket(Class<T> type, Function<PacketBuffer, T> factory, NetworkDirection direction) {
|
||||
encoder = T::write;
|
||||
decoder = factory;
|
||||
handler = T::handle;
|
||||
this.type = type;
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
private void register() {
|
||||
channel.messageBuilder(type, index++)
|
||||
channel.messageBuilder(type, index++, direction)
|
||||
.encoder(encoder)
|
||||
.decoder(decoder)
|
||||
.consumer(handler)
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
|
||||
|
@ -21,17 +20,10 @@ import net.minecraft.nbt.CompoundNBT;
|
|||
public class FilesHelper {
|
||||
|
||||
public static void createFolderIfMissing(String name) {
|
||||
Path path = Paths.get(name);
|
||||
if (path.getParent() != null)
|
||||
createFolderIfMissing(path.getParent()
|
||||
.toString());
|
||||
|
||||
if (!Files.isDirectory(path)) {
|
||||
try {
|
||||
Files.createDirectory(path);
|
||||
} catch (IOException e) {
|
||||
Create.logger.warn("Could not create Folder: " + name);
|
||||
}
|
||||
try {
|
||||
Files.createDirectories(Paths.get(name));
|
||||
} catch (IOException e) {
|
||||
Create.logger.warn("Could not create Folder: {}", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package com.simibubi.create.foundation.utility;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
import com.simibubi.create.content.logistics.item.filter.FilterItem;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
public final class NBTProcessors {
|
||||
|
||||
private static final Map<TileEntityType<?>, UnaryOperator<CompoundNBT>> processors = new HashMap<>();
|
||||
private static final Map<TileEntityType<?>, UnaryOperator<CompoundNBT>> survivalProcessors = new HashMap<>();
|
||||
|
||||
public static synchronized void addProcessor(TileEntityType<?> type, UnaryOperator<CompoundNBT> processor) {
|
||||
processors.put(type, processor);
|
||||
}
|
||||
|
||||
public static synchronized void addSurvivalProcessor(TileEntityType<?> type, UnaryOperator<CompoundNBT> processor) {
|
||||
survivalProcessors.put(type, processor);
|
||||
}
|
||||
|
||||
static {
|
||||
addProcessor(TileEntityType.SIGN, data -> {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
String s = data.getString("Text" + (i + 1));
|
||||
ITextComponent textcomponent = ITextComponent.Serializer.fromJson(s.isEmpty() ? "\"\"" : s);
|
||||
if (textcomponent != null && textcomponent.getStyle() != null
|
||||
&& textcomponent.getStyle().getClickEvent() != null)
|
||||
return null;
|
||||
}
|
||||
return data;
|
||||
});
|
||||
addSurvivalProcessor(AllTileEntities.FUNNEL.get(), data -> {
|
||||
if (data.contains("Filter")) {
|
||||
ItemStack filter = ItemStack.read(data.getCompound("Filter"));
|
||||
if (filter.getItem() instanceof FilterItem)
|
||||
data.remove("Filter");
|
||||
}
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
private NBTProcessors() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CompoundNBT process(TileEntity tileEntity, CompoundNBT compound, boolean survival) {
|
||||
if (compound == null)
|
||||
return null;
|
||||
TileEntityType<?> type = tileEntity.getType();
|
||||
if (survival && survivalProcessors.containsKey(type))
|
||||
compound = survivalProcessors.get(type).apply(compound);
|
||||
if (processors.containsKey(type))
|
||||
return processors.get(type).apply(compound);
|
||||
if (tileEntity.onlyOpsCanSetNbt())
|
||||
return null;
|
||||
return compound;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue