mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-16 23:11:40 +01:00
Handheld Worldshaper
- Fixed crash caused by suicidal deployers - Fixed blockzapper rendering inconsistencies before a block is selected - Added the Handheld Worldshaper with 3 brushes and 6 modes - Entities on belts no longer get blocked by entities they are being ridden by
This commit is contained in:
parent
5d2bbc930b
commit
c3278c91c8
39 changed files with 2079 additions and 518 deletions
|
@ -17,6 +17,7 @@ import com.simibubi.create.modules.curiosities.deforester.DeforesterItem;
|
|||
import com.simibubi.create.modules.curiosities.symmetry.SymmetryWandItem;
|
||||
import com.simibubi.create.modules.curiosities.tools.SandPaperItem;
|
||||
import com.simibubi.create.modules.curiosities.zapper.blockzapper.BlockzapperItem;
|
||||
import com.simibubi.create.modules.curiosities.zapper.terrainzapper.TerrainzapperItem;
|
||||
import com.simibubi.create.modules.gardens.TreeFertilizerItem;
|
||||
import com.simibubi.create.modules.logistics.item.filter.FilterItem;
|
||||
import com.simibubi.create.modules.schematics.item.SchematicAndQuillItem;
|
||||
|
@ -95,6 +96,7 @@ public enum AllItems {
|
|||
__CURIOSITIES__(module()),
|
||||
TREE_FERTILIZER(TreeFertilizerItem::new),
|
||||
PLACEMENT_HANDGUN(BlockzapperItem::new),
|
||||
TERRAIN_ZAPPER(TerrainzapperItem::new),
|
||||
DEFORESTER(DeforesterItem::new),
|
||||
SYMMETRY_WAND(SymmetryWandItem::new),
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import com.simibubi.create.foundation.packet.SimplePacketBase;
|
|||
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionStallPacket;
|
||||
import com.simibubi.create.modules.curiosities.symmetry.SymmetryEffectPacket;
|
||||
import com.simibubi.create.modules.curiosities.zapper.blockzapper.BlockzapperBeamPacket;
|
||||
import com.simibubi.create.modules.curiosities.zapper.ZapperBeamPacket;
|
||||
import com.simibubi.create.modules.logistics.item.filter.FilterScreenPacket;
|
||||
import com.simibubi.create.modules.logistics.packet.ConfigureFlexcratePacket;
|
||||
import com.simibubi.create.modules.logistics.packet.ConfigureStockswitchPacket;
|
||||
|
@ -42,7 +42,7 @@ public enum AllPackets {
|
|||
// Server to Client
|
||||
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new),
|
||||
SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new),
|
||||
BEAM_EFFECT(BlockzapperBeamPacket.class, BlockzapperBeamPacket::new),
|
||||
BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new),
|
||||
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new),
|
||||
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new),
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
|
|||
import com.simibubi.create.modules.contraptions.components.contraptions.ChassisRangeDisplay;
|
||||
import com.simibubi.create.modules.contraptions.components.turntable.TurntableHandler;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltConnectorItemHandler;
|
||||
import com.simibubi.create.modules.curiosities.zapper.terrainzapper.TerrainZapperRenderHandler;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
@ -60,6 +61,7 @@ public class ClientEvents {
|
|||
public static void onGameTick() {
|
||||
CreateClient.gameTick();
|
||||
BeltConnectorItemHandler.gameTick();
|
||||
TerrainZapperRenderHandler.tick();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
@ -69,6 +71,7 @@ public class ClientEvents {
|
|||
CreateClient.schematicHologram.render();
|
||||
KineticDebugger.renderSourceOutline();
|
||||
ChassisRangeDisplay.renderOutlines(event.getPartialTicks());
|
||||
TerrainZapperRenderHandler.render();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
|
|
@ -10,7 +10,9 @@ public enum ScreenResources {
|
|||
// Inventories
|
||||
PLAYER_INVENTORY("player_inventory.png", 176, 108),
|
||||
WAND_SYMMETRY("wand_symmetry.png", 207, 58),
|
||||
PLACEMENT_GUN("placement_handgun.png", 217, 70),
|
||||
BLOCKZAPPER("zapper.png", 217, 70),
|
||||
TERRAINZAPPER("zapper.png", 0, 70, 217, 105),
|
||||
TERRAINZAPPER_INACTIVE_PARAM("zapper.png", 0, 175, 14, 14),
|
||||
|
||||
SCHEMATIC_TABLE("schematic_table.png", 207, 89),
|
||||
SCHEMATIC_TABLE_PROGRESS("schematic_table.png", 209, 0, 24, 17),
|
||||
|
@ -127,6 +129,15 @@ public enum ScreenResources {
|
|||
I_REPLACE_SOLID(1, 2),
|
||||
I_REPLACE_ANY(2, 2),
|
||||
I_REPLACE_EMPTY(3, 2),
|
||||
I_CENTERED(4, 2),
|
||||
I_ATTACHED(5, 2),
|
||||
I_INSERTED(6, 2),
|
||||
I_FILL(7, 2),
|
||||
I_PLACE(8, 2),
|
||||
I_REPLACE(9, 2),
|
||||
I_CLEAR(10, 2),
|
||||
I_OVERLAY(11, 2),
|
||||
I_FLATTEN(12, 2),
|
||||
|
||||
I_TOOL_DEPLOY(0, 3),
|
||||
I_SKIP_TILES(2, 3),
|
||||
|
|
|
@ -259,7 +259,8 @@ public class DeployerTileEntity extends KineticTileEntity {
|
|||
player.rotationPitch = direction == Direction.UP ? -90 : direction == Direction.DOWN ? 90 : 0;
|
||||
|
||||
DeployerHandler.activate(player, center, clickedPos, movementVector, mode);
|
||||
heldItem = player.getHeldItemMainhand();
|
||||
if (player != null)
|
||||
heldItem = player.getHeldItemMainhand();
|
||||
}
|
||||
|
||||
protected void returnAndDeposit() {
|
||||
|
|
|
@ -4,6 +4,8 @@ import static net.minecraft.entity.MoverType.SELF;
|
|||
import static net.minecraft.util.Direction.AxisDirection.NEGATIVE;
|
||||
import static net.minecraft.util.Direction.AxisDirection.POSITIVE;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
|
||||
|
@ -62,9 +64,9 @@ public class BeltMovementHandler {
|
|||
TileEntity te = world.getTileEntity(pos);
|
||||
TileEntity tileEntityBelowPassenger = world.getTileEntity(entityIn.getPosition());
|
||||
BlockState blockState = info.lastCollidedState;
|
||||
Direction movementFacing = Direction.getFacingFromAxisDirection(
|
||||
blockState.get(BlockStateProperties.HORIZONTAL_FACING).getAxis(),
|
||||
beltTe.getSpeed() < 0 ? POSITIVE : NEGATIVE);
|
||||
Direction movementFacing =
|
||||
Direction.getFacingFromAxisDirection(blockState.get(BlockStateProperties.HORIZONTAL_FACING).getAxis(),
|
||||
beltTe.getSpeed() < 0 ? POSITIVE : NEGATIVE);
|
||||
|
||||
boolean collidedWithBelt = te instanceof BeltTileEntity;
|
||||
boolean betweenBelts = tileEntityBelowPassenger instanceof BeltTileEntity && tileEntityBelowPassenger != te;
|
||||
|
@ -105,8 +107,8 @@ public class BeltMovementHandler {
|
|||
float movementSpeed = beltTe.getBeltMovementSpeed();
|
||||
final Direction movementDirection = Direction.getFacingFromAxis(axis == Axis.X ? NEGATIVE : POSITIVE, axis);
|
||||
|
||||
Vec3i centeringDirection = Direction.getFacingFromAxis(POSITIVE, beltFacing.rotateY().getAxis())
|
||||
.getDirectionVec();
|
||||
Vec3i centeringDirection =
|
||||
Direction.getFacingFromAxis(POSITIVE, beltFacing.rotateY().getAxis()).getDirectionVec();
|
||||
Vec3d movement = new Vec3d(movementDirection.getDirectionVec()).scale(movementSpeed);
|
||||
|
||||
double diffCenter = axis == Axis.Z ? (pos.getX() + .5f - entityIn.posX) : (pos.getZ() + .5f - entityIn.posZ);
|
||||
|
@ -145,10 +147,11 @@ public class BeltMovementHandler {
|
|||
Vec3d checkDistance = movement.normalize().scale(0.5);
|
||||
AxisAlignedBB bb = entityIn.getBoundingBox();
|
||||
AxisAlignedBB checkBB = new AxisAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
|
||||
if (!world
|
||||
.getEntitiesWithinAABBExcludingEntity(entityIn, checkBB.offset(checkDistance)
|
||||
.grow(-Math.abs(checkDistance.x), -Math.abs(checkDistance.y), -Math.abs(checkDistance.z)))
|
||||
.isEmpty()) {
|
||||
checkBB = checkBB.offset(checkDistance).grow(-Math.abs(checkDistance.x), -Math.abs(checkDistance.y),
|
||||
-Math.abs(checkDistance.z));
|
||||
List<Entity> list = world.getEntitiesWithinAABBExcludingEntity(entityIn, checkBB);
|
||||
list.removeIf(e -> entityIn.isRidingOrBeingRiddenBy(e));
|
||||
if (!list.isEmpty()) {
|
||||
entityIn.setMotion(0, 0, 0);
|
||||
info.ticksSinceLastCollision--;
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.simibubi.create.ScreenResources;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public enum PlacementPatterns {
|
||||
|
||||
Solid(ScreenResources.I_PATTERN_SOLID),
|
||||
Checkered(ScreenResources.I_PATTERN_CHECKERED),
|
||||
InverseCheckered(ScreenResources.I_PATTERN_CHECKERED_INVERSED),
|
||||
Chance25(ScreenResources.I_PATTERN_CHANCE_25),
|
||||
Chance50(ScreenResources.I_PATTERN_CHANCE_50),
|
||||
Chance75(ScreenResources.I_PATTERN_CHANCE_75);
|
||||
|
||||
public String translationKey;
|
||||
public ScreenResources icon;
|
||||
|
||||
private PlacementPatterns(ScreenResources icon) {
|
||||
this.translationKey = Lang.asId(name());
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
public static void applyPattern(List<BlockPos> blocksIn, ItemStack stack) {
|
||||
CompoundNBT tag = stack.getTag();
|
||||
PlacementPatterns pattern =
|
||||
!tag.contains("Pattern") ? Solid : valueOf(tag.getString("Pattern"));
|
||||
Random r = new Random();
|
||||
Predicate<BlockPos> filter = Predicates.alwaysFalse();
|
||||
|
||||
switch (pattern) {
|
||||
case Chance25:
|
||||
filter = pos -> r.nextBoolean() || r.nextBoolean();
|
||||
break;
|
||||
case Chance50:
|
||||
filter = pos -> r.nextBoolean();
|
||||
break;
|
||||
case Chance75:
|
||||
filter = pos -> r.nextBoolean() && r.nextBoolean();
|
||||
break;
|
||||
case Checkered:
|
||||
filter = pos -> (pos.getX() + pos.getY() + pos.getZ()) % 2 == 0;
|
||||
break;
|
||||
case InverseCheckered:
|
||||
filter = pos -> (pos.getX() + pos.getY() + pos.getZ()) % 2 != 0;
|
||||
break;
|
||||
case Solid:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
blocksIn.removeIf(filter);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.blockzapper;
|
||||
package com.simibubi.create.modules.curiosities.zapper;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.foundation.packet.SimplePacketBase;
|
||||
import com.simibubi.create.modules.curiosities.zapper.blockzapper.BlockzapperHandler.LaserBeam;
|
||||
import com.simibubi.create.modules.curiosities.zapper.ZapperRenderHandler.LaserBeam;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
|
@ -14,21 +14,21 @@ import net.minecraftforge.api.distmarker.Dist;
|
|||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.fml.network.NetworkEvent.Context;
|
||||
|
||||
public class BlockzapperBeamPacket extends SimplePacketBase {
|
||||
public class ZapperBeamPacket extends SimplePacketBase {
|
||||
|
||||
public Vec3d start;
|
||||
public Vec3d target;
|
||||
public Hand hand;
|
||||
public boolean self;
|
||||
|
||||
public BlockzapperBeamPacket(Vec3d start, Vec3d target, Hand hand, boolean self) {
|
||||
public ZapperBeamPacket(Vec3d start, Vec3d target, Hand hand, boolean self) {
|
||||
this.start = start;
|
||||
this.target = target;
|
||||
this.hand = hand;
|
||||
this.self = self;
|
||||
}
|
||||
|
||||
public BlockzapperBeamPacket(PacketBuffer buffer) {
|
||||
public ZapperBeamPacket(PacketBuffer buffer) {
|
||||
start = new Vec3d(buffer.readDouble(), buffer.readDouble(), buffer.readDouble());
|
||||
target = new Vec3d(buffer.readDouble(), buffer.readDouble(), buffer.readDouble());
|
||||
hand = buffer.readBoolean()? Hand.MAIN_HAND : Hand.OFF_HAND;
|
||||
|
@ -51,12 +51,12 @@ public class BlockzapperBeamPacket extends SimplePacketBase {
|
|||
context.get().enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
|
||||
if (Minecraft.getInstance().player.getPositionVector().distanceTo(start) > 100)
|
||||
return;
|
||||
BlockzapperHandler.addBeam(new LaserBeam(start, target).followPlayer(self, hand == Hand.MAIN_HAND));
|
||||
ZapperRenderHandler.addBeam(new LaserBeam(start, target).followPlayer(self, hand == Hand.MAIN_HAND));
|
||||
|
||||
if (self)
|
||||
BlockzapperHandler.shoot(hand);
|
||||
ZapperRenderHandler.shoot(hand);
|
||||
else
|
||||
BlockzapperHandler.playSound(hand, new BlockPos(start));
|
||||
ZapperRenderHandler.playSound(hand, new BlockPos(start));
|
||||
}));
|
||||
context.get().setPacketHandled(true);
|
||||
}
|
|
@ -2,28 +2,47 @@ package com.simibubi.create.modules.curiosities.zapper;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.AllPackets;
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
import com.simibubi.create.foundation.item.ItemDescription;
|
||||
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemUseContext;
|
||||
import net.minecraft.item.Rarity;
|
||||
import net.minecraft.item.UseAction;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.state.properties.StairsShape;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.HandSide;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.RayTraceContext;
|
||||
import net.minecraft.util.math.RayTraceContext.BlockMode;
|
||||
import net.minecraft.util.math.RayTraceContext.FluidMode;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.fml.network.PacketDistributor;
|
||||
|
||||
public abstract class ZapperItem extends Item {
|
||||
|
||||
|
@ -35,13 +54,27 @@ public abstract class ZapperItem extends Item {
|
|||
@OnlyIn(Dist.CLIENT)
|
||||
public void addInformation(ItemStack stack, World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
|
||||
if (stack.hasTag() && stack.getTag().contains("BlockUsed")) {
|
||||
String usedblock = NBTUtil.readBlockState(stack.getTag().getCompound("BlockUsed")).getBlock()
|
||||
.getTranslationKey();
|
||||
String usedblock =
|
||||
NBTUtil.readBlockState(stack.getTag().getCompound("BlockUsed")).getBlock().getTranslationKey();
|
||||
ItemDescription.add(tooltip, TextFormatting.DARK_GRAY + Lang.translate("blockzapper.usingBlock",
|
||||
TextFormatting.GRAY + new TranslationTextComponent(usedblock).getFormattedText()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
|
||||
boolean differentBlock = false;
|
||||
if (oldStack.hasTag() && newStack.hasTag() && oldStack.getTag().contains("BlockUsed")
|
||||
&& newStack.getTag().contains("BlockUsed"))
|
||||
differentBlock = NBTUtil.readBlockState(oldStack.getTag().getCompound("BlockUsed")) != NBTUtil
|
||||
.readBlockState(newStack.getTag().getCompound("BlockUsed"));
|
||||
return slotChanged || !isZapper(newStack) || differentBlock;
|
||||
}
|
||||
|
||||
public boolean isZapper(ItemStack newStack) {
|
||||
return newStack.getItem() instanceof ZapperItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResultType onItemUse(ItemUseContext context) {
|
||||
// Shift -> open GUI
|
||||
|
@ -57,11 +90,110 @@ public abstract class ZapperItem extends Item {
|
|||
return super.onItemUse(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult<ItemStack> onItemRightClick(World world, PlayerEntity player, Hand hand) {
|
||||
ItemStack item = player.getHeldItem(hand);
|
||||
CompoundNBT nbt = item.getOrCreateTag();
|
||||
|
||||
// Shift -> Open GUI
|
||||
if (player.isSneaking()) {
|
||||
if (world.isRemote) {
|
||||
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
|
||||
openHandgunGUI(item, hand == Hand.OFF_HAND);
|
||||
});
|
||||
applyCooldown(player, item, false);
|
||||
}
|
||||
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item);
|
||||
}
|
||||
|
||||
boolean mainHand = hand == Hand.MAIN_HAND;
|
||||
boolean isSwap = item.getTag().contains("_Swap");
|
||||
boolean gunInOtherHand = isZapper(player.getHeldItem(mainHand ? Hand.OFF_HAND : Hand.MAIN_HAND));
|
||||
|
||||
// Pass To Offhand
|
||||
if (mainHand && isSwap && gunInOtherHand)
|
||||
return new ActionResult<ItemStack>(ActionResultType.FAIL, item);
|
||||
if (mainHand && !isSwap && gunInOtherHand)
|
||||
item.getTag().putBoolean("_Swap", true);
|
||||
if (!mainHand && isSwap)
|
||||
item.getTag().remove("_Swap");
|
||||
if (!mainHand && gunInOtherHand)
|
||||
player.getHeldItem(Hand.MAIN_HAND).getTag().remove("_Swap");
|
||||
player.setActiveHand(hand);
|
||||
|
||||
// Check if can be used
|
||||
String msg = validateUsage(item);
|
||||
if (msg != null) {
|
||||
world.playSound(player, player.getPosition(), AllSoundEvents.BLOCKZAPPER_DENY.get(), SoundCategory.BLOCKS,
|
||||
1f, 0.5f);
|
||||
player.sendStatusMessage(new StringTextComponent(TextFormatting.RED + msg), true);
|
||||
return new ActionResult<ItemStack>(ActionResultType.FAIL, item);
|
||||
}
|
||||
|
||||
BlockState stateToUse = Blocks.AIR.getDefaultState();
|
||||
if (nbt.contains("BlockUsed"))
|
||||
stateToUse = NBTUtil.readBlockState(nbt.getCompound("BlockUsed"));
|
||||
|
||||
// Raytrace - Find the target
|
||||
Vec3d start = player.getPositionVec().add(0, player.getEyeHeight(), 0);
|
||||
Vec3d range = player.getLookVec().scale(getRange(item));
|
||||
BlockRayTraceResult raytrace = world.rayTraceBlocks(
|
||||
new RayTraceContext(start, start.add(range), BlockMode.OUTLINE, FluidMode.NONE, player));
|
||||
BlockPos pos = raytrace.getPos();
|
||||
BlockState stateReplaced = world.getBlockState(pos);
|
||||
|
||||
// No target
|
||||
if (pos == null || stateReplaced.getBlock() == Blocks.AIR) {
|
||||
applyCooldown(player, item, gunInOtherHand);
|
||||
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item);
|
||||
}
|
||||
|
||||
// Find exact position of gun barrel for VFX
|
||||
float yaw = (float) ((player.rotationYaw) / -180 * Math.PI);
|
||||
float pitch = (float) ((player.rotationPitch) / -180 * Math.PI);
|
||||
Vec3d barrelPosNoTransform =
|
||||
new Vec3d(mainHand == (player.getPrimaryHand() == HandSide.RIGHT) ? -.35f : .35f, -0.1f, 1);
|
||||
Vec3d barrelPos = start.add(barrelPosNoTransform.rotatePitch(pitch).rotateYaw(yaw));
|
||||
|
||||
// Client side
|
||||
if (world.isRemote) {
|
||||
ZapperRenderHandler.dontAnimateItem(hand);
|
||||
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item);
|
||||
}
|
||||
|
||||
// Server side
|
||||
if (activate(world, player, item, stateToUse, raytrace)) {
|
||||
applyCooldown(player, item, gunInOtherHand);
|
||||
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> player),
|
||||
new ZapperBeamPacket(barrelPos, raytrace.getHitVec(), hand, false));
|
||||
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player),
|
||||
new ZapperBeamPacket(barrelPos, raytrace.getHitVec(), hand, true));
|
||||
}
|
||||
|
||||
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item);
|
||||
}
|
||||
|
||||
public String validateUsage(ItemStack item) {
|
||||
CompoundNBT tag = item.getOrCreateTag();
|
||||
if (!canActivateWithoutSelectedBlock(item) && !tag.contains("BlockUsed"))
|
||||
return Lang.translate("blockzapper.leftClickToSet");
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract boolean activate(World world, PlayerEntity player, ItemStack item, BlockState stateToUse,
|
||||
BlockRayTraceResult raytrace);
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
protected abstract void openHandgunGUI(ItemStack item, boolean b);
|
||||
|
||||
protected abstract int getCooldownDelay(ItemStack item);
|
||||
|
||||
protected abstract int getRange(ItemStack stack);
|
||||
|
||||
protected boolean canActivateWithoutSelectedBlock(ItemStack stack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void applyCooldown(PlayerEntity playerIn, ItemStack item, boolean dual) {
|
||||
int delay = getCooldownDelay(item);
|
||||
playerIn.getCooldownTracker().setCooldown(item.getItem(), dual ? delay * 2 / 3 : delay);
|
||||
|
@ -77,4 +209,50 @@ public abstract class ZapperItem extends Item {
|
|||
return UseAction.NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEntitySwing(ItemStack stack, LivingEntity entity) {
|
||||
if (!(entity instanceof PlayerEntity))
|
||||
return false;
|
||||
if (entity.isSneaking())
|
||||
return true;
|
||||
|
||||
Vec3d start = entity.getPositionVec().add(0, entity.getEyeHeight(), 0);
|
||||
Vec3d range = entity.getLookVec().scale(getRange(stack));
|
||||
BlockRayTraceResult raytrace = entity.world.rayTraceBlocks(
|
||||
new RayTraceContext(start, start.add(range), BlockMode.OUTLINE, FluidMode.NONE, entity));
|
||||
BlockPos pos = raytrace.getPos();
|
||||
if (pos == null)
|
||||
return true;
|
||||
|
||||
entity.world.sendBlockBreakProgress(entity.getEntityId(), pos, -1);
|
||||
BlockState newState = entity.world.getBlockState(pos);
|
||||
|
||||
if (BlockHelper.getRequiredItem(newState).isEmpty())
|
||||
return true;
|
||||
if (entity.world.getTileEntity(pos) != null)
|
||||
return true;
|
||||
if (newState.has(BlockStateProperties.DOUBLE_BLOCK_HALF))
|
||||
return true;
|
||||
if (newState.has(BlockStateProperties.ATTACHED))
|
||||
return true;
|
||||
if (newState.has(BlockStateProperties.HANGING))
|
||||
return true;
|
||||
if (newState.has(BlockStateProperties.BED_PART))
|
||||
return true;
|
||||
if (newState.has(BlockStateProperties.STAIRS_SHAPE))
|
||||
newState = newState.with(BlockStateProperties.STAIRS_SHAPE, StairsShape.STRAIGHT);
|
||||
if (newState.has(BlockStateProperties.PERSISTENT))
|
||||
newState = newState.with(BlockStateProperties.PERSISTENT, true);
|
||||
|
||||
CompoundNBT tag = stack.getOrCreateTag();
|
||||
if (tag.contains("BlockUsed") && NBTUtil.readBlockState(stack.getTag().getCompound("BlockUsed")) == newState)
|
||||
return true;
|
||||
|
||||
tag.put("BlockUsed", NBTUtil.writeBlockState(newState));
|
||||
entity.world.playSound((PlayerEntity) entity, entity.getPosition(), AllSoundEvents.BLOCKZAPPER_CONFIRM.get(),
|
||||
SoundCategory.BLOCKS, 0.5f, 0.8f);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FourWayBlock;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.ItemRenderer;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.tileentity.ItemStackTileEntityRenderer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
|
||||
public abstract class ZapperItemRenderer extends ItemStackTileEntityRenderer {
|
||||
|
||||
protected void renderBlockUsed(ItemStack stack, ItemRenderer itemRenderer) {
|
||||
BlockState state = NBTUtil.readBlockState(stack.getTag().getCompound("BlockUsed"));
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translatef(-0.3F, -0.45F, -0.0F);
|
||||
GlStateManager.scalef(0.25F, 0.25F, 0.25F);
|
||||
IBakedModel modelForState = Minecraft.getInstance().getBlockRendererDispatcher().getModelForState(state);
|
||||
|
||||
if (state.getBlock() instanceof FourWayBlock)
|
||||
modelForState = Minecraft.getInstance().getItemRenderer()
|
||||
.getModelWithOverrides(new ItemStack(state.getBlock()));
|
||||
|
||||
itemRenderer.renderItem(new ItemStack(state.getBlock()), modelForState);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
}
|
|
@ -11,11 +11,11 @@ import net.minecraft.util.math.BlockPos;
|
|||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||
|
||||
public class ZapLog {
|
||||
public class ZapperLog {
|
||||
|
||||
private World activeWorld;
|
||||
private List<List<BlockInfo>> log = new LinkedList<>();
|
||||
private int redoIndex;
|
||||
// private int redoIndex;
|
||||
|
||||
/*
|
||||
* Undo and redo operations applied by tools what information is necessary?
|
||||
|
@ -42,7 +42,7 @@ public class ZapLog {
|
|||
}).collect(Collectors.toList());
|
||||
|
||||
log.add(0, blocks);
|
||||
redoIndex = 0;
|
||||
// redoIndex = 0;
|
||||
|
||||
if (maxLogLength() < log.size())
|
||||
log.remove(log.size() - 1);
|
|
@ -1,15 +1,14 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.blockzapper;
|
||||
package com.simibubi.create.modules.curiosities.zapper;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
import com.simibubi.create.foundation.utility.TessellatorHelper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -40,7 +39,7 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
|||
|
||||
@SuppressWarnings("deprecation")
|
||||
@EventBusSubscriber(value = Dist.CLIENT)
|
||||
public class BlockzapperHandler {
|
||||
public class ZapperRenderHandler {
|
||||
|
||||
public static List<LaserBeam> cachedBeams;
|
||||
public static float leftHandAnimation;
|
||||
|
@ -171,10 +170,9 @@ public class BlockzapperHandler {
|
|||
@SubscribeEvent
|
||||
public static void onRenderPlayerHand(RenderSpecificHandEvent event) {
|
||||
ItemStack heldItem = event.getItemStack();
|
||||
if (!AllItems.PLACEMENT_HANDGUN.typeOf(heldItem))
|
||||
if (!(heldItem.getItem() instanceof ZapperItem))
|
||||
return;
|
||||
|
||||
boolean idle = !heldItem.getOrCreateTag().contains("BlockUsed");
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
boolean rightHand = event.getHand() == Hand.MAIN_HAND ^ mc.player.getPrimaryHand() == HandSide.LEFT;
|
||||
|
||||
|
@ -189,8 +187,6 @@ public class BlockzapperHandler {
|
|||
equipProgress = 0;
|
||||
if (!rightHand && (leftHandAnimation > .01f || dontReequipLeft))
|
||||
equipProgress = 0;
|
||||
if (idle)
|
||||
equipProgress = 1 - event.getEquipProgress();
|
||||
|
||||
// Render arm
|
||||
float f = rightHand ? 1.0F : -1.0F;
|
|
@ -0,0 +1,185 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.simibubi.create.AllPackets;
|
||||
import com.simibubi.create.ScreenResources;
|
||||
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
|
||||
import com.simibubi.create.foundation.gui.widgets.IconButton;
|
||||
import com.simibubi.create.foundation.packet.NbtPacket;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
|
||||
import net.minecraft.client.renderer.texture.AtlasTexture;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class ZapperScreen extends AbstractSimiScreen {
|
||||
|
||||
protected ItemStack zapper;
|
||||
protected boolean offhand;
|
||||
protected float animationProgress;
|
||||
protected ScreenResources background;
|
||||
|
||||
protected final String patternSection = Lang.translate("gui.blockzapper.patternSection");
|
||||
|
||||
protected String title;
|
||||
protected Vector<IconButton> patternButtons;
|
||||
protected int brightColor;
|
||||
protected int fontColor;
|
||||
|
||||
public ZapperScreen(ScreenResources background, ItemStack zapper, boolean offhand) {
|
||||
super();
|
||||
this.background = background;
|
||||
this.zapper = zapper;
|
||||
this.offhand = offhand;
|
||||
title = "";
|
||||
brightColor = 0xCCDDFF;
|
||||
fontColor = ScreenResources.FONT_COLOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
animationProgress = 0;
|
||||
setWindowSize(background.width + 40, background.height);
|
||||
super.init();
|
||||
widgets.clear();
|
||||
|
||||
int i = guiLeft - 20;
|
||||
int j = guiTop;
|
||||
CompoundNBT nbt = zapper.getOrCreateTag();
|
||||
|
||||
patternButtons = new Vector<>(6);
|
||||
for (int row = 0; row <= 1; row++) {
|
||||
for (int col = 0; col <= 2; col++) {
|
||||
int id = patternButtons.size();
|
||||
PlacementPatterns pattern = PlacementPatterns.values()[id];
|
||||
patternButtons.add(new IconButton(i + 147 + col * 18, j + 23 + row * 18, pattern.icon));
|
||||
patternButtons.get(id).setToolTip(Lang.translate("gui.blockzapper.pattern." + pattern.translationKey));
|
||||
}
|
||||
}
|
||||
|
||||
if (nbt.contains("Pattern"))
|
||||
patternButtons.get(PlacementPatterns.valueOf(nbt.getString("Pattern")).ordinal()).active = false;
|
||||
|
||||
widgets.addAll(patternButtons);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderWindow(int mouseX, int mouseY, float partialTicks) {
|
||||
int i = guiLeft - 20;
|
||||
int j = guiTop;
|
||||
|
||||
background.draw(this, i, j);
|
||||
drawOnBackground(i, j);
|
||||
|
||||
minecraft.getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
|
||||
GlStateManager.enableBlend();
|
||||
|
||||
renderBlock();
|
||||
renderZapper();
|
||||
}
|
||||
|
||||
protected void drawOnBackground(int i, int j) {
|
||||
font.drawStringWithShadow(title, i + 8, j + 10, brightColor);
|
||||
font.drawString(patternSection, i + 148, j + 11, fontColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
animationProgress += 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
CompoundNBT nbt = zapper.getTag();
|
||||
writeAdditionalOptions(nbt);
|
||||
AllPackets.channel.sendToServer(new NbtPacket(zapper, offhand ? Hand.OFF_HAND : Hand.MAIN_HAND));
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double x, double y, int button) {
|
||||
CompoundNBT nbt = zapper.getTag();
|
||||
|
||||
for (IconButton patternButton : patternButtons) {
|
||||
if (patternButton.isHovered()) {
|
||||
patternButtons.forEach(b -> b.active = true);
|
||||
patternButton.active = false;
|
||||
patternButton.playDownSound(Minecraft.getInstance().getSoundHandler());
|
||||
nbt.putString("Pattern", PlacementPatterns.values()[patternButtons.indexOf(patternButton)].name());
|
||||
}
|
||||
}
|
||||
|
||||
return super.mouseClicked(x, y, button);
|
||||
}
|
||||
|
||||
protected void renderZapper() {
|
||||
GlStateManager.pushLightingAttributes();
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
RenderHelper.enableStandardItemLighting();
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.enableRescaleNormal();
|
||||
GlStateManager.enableAlphaTest();
|
||||
GlStateManager.alphaFunc(516, 0.1F);
|
||||
GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||
GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
|
||||
GlStateManager.translated((this.width - this.sWidth) / 2 + 260, this.height / 2 - this.sHeight / 4, 100);
|
||||
GlStateManager.rotatef(90 + 0.2f * animationProgress, 0, 1, 0);
|
||||
GlStateManager.rotatef(-40, .8f, 0, -.0f);
|
||||
GlStateManager.scaled(100, -100, 100);
|
||||
|
||||
IBakedModel model = itemRenderer.getModelWithOverrides(zapper);
|
||||
model.handlePerspective(TransformType.FIXED);
|
||||
itemRenderer.renderItem(zapper, model);
|
||||
|
||||
GlStateManager.disableAlphaTest();
|
||||
GlStateManager.disableRescaleNormal();
|
||||
GlStateManager.disableLighting();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
GlStateManager.popAttributes();
|
||||
}
|
||||
|
||||
protected void renderBlock() {
|
||||
GlStateManager.pushMatrix();
|
||||
BufferBuilder buffer = Tessellator.getInstance().getBuffer();
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
|
||||
GlStateManager.translated(guiLeft + 1.7f, guiTop - 49, 120);
|
||||
GlStateManager.rotatef(-30f, .5f, .9f, -.1f);
|
||||
GlStateManager.scaled(20, -20, 20);
|
||||
|
||||
BlockState state = Blocks.AIR.getDefaultState();
|
||||
if (zapper.hasTag() && zapper.getTag().contains("BlockUsed"))
|
||||
state = NBTUtil.readBlockState(zapper.getTag().getCompound("BlockUsed"));
|
||||
|
||||
minecraft.getBlockRendererDispatcher().renderBlock(state, new BlockPos(0, -5, 0), minecraft.world, buffer,
|
||||
minecraft.world.rand, EmptyModelData.INSTANCE);
|
||||
|
||||
Tessellator.getInstance().draw();
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
protected void writeAdditionalOptions(CompoundNBT nbt) {
|
||||
}
|
||||
|
||||
}
|
|
@ -3,14 +3,9 @@ package com.simibubi.create.modules.curiosities.zapper.blockzapper;
|
|||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.AllPackets;
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.block.render.CustomRenderedItemModel;
|
||||
import com.simibubi.create.foundation.gui.ScreenOpener;
|
||||
|
@ -20,34 +15,25 @@ import com.simibubi.create.foundation.item.ItemDescription.Palette;
|
|||
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
import com.simibubi.create.modules.curiosities.zapper.PlacementPatterns;
|
||||
import com.simibubi.create.modules.curiosities.zapper.ZapperItem;
|
||||
|
||||
import net.minecraft.advancements.CriteriaTriggers;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.fluid.IFluidState;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.state.properties.StairsShape;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.HandSide;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.RayTraceContext;
|
||||
|
@ -63,8 +49,6 @@ import net.minecraftforge.api.distmarker.Dist;
|
|||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.common.util.BlockSnapshot;
|
||||
import net.minecraftforge.event.ForgeEventFactory;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.fml.network.PacketDistributor;
|
||||
|
||||
public class BlockzapperItem extends ZapperItem implements IHaveCustomItemModel {
|
||||
|
||||
|
@ -72,23 +56,6 @@ public class BlockzapperItem extends ZapperItem implements IHaveCustomItemModel
|
|||
super(properties);
|
||||
}
|
||||
|
||||
public static enum ComponentTier {
|
||||
None(TextFormatting.DARK_GRAY), Brass(TextFormatting.GOLD), Chromatic(TextFormatting.LIGHT_PURPLE),
|
||||
|
||||
;
|
||||
|
||||
public TextFormatting color;
|
||||
|
||||
private ComponentTier(TextFormatting color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static enum Components {
|
||||
Body, Amplifier, Accelerator, Retriever, Scope
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void addInformation(ItemStack stack, World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
|
||||
|
@ -99,10 +66,10 @@ public class BlockzapperItem extends ZapperItem implements IHaveCustomItemModel
|
|||
|
||||
for (Components c : Components.values()) {
|
||||
ComponentTier tier = getTier(c, stack);
|
||||
ItemDescription.add(tooltip,
|
||||
"> " + TextFormatting.GRAY + Lang.translate("blockzapper.component." + Lang.asId(c.name()))
|
||||
+ ": " + tier.color
|
||||
+ Lang.translate("blockzapper.componentTier." + Lang.asId(tier.name())));
|
||||
String componentName =
|
||||
TextFormatting.GRAY + Lang.translate("blockzapper.component." + Lang.asId(c.name()));
|
||||
String tierName = tier.color + Lang.translate("blockzapper.componentTier." + Lang.asId(tier.name()));
|
||||
ItemDescription.add(tooltip, "> " + componentName + ": " + tierName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,183 +92,51 @@ public class BlockzapperItem extends ZapperItem implements IHaveCustomItemModel
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult<ItemStack> onItemRightClick(World world, PlayerEntity player, Hand hand) {
|
||||
ItemStack item = player.getHeldItem(hand);
|
||||
CompoundNBT nbt = item.getOrCreateTag();
|
||||
|
||||
// Shift -> Open GUI
|
||||
if (player.isSneaking()) {
|
||||
if (world.isRemote) {
|
||||
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
|
||||
openHandgunGUI(item, hand == Hand.OFF_HAND);
|
||||
});
|
||||
applyCooldown(player, item, false);
|
||||
}
|
||||
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item);
|
||||
}
|
||||
|
||||
boolean mainHand = hand == Hand.MAIN_HAND;
|
||||
boolean isSwap = item.getTag().contains("_Swap");
|
||||
boolean gunInOtherHand = AllItems.PLACEMENT_HANDGUN
|
||||
.typeOf(player.getHeldItem(mainHand ? Hand.OFF_HAND : Hand.MAIN_HAND));
|
||||
|
||||
// Pass To Offhand
|
||||
if (mainHand && isSwap && gunInOtherHand)
|
||||
return new ActionResult<ItemStack>(ActionResultType.FAIL, item);
|
||||
if (mainHand && !isSwap && gunInOtherHand)
|
||||
item.getTag().putBoolean("_Swap", true);
|
||||
if (!mainHand && isSwap)
|
||||
item.getTag().remove("_Swap");
|
||||
if (!mainHand && gunInOtherHand)
|
||||
player.getHeldItem(Hand.MAIN_HAND).getTag().remove("_Swap");
|
||||
player.setActiveHand(hand);
|
||||
|
||||
// Check if block setting is present
|
||||
BlockState stateToUse = Blocks.AIR.getDefaultState();
|
||||
if (nbt.contains("BlockUsed"))
|
||||
stateToUse = NBTUtil.readBlockState(nbt.getCompound("BlockUsed"));
|
||||
else {
|
||||
world.playSound(player, player.getPosition(), AllSoundEvents.BLOCKZAPPER_DENY.get(), SoundCategory.BLOCKS, 1f,
|
||||
0.5f);
|
||||
player.sendStatusMessage(
|
||||
new StringTextComponent(TextFormatting.RED + Lang.translate("blockzapper.leftClickToSet")), true);
|
||||
return new ActionResult<ItemStack>(ActionResultType.FAIL, item);
|
||||
}
|
||||
|
||||
// Raytrace - Find the target
|
||||
Vec3d start = player.getPositionVec().add(0, player.getEyeHeight(), 0);
|
||||
Vec3d range = player.getLookVec().scale(getReachDistance(item));
|
||||
BlockRayTraceResult raytrace = world.rayTraceBlocks(
|
||||
new RayTraceContext(start, start.add(range), BlockMode.OUTLINE, FluidMode.NONE, player));
|
||||
BlockPos pos = raytrace.getPos();
|
||||
BlockState stateReplaced = world.getBlockState(pos);
|
||||
|
||||
// No target
|
||||
if (pos == null || stateReplaced.getBlock() == Blocks.AIR) {
|
||||
applyCooldown(player, item, gunInOtherHand);
|
||||
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item);
|
||||
}
|
||||
|
||||
// Find exact position of gun barrel for VFX
|
||||
float yaw = (float) ((player.rotationYaw) / -180 * Math.PI);
|
||||
float pitch = (float) ((player.rotationPitch) / -180 * Math.PI);
|
||||
Vec3d barrelPosNoTransform = new Vec3d(mainHand == (player.getPrimaryHand() == HandSide.RIGHT) ? -.35f : .35f,
|
||||
-0.1f, 1);
|
||||
Vec3d barrelPos = start.add(barrelPosNoTransform.rotatePitch(pitch).rotateYaw(yaw));
|
||||
|
||||
// Client side
|
||||
if (world.isRemote) {
|
||||
BlockzapperHandler.dontAnimateItem(hand);
|
||||
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item);
|
||||
}
|
||||
|
||||
// Server side - Replace Blocks
|
||||
protected boolean activate(World world, PlayerEntity player, ItemStack stack, BlockState selectedState,
|
||||
BlockRayTraceResult raytrace) {
|
||||
CompoundNBT nbt = stack.getOrCreateTag();
|
||||
boolean replace = nbt.contains("Replace") && nbt.getBoolean("Replace");
|
||||
List<BlockPos> selectedBlocks = getSelectedBlocks(item, world, player);
|
||||
applyPattern(selectedBlocks, item);
|
||||
|
||||
List<BlockPos> selectedBlocks = getSelectedBlocks(stack, world, player);
|
||||
PlacementPatterns.applyPattern(selectedBlocks, stack);
|
||||
Direction face = raytrace.getFace();
|
||||
|
||||
for (BlockPos placed : selectedBlocks) {
|
||||
if (world.getBlockState(placed) == stateToUse)
|
||||
if (world.getBlockState(placed) == selectedState)
|
||||
continue;
|
||||
if (!stateToUse.isValidPosition(world, placed))
|
||||
if (!selectedState.isValidPosition(world, placed))
|
||||
continue;
|
||||
if (!player.isCreative() && !canBreak(item, world.getBlockState(placed), world, placed))
|
||||
if (!player.isCreative() && !canBreak(stack, world.getBlockState(placed), world, placed))
|
||||
continue;
|
||||
if (!player.isCreative() && BlockHelper.findAndRemoveInInventory(stateToUse, player, 1) == 0) {
|
||||
player.getCooldownTracker().setCooldown(item.getItem(), 20);
|
||||
if (!player.isCreative() && BlockHelper.findAndRemoveInInventory(selectedState, player, 1) == 0) {
|
||||
player.getCooldownTracker().setCooldown(stack.getItem(), 20);
|
||||
player.sendStatusMessage(
|
||||
new StringTextComponent(TextFormatting.RED + Lang.translate("blockzapper.empty")), true);
|
||||
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!player.isCreative() && replace)
|
||||
dropBlocks(world, player, item, face, placed);
|
||||
dropBlocks(world, player, stack, face, placed);
|
||||
|
||||
for (Direction updateDirection : Direction.values())
|
||||
stateToUse = stateToUse.updatePostPlacement(updateDirection,
|
||||
selectedState = selectedState.updatePostPlacement(updateDirection,
|
||||
world.getBlockState(placed.offset(updateDirection)), world, placed,
|
||||
placed.offset(updateDirection));
|
||||
|
||||
BlockSnapshot blocksnapshot = BlockSnapshot.getBlockSnapshot(world, placed);
|
||||
IFluidState ifluidstate = world.getFluidState(placed);
|
||||
world.setBlockState(placed, ifluidstate.getBlockState(), 18);
|
||||
world.setBlockState(placed, stateToUse);
|
||||
world.setBlockState(placed, selectedState);
|
||||
if (ForgeEventFactory.onBlockPlace(player, blocksnapshot, Direction.UP)) {
|
||||
blocksnapshot.restore(true, false);
|
||||
return new ActionResult<ItemStack>(ActionResultType.FAIL, item);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (player instanceof ServerPlayerEntity)
|
||||
CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayerEntity) player, placed,
|
||||
new ItemStack(stateToUse.getBlock()));
|
||||
|
||||
new ItemStack(selectedState.getBlock()));
|
||||
}
|
||||
|
||||
applyCooldown(player, item, gunInOtherHand);
|
||||
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> player),
|
||||
new BlockzapperBeamPacket(barrelPos, raytrace.getHitVec(), hand, false));
|
||||
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player),
|
||||
new BlockzapperBeamPacket(barrelPos, raytrace.getHitVec(), hand, true));
|
||||
|
||||
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBlockDestroyed(ItemStack stack, World worldIn, BlockState state, BlockPos pos,
|
||||
LivingEntity entityLiving) {
|
||||
if (entityLiving instanceof PlayerEntity && ((PlayerEntity) entityLiving).isCreative()) {
|
||||
worldIn.setBlockState(pos, state);
|
||||
return false;
|
||||
}
|
||||
return super.onBlockDestroyed(stack, worldIn, state, pos, entityLiving);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEntitySwing(ItemStack stack, LivingEntity entity) {
|
||||
if (!(entity instanceof PlayerEntity))
|
||||
return false;
|
||||
if (entity.isSneaking())
|
||||
return true;
|
||||
|
||||
Vec3d start = entity.getPositionVec().add(0, entity.getEyeHeight(), 0);
|
||||
Vec3d range = entity.getLookVec().scale(getReachDistance(stack));
|
||||
BlockRayTraceResult raytrace = entity.world.rayTraceBlocks(
|
||||
new RayTraceContext(start, start.add(range), BlockMode.OUTLINE, FluidMode.NONE, entity));
|
||||
BlockPos pos = raytrace.getPos();
|
||||
if (pos == null)
|
||||
return true;
|
||||
|
||||
entity.world.sendBlockBreakProgress(entity.getEntityId(), pos, -1);
|
||||
BlockState newState = entity.world.getBlockState(pos);
|
||||
|
||||
if (BlockHelper.getRequiredItem(newState).isEmpty())
|
||||
return true;
|
||||
if (entity.world.getTileEntity(pos) != null)
|
||||
return true;
|
||||
if (newState.has(BlockStateProperties.DOUBLE_BLOCK_HALF))
|
||||
return true;
|
||||
if (newState.has(BlockStateProperties.ATTACHED))
|
||||
return true;
|
||||
if (newState.has(BlockStateProperties.HANGING))
|
||||
return true;
|
||||
if (newState.has(BlockStateProperties.BED_PART))
|
||||
return true;
|
||||
if (newState.has(BlockStateProperties.STAIRS_SHAPE))
|
||||
newState = newState.with(BlockStateProperties.STAIRS_SHAPE, StairsShape.STRAIGHT);
|
||||
if (newState.has(BlockStateProperties.PERSISTENT))
|
||||
newState = newState.with(BlockStateProperties.PERSISTENT, true);
|
||||
|
||||
if (stack.getTag().contains("BlockUsed")
|
||||
&& NBTUtil.readBlockState(stack.getTag().getCompound("BlockUsed")) == newState)
|
||||
return true;
|
||||
|
||||
stack.getTag().put("BlockUsed", NBTUtil.writeBlockState(newState));
|
||||
entity.world.playSound((PlayerEntity) entity, entity.getPosition(), AllSoundEvents.BLOCKZAPPER_CONFIRM.get(),
|
||||
SoundCategory.BLOCKS, 0.5f, 0.8f);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -322,38 +157,13 @@ public class BlockzapperItem extends ZapperItem implements IHaveCustomItemModel
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBlockStartBreak(ItemStack itemstack, BlockPos pos, PlayerEntity player) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUseDuration(ItemStack stack) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerStoppedUsing(ItemStack stack, World worldIn, LivingEntity entityLiving, int timeLeft) {
|
||||
super.onPlayerStoppedUsing(stack, worldIn, entityLiving, timeLeft);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
|
||||
boolean differentBlock = true;
|
||||
if (oldStack.hasTag() && newStack.hasTag() && oldStack.getTag().contains("BlockUsed")
|
||||
&& newStack.getTag().contains("BlockUsed"))
|
||||
differentBlock = NBTUtil.readBlockState(oldStack.getTag().getCompound("BlockUsed")) != NBTUtil
|
||||
.readBlockState(newStack.getTag().getCompound("BlockUsed"));
|
||||
return slotChanged || !AllItems.PLACEMENT_HANDGUN.typeOf(newStack) || differentBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
protected void openHandgunGUI(ItemStack handgun, boolean offhand) {
|
||||
ScreenOpener.open(new BlockzapperScreen(handgun, offhand));
|
||||
}
|
||||
|
||||
public static List<BlockPos> getSelectedBlocks(ItemStack stack, World worldIn, PlayerEntity player) {
|
||||
public List<BlockPos> getSelectedBlocks(ItemStack stack, World worldIn, PlayerEntity player) {
|
||||
List<BlockPos> list = new LinkedList<>();
|
||||
CompoundNBT tag = stack.getTag();
|
||||
if (tag == null)
|
||||
|
@ -368,7 +178,7 @@ public class BlockzapperItem extends ZapperItem implements IHaveCustomItemModel
|
|||
List<BlockPos> frontier = new LinkedList<>();
|
||||
|
||||
Vec3d start = player.getPositionVec().add(0, player.getEyeHeight(), 0);
|
||||
Vec3d range = player.getLookVec().scale(getReachDistance(stack));
|
||||
Vec3d range = player.getLookVec().scale(getRange(stack));
|
||||
BlockRayTraceResult raytrace = player.world.rayTraceBlocks(
|
||||
new RayTraceContext(start, start.add(range), BlockMode.COLLIDER, FluidMode.NONE, player));
|
||||
BlockPos pos = raytrace.getPos().toImmutable();
|
||||
|
@ -483,7 +293,8 @@ public class BlockzapperItem extends ZapperItem implements IHaveCustomItemModel
|
|||
return 20;
|
||||
}
|
||||
|
||||
public static int getReachDistance(ItemStack stack) {
|
||||
@Override
|
||||
protected int getRange(ItemStack stack) {
|
||||
ComponentTier tier = getTier(Components.Scope, stack);
|
||||
if (tier == ComponentTier.None)
|
||||
return 15;
|
||||
|
@ -495,37 +306,6 @@ public class BlockzapperItem extends ZapperItem implements IHaveCustomItemModel
|
|||
return 0;
|
||||
}
|
||||
|
||||
public static void applyPattern(List<BlockPos> blocksIn, ItemStack stack) {
|
||||
CompoundNBT tag = stack.getTag();
|
||||
PlacementPatterns pattern = !tag.contains("Pattern") ? PlacementPatterns.Solid
|
||||
: PlacementPatterns.valueOf(tag.getString("Pattern"));
|
||||
Random r = new Random();
|
||||
Predicate<BlockPos> filter = Predicates.alwaysFalse();
|
||||
|
||||
switch (pattern) {
|
||||
case Chance25:
|
||||
filter = pos -> r.nextBoolean() || r.nextBoolean();
|
||||
break;
|
||||
case Chance50:
|
||||
filter = pos -> r.nextBoolean();
|
||||
break;
|
||||
case Chance75:
|
||||
filter = pos -> r.nextBoolean() && r.nextBoolean();
|
||||
break;
|
||||
case Checkered:
|
||||
filter = pos -> (pos.getX() + pos.getY() + pos.getZ()) % 2 == 0;
|
||||
break;
|
||||
case InverseCheckered:
|
||||
filter = pos -> (pos.getX() + pos.getY() + pos.getZ()) % 2 != 0;
|
||||
break;
|
||||
case Solid:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
blocksIn.removeIf(filter);
|
||||
}
|
||||
|
||||
protected static void dropBlocks(World worldIn, PlayerEntity playerIn, ItemStack item, Direction face,
|
||||
BlockPos placed) {
|
||||
TileEntity tileentity = worldIn.getBlockState(placed).hasTileEntity() ? worldIn.getTileEntity(placed) : null;
|
||||
|
@ -554,6 +334,20 @@ public class BlockzapperItem extends ZapperItem implements IHaveCustomItemModel
|
|||
stack.getOrCreateTag().putString(component.name(), NBTHelper.writeEnum(tier));
|
||||
}
|
||||
|
||||
public static enum ComponentTier {
|
||||
None(TextFormatting.DARK_GRAY), Brass(TextFormatting.GOLD), Chromatic(TextFormatting.LIGHT_PURPLE);
|
||||
public TextFormatting color;
|
||||
|
||||
private ComponentTier(TextFormatting color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static enum Components {
|
||||
Body, Amplifier, Accelerator, Retriever, Scope
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(value = Dist.CLIENT)
|
||||
public CustomRenderedItemModel createModel(IBakedModel original) {
|
||||
|
|
|
@ -9,24 +9,22 @@ import static com.simibubi.create.modules.curiosities.zapper.blockzapper.Blockza
|
|||
import com.mojang.blaze3d.platform.GLX;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.modules.curiosities.zapper.ZapperRenderHandler;
|
||||
import com.simibubi.create.modules.curiosities.zapper.ZapperItemRenderer;
|
||||
import com.simibubi.create.modules.curiosities.zapper.blockzapper.BlockzapperItem.ComponentTier;
|
||||
import com.simibubi.create.modules.curiosities.zapper.blockzapper.BlockzapperItem.Components;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FourWayBlock;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||
import net.minecraft.client.renderer.ItemRenderer;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
|
||||
import net.minecraft.client.renderer.tileentity.ItemStackTileEntityRenderer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.util.HandSide;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class BlockzapperItemRenderer extends ItemStackTileEntityRenderer {
|
||||
public class BlockzapperItemRenderer extends ZapperItemRenderer {
|
||||
|
||||
@Override
|
||||
public void renderByItem(ItemStack stack) {
|
||||
|
@ -56,10 +54,10 @@ public class BlockzapperItemRenderer extends ItemStackTileEntityRenderer {
|
|||
boolean leftHanded = player.getPrimaryHand() == HandSide.LEFT;
|
||||
boolean mainHand = player.getHeldItemMainhand() == stack;
|
||||
boolean offHand = player.getHeldItemOffhand() == stack;
|
||||
float last = mainHand ^ leftHanded ? BlockzapperHandler.lastRightHandAnimation
|
||||
: BlockzapperHandler.lastLeftHandAnimation;
|
||||
float current = mainHand ^ leftHanded ? BlockzapperHandler.rightHandAnimation
|
||||
: BlockzapperHandler.leftHandAnimation;
|
||||
float last = mainHand ^ leftHanded ? ZapperRenderHandler.lastRightHandAnimation
|
||||
: ZapperRenderHandler.lastLeftHandAnimation;
|
||||
float current = mainHand ^ leftHanded ? ZapperRenderHandler.rightHandAnimation
|
||||
: ZapperRenderHandler.leftHandAnimation;
|
||||
float animation = MathHelper.clamp(MathHelper.lerp(pt, last, current) * 5, 0, 1);
|
||||
|
||||
// Core glows
|
||||
|
@ -90,22 +88,6 @@ public class BlockzapperItemRenderer extends ItemStackTileEntityRenderer {
|
|||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
public void renderBlockUsed(ItemStack stack, ItemRenderer itemRenderer) {
|
||||
BlockState state = NBTUtil.readBlockState(stack.getTag().getCompound("BlockUsed"));
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translatef(-0.3F, -0.45F, -0.0F);
|
||||
GlStateManager.scalef(0.25F, 0.25F, 0.25F);
|
||||
IBakedModel modelForState = Minecraft.getInstance().getBlockRendererDispatcher().getModelForState(state);
|
||||
|
||||
if (state.getBlock() instanceof FourWayBlock)
|
||||
modelForState = Minecraft.getInstance().getItemRenderer()
|
||||
.getModelWithOverrides(new ItemStack(state.getBlock()));
|
||||
|
||||
itemRenderer.renderItem(new ItemStack(state.getBlock()), modelForState);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
public void renderComponent(ItemStack stack, BlockzapperModel model, Components component,
|
||||
ItemRenderer itemRenderer) {
|
||||
ComponentTier tier = BlockzapperItem.getTier(component, stack);
|
||||
|
|
|
@ -1,48 +1,22 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.blockzapper;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.simibubi.create.AllPackets;
|
||||
import com.simibubi.create.ScreenResources;
|
||||
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
|
||||
import com.simibubi.create.foundation.gui.widgets.IconButton;
|
||||
import com.simibubi.create.foundation.gui.widgets.Indicator;
|
||||
import com.simibubi.create.foundation.gui.widgets.Indicator.State;
|
||||
import com.simibubi.create.foundation.gui.widgets.Label;
|
||||
import com.simibubi.create.foundation.gui.widgets.ScrollInput;
|
||||
import com.simibubi.create.foundation.packet.NbtPacket;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.modules.curiosities.zapper.ZapperScreen;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
|
||||
import net.minecraft.client.renderer.texture.AtlasTexture;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class BlockzapperScreen extends AbstractSimiScreen {
|
||||
public class BlockzapperScreen extends ZapperScreen {
|
||||
|
||||
private ItemStack item;
|
||||
private boolean offhand;
|
||||
private float animationProgress;
|
||||
|
||||
private final String title = Lang.translate("gui.blockzapper.title");
|
||||
private final String patternSection = Lang.translate("gui.blockzapper.patternSection");
|
||||
private final String needsUpgradedAmplifier = Lang.translate("gui.blockzapper.needsUpgradedAmplifier");
|
||||
|
||||
private IconButton replaceModeButton;
|
||||
|
@ -55,25 +29,19 @@ public class BlockzapperScreen extends AbstractSimiScreen {
|
|||
private ScrollInput spreadRangeInput;
|
||||
private Label spreadRangeLabel;
|
||||
|
||||
private Vector<IconButton> patternButtons;
|
||||
|
||||
public BlockzapperScreen(ItemStack handgun, boolean offhand) {
|
||||
super();
|
||||
item = handgun;
|
||||
this.offhand = offhand;
|
||||
public BlockzapperScreen(ItemStack zapper, boolean offhand) {
|
||||
super(ScreenResources.BLOCKZAPPER, zapper, offhand);
|
||||
title = Lang.translate("gui.blockzapper.title");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
animationProgress = 0;
|
||||
setWindowSize(ScreenResources.PLACEMENT_GUN.width + 40, ScreenResources.PLACEMENT_GUN.height);
|
||||
super.init();
|
||||
|
||||
int i = guiLeft - 20;
|
||||
int j = guiTop;
|
||||
CompoundNBT nbt = zapper.getOrCreateTag();
|
||||
|
||||
CompoundNBT nbt = item.getOrCreateTag();
|
||||
|
||||
widgets.clear();
|
||||
replaceModeIndicator = new Indicator(i + 51, j + 36, "");
|
||||
replaceModeButton = new IconButton(i + 51, j + 41, ScreenResources.I_REPLACE_SOLID);
|
||||
if (nbt.contains("Replace") && nbt.getBoolean("Replace"))
|
||||
|
@ -93,39 +61,22 @@ public class BlockzapperScreen extends AbstractSimiScreen {
|
|||
spreadMaterialButton.setToolTip(Lang.translate("gui.blockzapper.searchFuzzy"));
|
||||
|
||||
spreadRangeLabel = new Label(i + 119, j + 46, "").withShadow().withSuffix("m");
|
||||
spreadRangeInput = new ScrollInput(i + 115, j + 43, 22, 14).withRange(1, BlockzapperItem.getMaxAoe(item))
|
||||
spreadRangeInput = new ScrollInput(i + 115, j + 43, 22, 14).withRange(1, BlockzapperItem.getMaxAoe(zapper))
|
||||
.setState(1).titled(Lang.translate("gui.blockzapper.range")).writingTo(spreadRangeLabel);
|
||||
|
||||
if (nbt.contains("SearchDistance"))
|
||||
spreadRangeInput.setState(nbt.getInt("SearchDistance"));
|
||||
if (BlockzapperItem.getMaxAoe(item) == 2)
|
||||
if (BlockzapperItem.getMaxAoe(zapper) == 2)
|
||||
spreadRangeInput.getToolTip().add(1, TextFormatting.RED + needsUpgradedAmplifier);
|
||||
|
||||
Collections.addAll(widgets, replaceModeButton, replaceModeIndicator, spreadDiagonallyButton,
|
||||
spreadDiagonallyIndicator, spreadMaterialButton, spreadMaterialIndicator, spreadRangeLabel,
|
||||
spreadRangeInput);
|
||||
|
||||
patternButtons = new Vector<>(6);
|
||||
for (int row = 0; row <= 1; row++) {
|
||||
for (int col = 0; col <= 2; col++) {
|
||||
int id = patternButtons.size();
|
||||
PlacementPatterns pattern = PlacementPatterns.values()[id];
|
||||
patternButtons.add(new IconButton(i + 147 + col * 18, j + 23 + row * 18, pattern.icon));
|
||||
patternButtons.get(id).setToolTip(Lang.translate("gui.blockzapper.pattern." + pattern.translationKey));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (nbt.contains("Pattern"))
|
||||
patternButtons.get(PlacementPatterns.valueOf(nbt.getString("Pattern")).ordinal()).active = false;
|
||||
|
||||
widgets.addAll(patternButtons);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double x, double y, int button) {
|
||||
CompoundNBT nbt = item.getTag();
|
||||
CompoundNBT nbt = zapper.getTag();
|
||||
|
||||
if (replaceModeButton.isHovered()) {
|
||||
boolean mode = nbt.contains("Replace") && nbt.getBoolean("Replace");
|
||||
|
@ -148,91 +99,13 @@ public class BlockzapperScreen extends AbstractSimiScreen {
|
|||
nbt.putBoolean("SearchFuzzy", mode);
|
||||
}
|
||||
|
||||
for (IconButton patternButton : patternButtons) {
|
||||
if (patternButton.isHovered()) {
|
||||
patternButtons.forEach(b -> b.active = true);
|
||||
patternButton.active = false;
|
||||
patternButton.playDownSound(Minecraft.getInstance().getSoundHandler());
|
||||
nbt.putString("Pattern", PlacementPatterns.values()[patternButtons.indexOf(patternButton)].name());
|
||||
}
|
||||
}
|
||||
|
||||
return super.mouseClicked(x, y, button);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
CompoundNBT nbt = item.getTag();
|
||||
protected void writeAdditionalOptions(CompoundNBT nbt) {
|
||||
nbt.putInt("SearchDistance", spreadRangeInput.getState());
|
||||
AllPackets.channel.sendToServer(new NbtPacket(item, offhand ? -2 : -1));
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
animationProgress += 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderWindow(int mouseX, int mouseY, float partialTicks) {
|
||||
int i = guiLeft - 20;
|
||||
int j = guiTop;
|
||||
ScreenResources.PLACEMENT_GUN.draw(this, i, j);
|
||||
|
||||
font.drawStringWithShadow(title, i + 8, j + 10, 0xCCDDFF);
|
||||
font.drawString(patternSection, i + 148, j + 11, ScreenResources.FONT_COLOR);
|
||||
|
||||
minecraft.getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
|
||||
GlStateManager.enableBlend();
|
||||
|
||||
renderBlock();
|
||||
|
||||
GlStateManager.pushLightingAttributes();
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
RenderHelper.enableStandardItemLighting();
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.enableRescaleNormal();
|
||||
GlStateManager.enableAlphaTest();
|
||||
GlStateManager.alphaFunc(516, 0.1F);
|
||||
GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||
GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
|
||||
GlStateManager.translated((this.width - this.sWidth) / 2 + 260, this.height / 2 - this.sHeight / 4, 100);
|
||||
GlStateManager.rotatef(90 + 0.2f * animationProgress, 0, 1, 0);
|
||||
GlStateManager.rotatef(-40, .8f, 0, -.0f);
|
||||
GlStateManager.scaled(100, -100, 100);
|
||||
|
||||
IBakedModel model = itemRenderer.getModelWithOverrides(item);
|
||||
model.handlePerspective(TransformType.FIXED);
|
||||
itemRenderer.renderItem(item, model);
|
||||
|
||||
GlStateManager.disableAlphaTest();
|
||||
GlStateManager.disableRescaleNormal();
|
||||
GlStateManager.disableLighting();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
GlStateManager.popAttributes();
|
||||
}
|
||||
|
||||
private void renderBlock() {
|
||||
GlStateManager.pushMatrix();
|
||||
BufferBuilder buffer = Tessellator.getInstance().getBuffer();
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
|
||||
GlStateManager.translated(guiLeft + 1.7f, guiTop - 49, 120);
|
||||
GlStateManager.rotatef(-30f, .5f, .9f, -.1f);
|
||||
GlStateManager.scaled(20, -20, 20);
|
||||
|
||||
BlockState state = Blocks.BEACON.getDefaultState();
|
||||
if (item.hasTag() && item.getTag().contains("BlockUsed"))
|
||||
state = NBTUtil.readBlockState(item.getTag().getCompound("BlockUsed"));
|
||||
|
||||
minecraft.getBlockRendererDispatcher().renderBlock(state, new BlockPos(0, -5, 0), minecraft.world, buffer,
|
||||
minecraft.world.rand, EmptyModelData.INSTANCE);
|
||||
|
||||
Tessellator.getInstance().draw();
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.blockzapper;
|
||||
|
||||
import com.simibubi.create.ScreenResources;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
public enum PlacementPatterns {
|
||||
|
||||
Solid(ScreenResources.I_PATTERN_SOLID),
|
||||
Checkered(ScreenResources.I_PATTERN_CHECKERED),
|
||||
InverseCheckered(ScreenResources.I_PATTERN_CHECKERED_INVERSED),
|
||||
Chance25(ScreenResources.I_PATTERN_CHANCE_25),
|
||||
Chance50(ScreenResources.I_PATTERN_CHANCE_50),
|
||||
Chance75(ScreenResources.I_PATTERN_CHANCE_75);
|
||||
|
||||
public String translationKey;
|
||||
public ScreenResources icon;
|
||||
|
||||
private PlacementPatterns(ScreenResources icon) {
|
||||
this.translationKey = Lang.asId(name());
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.terrainzapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
|
||||
public abstract class Brush {
|
||||
|
||||
protected int param0;
|
||||
protected int param1;
|
||||
protected int param2;
|
||||
int amtParams;
|
||||
|
||||
public Brush(int amtParams) {
|
||||
this.amtParams = amtParams;
|
||||
}
|
||||
|
||||
public void set(int param0, int param1, int param2) {
|
||||
this.param0 = param0;
|
||||
this.param1 = param1;
|
||||
this.param2 = param2;
|
||||
}
|
||||
|
||||
int getMax(int paramIndex) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
int getMin(int paramIndex) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
String getParamLabel(int paramIndex) {
|
||||
return Lang
|
||||
.translate(paramIndex == 0 ? "generic.width" : paramIndex == 1 ? "generic.height" : "generic.length");
|
||||
}
|
||||
|
||||
public int get(int paramIndex) {
|
||||
return paramIndex == 0 ? param0 : paramIndex == 1 ? param1 : param2;
|
||||
}
|
||||
|
||||
public BlockPos getOffset(Vec3d ray, Direction face, PlacementOptions option) {
|
||||
return BlockPos.ZERO;
|
||||
}
|
||||
|
||||
abstract VoxelShape getSelectionBox();
|
||||
|
||||
abstract List<BlockPos> getIncludedPositions();
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.terrainzapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Direction.AxisDirection;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.util.math.shapes.VoxelShapes;
|
||||
|
||||
public class CuboidBrush extends Brush {
|
||||
|
||||
public static final int MAX_SIZE = 32;
|
||||
private VoxelShape shape;
|
||||
private List<BlockPos> positions;
|
||||
|
||||
public CuboidBrush() {
|
||||
super(3);
|
||||
shape = VoxelShapes.empty();
|
||||
positions = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int param0, int param1, int param2) {
|
||||
boolean updateShape = this.param0 != param0 || this.param1 != param1 || this.param2 != param2;
|
||||
super.set(param0, param1, param2);
|
||||
|
||||
if (updateShape) {
|
||||
BlockPos zero = BlockPos.ZERO;
|
||||
shape = VoxelShapes.create(new AxisAlignedBB(zero).grow(1 / 32f)
|
||||
.grow(((param0 - 1) / 2f), ((param1 - 1) / 2f), ((param2 - 1) / 2f))
|
||||
.offset((1 - param0 % 2) * .5f, (1 - param1 % 2) * .5f, (1 - param2 % 2) * .5f));
|
||||
positions = BlockPos
|
||||
.getAllInBox(zero.add((param0 - 1) / -2, (param1 - 1) / -2, (param2 - 1) / -2),
|
||||
zero.add((param0) / 2, (param1) / 2, (param2) / 2))
|
||||
.map(BlockPos::new).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
int getMin(int paramIndex) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
int getMax(int paramIndex) {
|
||||
return MAX_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getOffset(Vec3d ray, Direction face, PlacementOptions option) {
|
||||
if (option == PlacementOptions.Merged)
|
||||
return BlockPos.ZERO;
|
||||
|
||||
int offset =
|
||||
option == PlacementOptions.Attached ? face.getAxisDirection() == AxisDirection.NEGATIVE ? 2 : 1 : 0;
|
||||
int x = (param0 + (param0 == 0 ? 0 : offset)) / 2;
|
||||
int y = (param1 + (param1 == 0 ? 0 : offset)) / 2;
|
||||
int z = (param2 + (param2 == 0 ? 0 : offset)) / 2;
|
||||
|
||||
return BlockPos.ZERO.offset(face,
|
||||
face.getAxis().getCoordinate(x, y, z) * (option == PlacementOptions.Attached ? 1 : -1));
|
||||
}
|
||||
|
||||
@Override
|
||||
List<BlockPos> getIncludedPositions() {
|
||||
return positions;
|
||||
}
|
||||
|
||||
@Override
|
||||
VoxelShape getSelectionBox() {
|
||||
return shape;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.terrainzapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -7,45 +8,95 @@ import java.util.stream.Collectors;
|
|||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Direction.AxisDirection;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.util.math.shapes.VoxelShapes;
|
||||
|
||||
public class CylinderBrush {
|
||||
public class CylinderBrush extends Brush {
|
||||
|
||||
public static final int MAX_RADIUS = 6;
|
||||
public static final int MAX_HEIGHT = 6;
|
||||
public static final int MAX_HEIGHT = 8;
|
||||
private Map<Pair<Integer, Integer>, Pair<List<BlockPos>, VoxelShape>> cachedBrushes;
|
||||
|
||||
public CylinderBrush() {
|
||||
super(2);
|
||||
|
||||
cachedBrushes = new HashMap<>();
|
||||
VoxelShape fullCube = VoxelShapes.fullCube();
|
||||
VoxelShape fullCube = Block.makeCuboidShape(-.5f, -.5f, -.5f, 16.5f, 16.5f, 16.5f);
|
||||
|
||||
for (int i = 0; i <= MAX_RADIUS; i++) {
|
||||
int radius = i;
|
||||
VoxelShape shape = VoxelShapes.empty();
|
||||
List<BlockPos> positions = BlockPos.getAllInBox(BlockPos.ZERO.add(-i, 0, -i), BlockPos.ZERO.add(i, 0, i))
|
||||
.filter(p -> p.withinDistance(BlockPos.ZERO, radius)).collect(Collectors.toList());
|
||||
List<BlockPos> positions =
|
||||
BlockPos.getAllInBox(BlockPos.ZERO.add(-i - 1, 0, -i - 1), BlockPos.ZERO.add(i + 1, 0, i + 1))
|
||||
.map(BlockPos::new).filter(p -> VecHelper.getCenterOf(p)
|
||||
.distanceTo(VecHelper.getCenterOf(BlockPos.ZERO)) < radius + .42f)
|
||||
.collect(Collectors.toList());
|
||||
for (BlockPos p : positions)
|
||||
shape = VoxelShapes.or(shape, fullCube.withOffset(p.getX(), p.getY(), p.getZ()));
|
||||
for (int h = 0; h <= MAX_HEIGHT; h++) {
|
||||
List<BlockPos> stackedPositions = new ArrayList<>();
|
||||
VoxelShape stackedShape = shape.simplify();
|
||||
for (int layer = 0; layer <= layer; i++)
|
||||
stackedShape = VoxelShapes.or(stackedShape, shape.withOffset(0, layer - h / 2, 0));
|
||||
cachedBrushes.put(Pair.of(i, h), Pair.of(positions, stackedShape.simplify()));
|
||||
for (int layer = 0; layer < h; layer++) {
|
||||
int yOffset = layer - h / 2;
|
||||
stackedShape = VoxelShapes.or(stackedShape, shape.withOffset(0, yOffset, 0));
|
||||
for (BlockPos p : positions)
|
||||
stackedPositions.add(p.up(yOffset));
|
||||
}
|
||||
cachedBrushes.put(Pair.of(i, h), Pair.of(stackedPositions, stackedShape.simplify()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public VoxelShape getSelectionBox(int radius, int height) {
|
||||
return get(radius, height).getRight();
|
||||
@Override
|
||||
public BlockPos getOffset(Vec3d ray, Direction face, PlacementOptions option) {
|
||||
if (option == PlacementOptions.Merged)
|
||||
return BlockPos.ZERO;
|
||||
|
||||
int offset = option == PlacementOptions.Attached ? 0 : -1;
|
||||
boolean negative = face.getAxisDirection() == AxisDirection.NEGATIVE;
|
||||
int yOffset = option == PlacementOptions.Attached ? negative ? 1 : 2 : negative ? 0 : -1;
|
||||
int r = (param0 + 1 + offset);
|
||||
int y = (param1 + (param1 == 0 ? 0 : yOffset)) / 2;
|
||||
|
||||
return BlockPos.ZERO.offset(face,
|
||||
(face.getAxis().isVertical() ? y : r) * (option == PlacementOptions.Attached ? 1 : -1));
|
||||
}
|
||||
|
||||
public List<BlockPos> getIncludedPositions(int radius, int height) {
|
||||
return get(radius, height).getLeft();
|
||||
@Override
|
||||
int getMax(int paramIndex) {
|
||||
return paramIndex == 0 ? MAX_RADIUS : MAX_HEIGHT;
|
||||
}
|
||||
|
||||
protected Pair<List<BlockPos>, VoxelShape> get(int radius, int height) {
|
||||
@Override
|
||||
int getMin(int paramIndex) {
|
||||
return paramIndex == 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
String getParamLabel(int paramIndex) {
|
||||
return paramIndex == 0 ? Lang.translate("generic.radius") : super.getParamLabel(paramIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
VoxelShape getSelectionBox() {
|
||||
return getEntry(param0, param1).getRight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockPos> getIncludedPositions() {
|
||||
return getEntry(param0, param1).getLeft();
|
||||
}
|
||||
|
||||
protected Pair<List<BlockPos>, VoxelShape> getEntry(int radius, int height) {
|
||||
return cachedBrushes.get(Pair.of(Integer.valueOf(radius), Integer.valueOf(height)));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.terrainzapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FlowingFluidBlock;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class FlattenTool {
|
||||
|
||||
// gaussian with sig=1
|
||||
static float[][] kernel = {
|
||||
|
||||
{ 0.003765f, 0.015019f, 0.023792f, 0.015019f, 0.003765f },
|
||||
{ 0.015019f, 0.059912f, 0.094907f, 0.059912f, 0.015019f },
|
||||
{ 0.023792f, 0.094907f, 0.150342f, 0.094907f, 0.023792f },
|
||||
{ 0.015019f, 0.059912f, 0.094907f, 0.059912f, 0.015019f },
|
||||
{ 0.003765f, 0.015019f, 0.023792f, 0.015019f, 0.003765f },
|
||||
|
||||
};
|
||||
|
||||
private static int[][] applyKernel(int[][] values) {
|
||||
int[][] result = new int[values.length][values[0].length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
for (int j = 0; j < values[i].length; j++) {
|
||||
int value = values[i][j];
|
||||
float newValue = 0;
|
||||
for (int iOffset = -2; iOffset <= 2; iOffset++) {
|
||||
for (int jOffset = -2; jOffset <= 2; jOffset++) {
|
||||
int iTarget = i + iOffset;
|
||||
int jTarget = j + jOffset;
|
||||
int ref = 0;
|
||||
if (iTarget < 0 || iTarget >= values.length || jTarget < 0 || jTarget >= values[0].length)
|
||||
ref = value;
|
||||
else
|
||||
ref = values[iTarget][jTarget];
|
||||
if (ref == Integer.MIN_VALUE)
|
||||
ref = value;
|
||||
newValue += kernel[iOffset + 2][jOffset + 2] * ref;
|
||||
}
|
||||
}
|
||||
result[i][j] = MathHelper.floor(newValue + .5f);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void apply(World world, List<BlockPos> targetPositions, Direction facing) {
|
||||
List<BlockPos> surfaces = new ArrayList<>();
|
||||
Map<Pair<Integer, Integer>, Integer> heightMap = new HashMap<>();
|
||||
int offset = facing.getAxisDirection().getOffset();
|
||||
|
||||
int minEntry = Integer.MAX_VALUE;
|
||||
int minCoord1 = Integer.MAX_VALUE;
|
||||
int minCoord2 = Integer.MAX_VALUE;
|
||||
int maxEntry = Integer.MIN_VALUE;
|
||||
int maxCoord1 = Integer.MIN_VALUE;
|
||||
int maxCoord2 = Integer.MIN_VALUE;
|
||||
|
||||
for (BlockPos p : targetPositions) {
|
||||
Pair<Integer, Integer> coords = getCoords(p, facing);
|
||||
BlockState belowSurface = world.getBlockState(p);
|
||||
|
||||
minCoord1 = Math.min(minCoord1, coords.getKey());
|
||||
minCoord2 = Math.min(minCoord2, coords.getValue());
|
||||
maxCoord1 = Math.max(maxCoord1, coords.getKey());
|
||||
maxCoord2 = Math.max(maxCoord2, coords.getValue());
|
||||
|
||||
if (TerrainTools.isReplaceable(belowSurface)) {
|
||||
if (!heightMap.containsKey(coords))
|
||||
heightMap.put(coords, Integer.MIN_VALUE);
|
||||
continue;
|
||||
}
|
||||
|
||||
p = p.offset(facing);
|
||||
BlockState surface = world.getBlockState(p);
|
||||
|
||||
if (!TerrainTools.isReplaceable(surface)) {
|
||||
if (!heightMap.containsKey(coords) || heightMap.get(coords).equals(Integer.MIN_VALUE))
|
||||
heightMap.put(coords, Integer.MAX_VALUE);
|
||||
continue;
|
||||
}
|
||||
|
||||
surfaces.add(p);
|
||||
int coordinate = facing.getAxis().getCoordinate(p.getX(), p.getY(), p.getZ());
|
||||
if (!heightMap.containsKey(coords) || heightMap.get(coords).equals(Integer.MAX_VALUE)
|
||||
|| heightMap.get(coords).equals(Integer.MIN_VALUE)
|
||||
|| heightMap.get(coords) * offset < coordinate * offset) {
|
||||
heightMap.put(coords, coordinate);
|
||||
maxEntry = Math.max(maxEntry, coordinate);
|
||||
minEntry = Math.min(minEntry, coordinate);
|
||||
}
|
||||
}
|
||||
|
||||
if (surfaces.isEmpty())
|
||||
return;
|
||||
|
||||
// fill heightmap
|
||||
int[][] heightMapArray = new int[maxCoord1 - minCoord1 + 1][maxCoord2 - minCoord2 + 1];
|
||||
for (int i = 0; i < heightMapArray.length; i++) {
|
||||
for (int j = 0; j < heightMapArray[i].length; j++) {
|
||||
Pair<Integer, Integer> pair = Pair.of(minCoord1 + i, minCoord2 + j);
|
||||
if (!heightMap.containsKey(pair)) {
|
||||
heightMapArray[i][j] = Integer.MIN_VALUE;
|
||||
continue;
|
||||
}
|
||||
Integer height = heightMap.get(pair);
|
||||
if (height.equals(Integer.MAX_VALUE)) {
|
||||
heightMapArray[i][j] = offset == 1 ? maxEntry + 2 : minEntry - 2;
|
||||
continue;
|
||||
}
|
||||
if (height.equals(Integer.MIN_VALUE)) {
|
||||
heightMapArray[i][j] = offset == 1 ? minEntry - 2 : maxEntry + 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
heightMapArray[i][j] = height;
|
||||
}
|
||||
}
|
||||
|
||||
heightMapArray = applyKernel(heightMapArray);
|
||||
|
||||
for (BlockPos p : surfaces) {
|
||||
Pair<Integer, Integer> coords = getCoords(p, facing);
|
||||
int surfaceCoord = facing.getAxis().getCoordinate(p.getX(), p.getY(), p.getZ()) * offset;
|
||||
int targetCoord = heightMapArray[coords.getKey() - minCoord1][coords.getValue() - minCoord2] * offset;
|
||||
|
||||
// Keep surface
|
||||
if (surfaceCoord == targetCoord)
|
||||
continue;
|
||||
|
||||
// Lower surface
|
||||
BlockState blockState = world.getBlockState(p);
|
||||
int timeOut = 1000;
|
||||
while (surfaceCoord > targetCoord) {
|
||||
BlockPos below = p.offset(facing.getOpposite());
|
||||
world.setBlockState(below, blockState);
|
||||
world.setBlockState(p, blockState.getFluidState().getBlockState());
|
||||
p = p.offset(facing.getOpposite());
|
||||
surfaceCoord--;
|
||||
if (timeOut-- <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// Raise surface
|
||||
while (surfaceCoord < targetCoord) {
|
||||
BlockPos above = p.offset(facing);
|
||||
if (!(blockState.getBlock() instanceof FlowingFluidBlock))
|
||||
world.setBlockState(above, blockState);
|
||||
world.setBlockState(p, world.getBlockState(p.offset(facing.getOpposite())));
|
||||
p = p.offset(facing);
|
||||
surfaceCoord++;
|
||||
if (timeOut-- <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static Pair<Integer, Integer> getCoords(BlockPos pos, Direction facing) {
|
||||
switch (facing.getAxis()) {
|
||||
case X:
|
||||
return Pair.of(pos.getZ(), pos.getY());
|
||||
case Y:
|
||||
return Pair.of(pos.getX(), pos.getZ());
|
||||
case Z:
|
||||
return Pair.of(pos.getX(), pos.getY());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.terrainzapper;
|
||||
|
||||
import com.simibubi.create.ScreenResources;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
public enum PlacementOptions {
|
||||
|
||||
Merged(ScreenResources.I_CENTERED),
|
||||
Attached(ScreenResources.I_ATTACHED),
|
||||
Inserted(ScreenResources.I_INSERTED);
|
||||
|
||||
public String translationKey;
|
||||
public ScreenResources icon;
|
||||
|
||||
private PlacementOptions(ScreenResources icon) {
|
||||
this.translationKey = Lang.asId(name());
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
}
|
|
@ -7,23 +7,34 @@ import java.util.stream.Collectors;
|
|||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.util.math.shapes.VoxelShapes;
|
||||
|
||||
public class SphereBrush {
|
||||
public class SphereBrush extends Brush {
|
||||
|
||||
public static final int MAX_RADIUS = 6;
|
||||
private Map<Integer, Pair<List<BlockPos>, VoxelShape>> cachedBrushes;
|
||||
|
||||
public SphereBrush() {
|
||||
super(1);
|
||||
|
||||
cachedBrushes = new HashMap<>();
|
||||
for (int i = 0; i <= MAX_RADIUS; i++) {
|
||||
int radius = i;
|
||||
VoxelShape shape = VoxelShapes.empty();
|
||||
List<BlockPos> positions = BlockPos.getAllInBox(BlockPos.ZERO.add(-i, -i, -i), BlockPos.ZERO.add(i, i, i))
|
||||
.filter(p -> p.withinDistance(BlockPos.ZERO, radius)).collect(Collectors.toList());
|
||||
VoxelShape fullCube = VoxelShapes.fullCube();
|
||||
List<BlockPos> positions =
|
||||
BlockPos.getAllInBox(BlockPos.ZERO.add(-i - 1, -i - 1, -i - 1), BlockPos.ZERO.add(i + 1, i + 1, i + 1))
|
||||
.map(BlockPos::new).filter(p -> VecHelper.getCenterOf(p)
|
||||
.distanceTo(VecHelper.getCenterOf(BlockPos.ZERO)) < radius + .5f)
|
||||
.collect(Collectors.toList());
|
||||
VoxelShape fullCube = Block.makeCuboidShape(-.5f, -.5f, -.5f, 16.5f, 16.5f, 16.5f);
|
||||
for (BlockPos p : positions)
|
||||
shape = VoxelShapes.or(shape, fullCube.withOffset(p.getX(), p.getY(), p.getZ()));
|
||||
shape = shape.simplify();
|
||||
|
@ -31,15 +42,38 @@ public class SphereBrush {
|
|||
}
|
||||
}
|
||||
|
||||
public VoxelShape getSelectionBox(int size) {
|
||||
return get(size).getRight();
|
||||
@Override
|
||||
public BlockPos getOffset(Vec3d ray, Direction face, PlacementOptions option) {
|
||||
if (option == PlacementOptions.Merged)
|
||||
return BlockPos.ZERO;
|
||||
|
||||
int offset = option == PlacementOptions.Attached ? 0 : -1;
|
||||
int r = (param0 + 1 + offset);
|
||||
|
||||
return BlockPos.ZERO.offset(face, r * (option == PlacementOptions.Attached ? 1 : -1));
|
||||
}
|
||||
|
||||
public List<BlockPos> getIncludedPositions(int size) {
|
||||
return get(size).getLeft();
|
||||
@Override
|
||||
int getMax(int paramIndex) {
|
||||
return MAX_RADIUS;
|
||||
}
|
||||
|
||||
protected Pair<List<BlockPos>, VoxelShape> get(int size) {
|
||||
@Override
|
||||
VoxelShape getSelectionBox() {
|
||||
return getEntry(param0).getRight();
|
||||
}
|
||||
|
||||
@Override
|
||||
String getParamLabel(int paramIndex) {
|
||||
return Lang.translate("generic.radius");
|
||||
}
|
||||
|
||||
@Override
|
||||
List<BlockPos> getIncludedPositions() {
|
||||
return getEntry(param0).getLeft();
|
||||
}
|
||||
|
||||
protected Pair<List<BlockPos>, VoxelShape> getEntry(int size) {
|
||||
return cachedBrushes.get(Integer.valueOf(size));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.terrainzapper;
|
||||
|
||||
public enum TerrainBrushes {
|
||||
|
||||
Cuboid(new CuboidBrush()),
|
||||
Sphere(new SphereBrush()),
|
||||
Cylinder(new CylinderBrush()),
|
||||
|
||||
;
|
||||
|
||||
private Brush brush;
|
||||
|
||||
private TerrainBrushes(Brush brush) {
|
||||
this.brush = brush;
|
||||
}
|
||||
|
||||
public Brush get() {
|
||||
// if (this == Cylinder)
|
||||
// brush = new CylinderBrush();
|
||||
// if (this == Sphere)
|
||||
// brush = new SphereBrush();
|
||||
return brush;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.terrainzapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.simibubi.create.ScreenResources;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public enum TerrainTools {
|
||||
|
||||
Fill(ScreenResources.I_FILL),
|
||||
Place(ScreenResources.I_PLACE),
|
||||
Replace(ScreenResources.I_REPLACE),
|
||||
Clear(ScreenResources.I_CLEAR),
|
||||
Overlay(ScreenResources.I_OVERLAY),
|
||||
Flatten(ScreenResources.I_FLATTEN);
|
||||
|
||||
public String translationKey;
|
||||
public ScreenResources icon;
|
||||
|
||||
private TerrainTools(ScreenResources icon) {
|
||||
this.translationKey = Lang.asId(name());
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
public boolean requiresSelectedBlock() {
|
||||
return this != Clear && this != Flatten;
|
||||
}
|
||||
|
||||
public void run(World world, List<BlockPos> targetPositions, Direction facing, @Nullable BlockState paintedState) {
|
||||
switch (this) {
|
||||
case Clear:
|
||||
targetPositions.forEach(p -> world.setBlockState(p, Blocks.AIR.getDefaultState()));
|
||||
break;
|
||||
case Fill:
|
||||
targetPositions.forEach(p -> {
|
||||
BlockState toReplace = world.getBlockState(p);
|
||||
if (!isReplaceable(toReplace))
|
||||
return;
|
||||
world.setBlockState(p, paintedState);
|
||||
});
|
||||
break;
|
||||
case Flatten:
|
||||
FlattenTool.apply(world, targetPositions, facing);
|
||||
break;
|
||||
case Overlay:
|
||||
targetPositions.forEach(p -> {
|
||||
BlockState toOverlay = world.getBlockState(p);
|
||||
if (isReplaceable(toOverlay))
|
||||
return;
|
||||
if (toOverlay == paintedState)
|
||||
return;
|
||||
|
||||
p = p.up();
|
||||
|
||||
BlockState toReplace = world.getBlockState(p);
|
||||
if (!isReplaceable(toReplace))
|
||||
return;
|
||||
world.setBlockState(p, paintedState);
|
||||
});
|
||||
break;
|
||||
case Place:
|
||||
targetPositions.forEach(p -> {
|
||||
world.setBlockState(p, paintedState);
|
||||
});
|
||||
break;
|
||||
case Replace:
|
||||
targetPositions.forEach(p -> {
|
||||
BlockState toReplace = world.getBlockState(p);
|
||||
if (isReplaceable(toReplace))
|
||||
return;
|
||||
world.setBlockState(p, paintedState);
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isReplaceable(BlockState toReplace) {
|
||||
return toReplace.getMaterial().isReplaceable();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.terrainzapper;
|
||||
|
||||
import com.simibubi.create.modules.curiosities.zapper.ZapperItem;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class TerrainZapperItem extends ZapperItem {
|
||||
|
||||
public TerrainZapperItem(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void openHandgunGUI(ItemStack item, boolean b) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getCooldownDelay(ItemStack item) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.terrainzapper;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
import com.simibubi.create.foundation.utility.TessellatorHelper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.RayTraceContext;
|
||||
import net.minecraft.util.math.RayTraceContext.BlockMode;
|
||||
import net.minecraft.util.math.RayTraceContext.FluidMode;
|
||||
import net.minecraft.util.math.RayTraceResult.Type;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
|
||||
public class TerrainZapperRenderHandler {
|
||||
|
||||
private static VoxelShape renderedShape;
|
||||
private static BlockPos renderedPosition;
|
||||
|
||||
public static void tick() {
|
||||
ClientPlayerEntity player = Minecraft.getInstance().player;
|
||||
ItemStack heldMain = player.getHeldItemMainhand();
|
||||
ItemStack heldOff = player.getHeldItemOffhand();
|
||||
boolean zapperInMain = AllItems.TERRAIN_ZAPPER.typeOf(heldMain);
|
||||
boolean zapperInOff = AllItems.TERRAIN_ZAPPER.typeOf(heldOff);
|
||||
|
||||
if (zapperInMain) {
|
||||
CompoundNBT tag = heldMain.getOrCreateTag();
|
||||
if (!tag.contains("_Swap")) {
|
||||
createBrushOutline(tag, player, heldMain);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (zapperInOff) {
|
||||
CompoundNBT tag = heldOff.getOrCreateTag();
|
||||
createBrushOutline(tag, player, heldOff);
|
||||
return;
|
||||
}
|
||||
|
||||
renderedPosition = null;
|
||||
}
|
||||
|
||||
public static void createBrushOutline(CompoundNBT tag, ClientPlayerEntity player, ItemStack zapper) {
|
||||
if (!tag.contains("BrushParams")) {
|
||||
renderedPosition = null;
|
||||
return;
|
||||
}
|
||||
|
||||
Brush brush = NBTHelper.readEnum(tag.getString("Brush"), TerrainBrushes.class).get();
|
||||
PlacementOptions placement = NBTHelper.readEnum(tag.getString("Placement"), PlacementOptions.class);
|
||||
BlockPos params = NBTUtil.readBlockPos(tag.getCompound("BrushParams"));
|
||||
brush.set(params.getX(), params.getY(), params.getZ());
|
||||
renderedShape = brush.getSelectionBox();
|
||||
|
||||
Vec3d start = player.getPositionVec().add(0, player.getEyeHeight(), 0);
|
||||
Vec3d range = player.getLookVec().scale(128);
|
||||
BlockRayTraceResult raytrace = player.world.rayTraceBlocks(
|
||||
new RayTraceContext(start, start.add(range), BlockMode.OUTLINE, FluidMode.NONE, player));
|
||||
if (raytrace == null || raytrace.getType() == Type.MISS) {
|
||||
renderedPosition = null;
|
||||
return;
|
||||
}
|
||||
|
||||
BlockPos pos = raytrace.getPos();
|
||||
renderedPosition = pos.add(brush.getOffset(player.getLookVec(), raytrace.getFace(), placement));
|
||||
}
|
||||
|
||||
public static void render() {
|
||||
if (renderedPosition == null)
|
||||
return;
|
||||
|
||||
GlStateManager.lineWidth(2);
|
||||
TessellatorHelper.prepareForDrawing();
|
||||
GlStateManager.disableTexture();
|
||||
|
||||
GlStateManager.translated(renderedPosition.getX(), renderedPosition.getY(), renderedPosition.getZ());
|
||||
WorldRenderer.drawShape(renderedShape, 0, 0, 0, 0f, 0f, 0f, 0.5f);
|
||||
|
||||
GlStateManager.enableTexture();
|
||||
TessellatorHelper.cleanUpAfterDrawing();
|
||||
GlStateManager.lineWidth(1);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.terrainzapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.foundation.block.render.CustomRenderedItemModel;
|
||||
import com.simibubi.create.foundation.gui.ScreenOpener;
|
||||
import com.simibubi.create.foundation.item.IHaveCustomItemModel;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
import com.simibubi.create.modules.curiosities.zapper.PlacementPatterns;
|
||||
import com.simibubi.create.modules.curiosities.zapper.ZapperItem;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public class TerrainzapperItem extends ZapperItem implements IHaveCustomItemModel {
|
||||
|
||||
public TerrainzapperItem(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void openHandgunGUI(ItemStack item, boolean b) {
|
||||
ScreenOpener.open(new TerrainzapperScreen(item, b));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRange(ItemStack stack) {
|
||||
return 128;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getCooldownDelay(ItemStack item) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(value = Dist.CLIENT)
|
||||
public CustomRenderedItemModel createModel(IBakedModel original) {
|
||||
return new TerrainzapperModel(original);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String validateUsage(ItemStack item) {
|
||||
if (!item.getOrCreateTag().contains("BrushParams"))
|
||||
return Lang.translate("terrainzapper.shiftRightClickToSet");
|
||||
return super.validateUsage(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canActivateWithoutSelectedBlock(ItemStack stack) {
|
||||
CompoundNBT tag = stack.getOrCreateTag();
|
||||
TerrainTools tool = NBTHelper.readEnum(tag.getString("Tool"), TerrainTools.class);
|
||||
return !tool.requiresSelectedBlock();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean activate(World world, PlayerEntity player, ItemStack stack, BlockState stateToUse,
|
||||
BlockRayTraceResult raytrace) {
|
||||
|
||||
BlockPos targetPos = raytrace.getPos();
|
||||
List<BlockPos> affectedPositions = new ArrayList<>();
|
||||
|
||||
CompoundNBT tag = stack.getOrCreateTag();
|
||||
Brush brush = NBTHelper.readEnum(tag.getString("Brush"), TerrainBrushes.class).get();
|
||||
BlockPos params = NBTUtil.readBlockPos(tag.getCompound("BrushParams"));
|
||||
PlacementOptions option = NBTHelper.readEnum(tag.getString("Placement"), PlacementOptions.class);
|
||||
TerrainTools tool = NBTHelper.readEnum(tag.getString("Tool"), TerrainTools.class);
|
||||
|
||||
brush.set(params.getX(), params.getY(), params.getZ());
|
||||
targetPos = targetPos.add(brush.getOffset(player.getLookVec(), raytrace.getFace(), option));
|
||||
for (BlockPos blockPos : brush.getIncludedPositions())
|
||||
affectedPositions.add(targetPos.add(blockPos));
|
||||
PlacementPatterns.applyPattern(affectedPositions, stack);
|
||||
tool.run(world, affectedPositions, raytrace.getFace(), stateToUse);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.terrainzapper;
|
||||
|
||||
import com.mojang.blaze3d.platform.GLX;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.modules.curiosities.zapper.ZapperRenderHandler;
|
||||
import com.simibubi.create.modules.curiosities.zapper.ZapperItemRenderer;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||
import net.minecraft.client.renderer.ItemRenderer;
|
||||
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.HandSide;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class TerrainzapperItemRenderer extends ZapperItemRenderer {
|
||||
|
||||
@Override
|
||||
public void renderByItem(ItemStack stack) {
|
||||
ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
|
||||
TerrainzapperModel mainModel = (TerrainzapperModel) itemRenderer.getModelWithOverrides(stack);
|
||||
float pt = Minecraft.getInstance().getRenderPartialTicks();
|
||||
float worldTime = AnimationTickHolder.getRenderTick() / 20;
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translatef(0.5F, 0.5F, 0.5F);
|
||||
float lastCoordx = GLX.lastBrightnessX;
|
||||
float lastCoordy = GLX.lastBrightnessY;
|
||||
GLX.glMultiTexCoord2f(GLX.GL_TEXTURE1, Math.min(lastCoordx + 60, 240), Math.min(lastCoordy + 120, 240));
|
||||
itemRenderer.renderItem(stack, mainModel.getBakedModel());
|
||||
|
||||
// Block indicator
|
||||
if (mainModel.getCurrentPerspective() == TransformType.GUI && stack.hasTag()
|
||||
&& stack.getTag().contains("BlockUsed"))
|
||||
renderBlockUsed(stack, itemRenderer);
|
||||
|
||||
ClientPlayerEntity player = Minecraft.getInstance().player;
|
||||
boolean leftHanded = player.getPrimaryHand() == HandSide.LEFT;
|
||||
boolean mainHand = player.getHeldItemMainhand() == stack;
|
||||
boolean offHand = player.getHeldItemOffhand() == stack;
|
||||
float last = mainHand ^ leftHanded ? ZapperRenderHandler.lastRightHandAnimation
|
||||
: ZapperRenderHandler.lastLeftHandAnimation;
|
||||
float current = mainHand ^ leftHanded ? ZapperRenderHandler.rightHandAnimation
|
||||
: ZapperRenderHandler.leftHandAnimation;
|
||||
float animation = MathHelper.clamp(MathHelper.lerp(pt, last, current) * 5, 0, 1);
|
||||
|
||||
// Core glows
|
||||
GlStateManager.disableLighting();
|
||||
float multiplier = MathHelper.sin(worldTime * 5);
|
||||
if (mainHand || offHand) {
|
||||
multiplier = animation;
|
||||
}
|
||||
|
||||
GLX.glMultiTexCoord2f(GLX.GL_TEXTURE1, multiplier * 240, 120);
|
||||
itemRenderer.renderItem(stack, mainModel.getPartial("terrain_core"));
|
||||
GLX.glMultiTexCoord2f(GLX.GL_TEXTURE1, lastCoordx, lastCoordy);
|
||||
GlStateManager.enableLighting();
|
||||
|
||||
// Accelerator spins
|
||||
float angle = worldTime * -25;
|
||||
if (mainHand || offHand)
|
||||
angle += 360 * animation;
|
||||
|
||||
angle %= 360;
|
||||
float offset = -.155f;
|
||||
GlStateManager.translatef(0, offset, 0);
|
||||
GlStateManager.rotatef(angle, 0, 0, 1);
|
||||
GlStateManager.translatef(0, -offset, 0);
|
||||
itemRenderer.renderItem(stack, mainModel.getPartial("terrain_accelerator"));
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.terrainzapper;
|
||||
|
||||
import com.simibubi.create.foundation.block.render.CustomRenderedItemModel;
|
||||
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.tileentity.ItemStackTileEntityRenderer;
|
||||
|
||||
public class TerrainzapperModel extends CustomRenderedItemModel {
|
||||
|
||||
public TerrainzapperModel(IBakedModel template) {
|
||||
super(template, "blockzapper");
|
||||
addPartials("terrain_core", "terrain_accelerator");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStackTileEntityRenderer createRenderer() {
|
||||
return new TerrainzapperItemRenderer();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
package com.simibubi.create.modules.curiosities.zapper.terrainzapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import com.simibubi.create.ScreenResources;
|
||||
import com.simibubi.create.foundation.gui.widgets.IconButton;
|
||||
import com.simibubi.create.foundation.gui.widgets.Label;
|
||||
import com.simibubi.create.foundation.gui.widgets.ScrollInput;
|
||||
import com.simibubi.create.foundation.gui.widgets.SelectionScrollInput;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
import com.simibubi.create.modules.curiosities.zapper.ZapperScreen;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class TerrainzapperScreen extends ZapperScreen {
|
||||
|
||||
protected final String placementSection = Lang.translate("gui.terrainzapper.placement");
|
||||
protected final String toolSection = Lang.translate("gui.terrainzapper.tool");
|
||||
protected final List<String> brushOptions =
|
||||
Lang.translatedOptions("gui.terrainzapper.brush", "cuboid", "sphere", "cylinder");
|
||||
|
||||
protected Vector<IconButton> toolButtons;
|
||||
protected Vector<IconButton> placementButtons;
|
||||
|
||||
protected ScrollInput brushInput;
|
||||
protected Label brushLabel;
|
||||
protected Vector<ScrollInput> brushParams;
|
||||
protected Vector<Label> brushParamLabels;
|
||||
private int i;
|
||||
private int j;
|
||||
private CompoundNBT nbt;
|
||||
|
||||
public TerrainzapperScreen(ItemStack zapper, boolean offhand) {
|
||||
super(ScreenResources.TERRAINZAPPER, zapper, offhand);
|
||||
brightColor = 0xDFF6FF;
|
||||
fontColor = 0x436B77;
|
||||
title = Lang.translate("gui.terrainzapper.title");
|
||||
nbt = zapper.getOrCreateTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
|
||||
i = guiLeft - 20;
|
||||
j = guiTop;
|
||||
|
||||
brushLabel = new Label(i + 58, j + 28, "").withShadow();
|
||||
brushInput = new SelectionScrollInput(i + 55, j + 25, 78, 14).forOptions(brushOptions)
|
||||
.titled(Lang.translate("gui.terrainzapper.brush")).writingTo(brushLabel).calling(this::brushChanged);
|
||||
if (nbt.contains("Brush"))
|
||||
brushInput.setState(NBTHelper.readEnum(nbt.getString("Brush"), TerrainBrushes.class).ordinal());
|
||||
|
||||
widgets.add(brushLabel);
|
||||
widgets.add(brushInput);
|
||||
initBrushParams();
|
||||
|
||||
toolButtons = new Vector<>(6);
|
||||
TerrainTools[] toolValues = TerrainTools.values();
|
||||
for (int id = 0; id < toolValues.length; id++) {
|
||||
TerrainTools tool = toolValues[id];
|
||||
toolButtons.add(new IconButton(i + 8 + id * 18, j + 76, tool.icon));
|
||||
toolButtons.get(id).setToolTip(Lang.translate("gui.terrainzapper.tool." + tool.translationKey));
|
||||
}
|
||||
|
||||
if (nbt.contains("Tool"))
|
||||
toolButtons.get(NBTHelper.readEnum(nbt.getString("Tool"), TerrainTools.class).ordinal()).active = false;
|
||||
widgets.addAll(toolButtons);
|
||||
|
||||
placementButtons = new Vector<>(3);
|
||||
PlacementOptions[] placementValues = PlacementOptions.values();
|
||||
for (int id = 0; id < placementValues.length; id++) {
|
||||
PlacementOptions option = placementValues[id];
|
||||
placementButtons.add(new IconButton(i + 147 + id * 18, j + 76, option.icon));
|
||||
placementButtons.get(id).setToolTip(Lang.translate("gui.terrainzapper.placement." + option.translationKey));
|
||||
}
|
||||
|
||||
if (nbt.contains("Placement"))
|
||||
placementButtons
|
||||
.get(NBTHelper.readEnum(nbt.getString("Placement"), PlacementOptions.class).ordinal()).active =
|
||||
false;
|
||||
widgets.addAll(placementButtons);
|
||||
|
||||
}
|
||||
|
||||
public void initBrushParams() {
|
||||
if (brushParams != null) {
|
||||
nbt.put("BrushParams", NBTUtil.writeBlockPos(new BlockPos(brushParams.get(0).getState(),
|
||||
brushParams.get(1).getState(), brushParams.get(2).getState())));
|
||||
|
||||
widgets.removeAll(brushParamLabels);
|
||||
widgets.removeAll(brushParams);
|
||||
}
|
||||
|
||||
brushParamLabels = new Vector<>(3);
|
||||
brushParams = new Vector<>(3);
|
||||
BlockPos data = NBTUtil.readBlockPos(nbt.getCompound("BrushParams"));
|
||||
int[] params = new int[] { data.getX(), data.getY(), data.getZ() };
|
||||
Brush currentBrush = TerrainBrushes.values()[brushInput.getState()].get();
|
||||
for (int index = 0; index < 3; index++) {
|
||||
|
||||
Label label = new Label(i + 62 + 18 * index, j + 46, "").withShadow();
|
||||
brushParamLabels.add(label);
|
||||
int indexFinal = index;
|
||||
ScrollInput input = new ScrollInput(i + 55 + 18 * index, j + 43, 14, 14)
|
||||
.withRange(currentBrush.getMin(index), currentBrush.getMax(index) + 1).writingTo(label)
|
||||
.titled(currentBrush.getParamLabel(index)).calling(state -> {
|
||||
label.x = i + 62 + 18 * indexFinal - font.getStringWidth(label.text) / 2;
|
||||
});
|
||||
input.setState(params[index]);
|
||||
input.onChanged();
|
||||
if (index >= currentBrush.amtParams) {
|
||||
input.visible = false;
|
||||
label.visible = false;
|
||||
input.active = false;
|
||||
}
|
||||
|
||||
brushParams.add(input);
|
||||
}
|
||||
|
||||
widgets.addAll(brushParamLabels);
|
||||
widgets.addAll(brushParams);
|
||||
}
|
||||
|
||||
private void brushChanged(int brushIndex) {
|
||||
initBrushParams();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double x, double y, int button) {
|
||||
CompoundNBT nbt = zapper.getTag();
|
||||
|
||||
for (IconButton placementButton : placementButtons) {
|
||||
if (placementButton.isHovered()) {
|
||||
placementButtons.forEach(b -> b.active = true);
|
||||
placementButton.active = false;
|
||||
placementButton.playDownSound(Minecraft.getInstance().getSoundHandler());
|
||||
nbt.putString("Placement", PlacementOptions.values()[placementButtons.indexOf(placementButton)].name());
|
||||
}
|
||||
}
|
||||
|
||||
for (IconButton toolButton : toolButtons) {
|
||||
if (toolButton.isHovered()) {
|
||||
toolButtons.forEach(b -> b.active = true);
|
||||
toolButton.active = false;
|
||||
toolButton.playDownSound(Minecraft.getInstance().getSoundHandler());
|
||||
nbt.putString("Tool", TerrainTools.values()[toolButtons.indexOf(toolButton)].name());
|
||||
}
|
||||
}
|
||||
|
||||
return super.mouseClicked(x, y, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawOnBackground(int i, int j) {
|
||||
super.drawOnBackground(i, j);
|
||||
|
||||
Brush currentBrush = TerrainBrushes.values()[brushInput.getState()].get();
|
||||
for (int index = 2; index >= currentBrush.amtParams; index--) {
|
||||
ScreenResources.TERRAINZAPPER_INACTIVE_PARAM.draw(i + 55 + index * 18, j + 43);
|
||||
}
|
||||
|
||||
font.drawString(toolSection, i + 8, j + 64, fontColor);
|
||||
font.drawString(placementSection, i + 148, j + 64, fontColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeAdditionalOptions(CompoundNBT nbt) {
|
||||
super.writeAdditionalOptions(nbt);
|
||||
nbt.putString("Brush", NBTHelper.writeEnum(TerrainBrushes.values()[brushInput.getState()]));
|
||||
nbt.put("BrushParams", NBTUtil.writeBlockPos(new BlockPos(brushParams.get(0).getState(),
|
||||
brushParams.get(1).getState(), brushParams.get(2).getState())));
|
||||
}
|
||||
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
"item.create.symmetry_wand": "Staff of Symmetry",
|
||||
"item.create.placement_handgun": "Handheld Blockzapper",
|
||||
"item.create.terrain_zapper": "Handheld Worldshaper",
|
||||
"item.create.tree_fertilizer": "Tree Fertilizer",
|
||||
"item.create.empty_blueprint": "Empty Schematic",
|
||||
"item.create.andesite_alloy": "Andesite Alloy",
|
||||
|
@ -298,6 +299,9 @@
|
|||
|
||||
"create.generic.range": "Range",
|
||||
"create.generic.radius": "Radius",
|
||||
"create.generic.width": "Width",
|
||||
"create.generic.height": "Height",
|
||||
"create.generic.length": "Length",
|
||||
"create.generic.speed": "Speed",
|
||||
"create.generic.delay": "Delay",
|
||||
"create.generic.unit.ticks": "Ticks",
|
||||
|
@ -340,7 +344,7 @@
|
|||
"create.gui.blockzapper.searchFuzzy": "Ignore Material Borders",
|
||||
"create.gui.blockzapper.range": "Spread Range",
|
||||
"create.gui.blockzapper.needsUpgradedAmplifier": "Requires Upgraded Amplifier",
|
||||
"create.gui.blockzapper.patternSection": "Patterns",
|
||||
"create.gui.blockzapper.patternSection": "Pattern",
|
||||
"create.gui.blockzapper.pattern.solid": "Solid",
|
||||
"create.gui.blockzapper.pattern.checkered": "Checkerboard",
|
||||
"create.gui.blockzapper.pattern.inversecheckered": "Inversed Checkerboard",
|
||||
|
@ -348,6 +352,24 @@
|
|||
"create.gui.blockzapper.pattern.chance50": "50% Roll",
|
||||
"create.gui.blockzapper.pattern.chance75": "75% Roll",
|
||||
|
||||
"create.gui.terrainzapper.title": "Handheld Worldshaper",
|
||||
"create.gui.terrainzapper.placement": "Placement",
|
||||
"create.gui.terrainzapper.placement.merged": "Merged",
|
||||
"create.gui.terrainzapper.placement.attached": "Attached",
|
||||
"create.gui.terrainzapper.placement.inserted": "Inserted",
|
||||
"create.gui.terrainzapper.brush": "Brush",
|
||||
"create.gui.terrainzapper.brush.cuboid": "Cuboid",
|
||||
"create.gui.terrainzapper.brush.sphere": "Sphere",
|
||||
"create.gui.terrainzapper.brush.cylinder": "Cylinder",
|
||||
"create.gui.terrainzapper.tool": "Tool",
|
||||
"create.gui.terrainzapper.tool.fill": "Fill",
|
||||
"create.gui.terrainzapper.tool.place": "Place",
|
||||
"create.gui.terrainzapper.tool.replace": "Replace",
|
||||
"create.gui.terrainzapper.tool.clear": "Clear",
|
||||
"create.gui.terrainzapper.tool.overlay": "Overlay",
|
||||
"create.gui.terrainzapper.tool.flatten": "Flatten",
|
||||
"create.terrainzapper.shiftRightClickToSet": "Shift-Right-Click to Select a Shape",
|
||||
|
||||
"create.blockzapper.usingBlock": "Using: %1$s",
|
||||
"create.blockzapper.componentUpgrades": "Component Upgrades:",
|
||||
"create.blockzapper.component.body": "Body",
|
||||
|
@ -668,6 +690,15 @@
|
|||
"item.create.placement_handgun.tooltip.control3": "R-Click while Sneaking",
|
||||
"item.create.placement_handgun.tooltip.action3": "Opens the _Configuration_ _Interface_",
|
||||
|
||||
"item.create.terrain_zapper.tooltip": "HANDHELD WORLDSHAPER",
|
||||
"item.create.terrain_zapper.tooltip.summary": "Handy tool for creating _landscapes_ and _terrain_ _features._",
|
||||
"item.create.terrain_zapper.tooltip.control1": "L-Click at Block",
|
||||
"item.create.terrain_zapper.tooltip.action1": "Sets blocks placed by the tool to the targeted block.",
|
||||
"item.create.terrain_zapper.tooltip.control2": "R-Click at Block",
|
||||
"item.create.terrain_zapper.tooltip.action2": "Applies the currently selected _Brush_ and _Tool_ at the targeted location.",
|
||||
"item.create.terrain_zapper.tooltip.control3": "R-Click while Sneaking",
|
||||
"item.create.terrain_zapper.tooltip.action3": "Opens the _Configuration_ _Interface_",
|
||||
|
||||
"item.create.tree_fertilizer.tooltip": "TREE FERTILIZER",
|
||||
"item.create.tree_fertilizer.tooltip.summary": "A powerful combination of minerals suitable for growing common tree types more quickly",
|
||||
"item.create.tree_fertilizer.tooltip.condition1": "When used on Sapling",
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "create:item/placement_handgun",
|
||||
"textures": {
|
||||
"cog": "block/prismarine_bricks",
|
||||
"particle": "block/obsidian"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "Cog",
|
||||
"from": [7.5, 3, 11],
|
||||
"to": [8.5, 8, 14],
|
||||
"faces": {
|
||||
"north": {"uv": [6, 7, 7, 12], "texture": "#cog"},
|
||||
"east": {"uv": [5, 3, 8, 8], "texture": "#cog"},
|
||||
"south": {"uv": [4, 4, 5, 9], "texture": "#cog"},
|
||||
"west": {"uv": [4, 6, 7, 11], "texture": "#cog"},
|
||||
"up": {"uv": [4, 6, 5, 9], "texture": "#cog"},
|
||||
"down": {"uv": [5, 6, 6, 9], "texture": "#cog"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Cog",
|
||||
"from": [7.5, 3, 11],
|
||||
"to": [8.5, 8, 14],
|
||||
"rotation": {"angle": 45, "axis": "z", "origin": [8, 5.5, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [6, 7, 7, 12], "texture": "#cog"},
|
||||
"east": {"uv": [5, 3, 8, 8], "texture": "#cog"},
|
||||
"south": {"uv": [4, 4, 5, 9], "texture": "#cog"},
|
||||
"west": {"uv": [4, 6, 7, 11], "texture": "#cog"},
|
||||
"up": {"uv": [4, 6, 5, 9], "texture": "#cog"},
|
||||
"down": {"uv": [5, 6, 6, 9], "texture": "#cog"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Cog",
|
||||
"from": [7.5, 3, 11],
|
||||
"to": [8.5, 8, 14],
|
||||
"rotation": {"angle": -45, "axis": "z", "origin": [8, 5.5, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [6, 7, 7, 12], "texture": "#cog"},
|
||||
"east": {"uv": [5, 3, 8, 8], "texture": "#cog"},
|
||||
"south": {"uv": [4, 4, 5, 9], "texture": "#cog"},
|
||||
"west": {"uv": [4, 6, 7, 11], "texture": "#cog"},
|
||||
"up": {"uv": [4, 6, 5, 9], "texture": "#cog"},
|
||||
"down": {"uv": [5, 6, 6, 9], "texture": "#cog"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Cog",
|
||||
"from": [5.5, 5, 11],
|
||||
"to": [10.5, 6, 14],
|
||||
"faces": {
|
||||
"north": {"uv": [6, 7, 11, 8], "texture": "#cog"},
|
||||
"east": {"uv": [5, 3, 8, 4], "texture": "#cog"},
|
||||
"south": {"uv": [4, 4, 9, 5], "texture": "#cog"},
|
||||
"west": {"uv": [4, 6, 7, 7], "texture": "#cog"},
|
||||
"up": {"uv": [4, 6, 9, 9], "texture": "#cog"},
|
||||
"down": {"uv": [5, 6, 10, 9], "texture": "#cog"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"display": {
|
||||
"thirdperson_righthand": {
|
||||
"rotation": [1, 0, 0],
|
||||
"translation": [0, 4, -2.5],
|
||||
"scale": [0.8, 0.8, 0.8]
|
||||
},
|
||||
"thirdperson_lefthand": {
|
||||
"rotation": [1, 0, 0],
|
||||
"translation": [0, 4, -2.5],
|
||||
"scale": [0.8, 0.8, 0.8]
|
||||
},
|
||||
"firstperson_righthand": {
|
||||
"rotation": [10, 0, 10],
|
||||
"translation": [1, 4, 1]
|
||||
},
|
||||
"firstperson_lefthand": {
|
||||
"rotation": [10, 0, 10],
|
||||
"translation": [1, 4, 1]
|
||||
},
|
||||
"ground": {
|
||||
"rotation": [0, 0, 90],
|
||||
"translation": [-2.25, -1, -0.75],
|
||||
"scale": [0.75, 0.75, 0.75]
|
||||
},
|
||||
"gui": {
|
||||
"rotation": [30, 45, 0],
|
||||
"translation": [-0.5, 3.5, 0]
|
||||
},
|
||||
"fixed": {
|
||||
"rotation": [0, 90, 0],
|
||||
"translation": [-1.25, 4.25, -1]
|
||||
}
|
||||
},
|
||||
"groups": [
|
||||
{
|
||||
"name": "accelerator",
|
||||
"origin": [8, 8, 8],
|
||||
"children": [0, 1, 2, 3]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "create:item/placement_handgun",
|
||||
"textures": {
|
||||
"2": "block/white_concrete_powder",
|
||||
"3": "block/white_stained_glass",
|
||||
"particle": "block/obsidian"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "Core",
|
||||
"from": [6.8, 5, 0.7],
|
||||
"to": [9.2, 6, 10.7],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8.5, 8, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [6, 5, 8.4, 6], "texture": "#2"},
|
||||
"east": {"uv": [3, 5, 13, 6], "texture": "#2"},
|
||||
"west": {"uv": [3, 7, 13, 8], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Core Glow",
|
||||
"from": [6.6, 4.6, 0.5],
|
||||
"to": [9.4, 6.4, 10.4],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8.5, 8, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [6, 7, 8.8, 8.8], "texture": "#3"},
|
||||
"east": {"uv": [3, 7, 12.9, 8.8], "texture": "#3"},
|
||||
"south": {"uv": [5, 7, 7.8, 8.8], "texture": "#3"},
|
||||
"west": {"uv": [4, 7, 13.9, 8.8], "texture": "#3"},
|
||||
"up": {"uv": [7, 3, 9.8, 12.9], "texture": "#3"},
|
||||
"down": {"uv": [7, 4, 9.8, 13.9], "texture": "#3"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Amplifier Core",
|
||||
"from": [6.8, 3, 2.7],
|
||||
"to": [9.2, 4, 7.7],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8.5, 8, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [6, 5, 8.4, 6], "texture": "#2"},
|
||||
"east": {"uv": [3, 5, 8, 6], "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2.4, 1], "texture": "#2"},
|
||||
"west": {"uv": [3, 7, 8, 8], "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2.4, 5], "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2.4, 5], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Amplifier Core Glow",
|
||||
"from": [6.6, 2.6, 2.5],
|
||||
"to": [9.4, 4.4, 7.4],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8.5, 8, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [6, 7, 8.8, 8.8], "texture": "#3"},
|
||||
"east": {"uv": [3, 7, 7.9, 8.8], "texture": "#3"},
|
||||
"south": {"uv": [5, 7, 7.8, 8.8], "texture": "#3"},
|
||||
"west": {"uv": [4, 7, 8.9, 8.8], "texture": "#3"},
|
||||
"up": {"uv": [7, 3, 9.8, 7.9], "texture": "#3"},
|
||||
"down": {"uv": [7, 4, 9.8, 8.9], "texture": "#3"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"display": {
|
||||
"thirdperson_righthand": {
|
||||
"rotation": [1, 0, 0],
|
||||
"translation": [0, 4, -2.5],
|
||||
"scale": [0.8, 0.8, 0.8]
|
||||
},
|
||||
"thirdperson_lefthand": {
|
||||
"rotation": [1, 0, 0],
|
||||
"translation": [0, 4, -2.5],
|
||||
"scale": [0.8, 0.8, 0.8]
|
||||
},
|
||||
"firstperson_righthand": {
|
||||
"rotation": [10, 0, 10],
|
||||
"translation": [1, 4, 1]
|
||||
},
|
||||
"firstperson_lefthand": {
|
||||
"rotation": [10, 0, 10],
|
||||
"translation": [1, 4, 1]
|
||||
},
|
||||
"ground": {
|
||||
"rotation": [0, 0, 90],
|
||||
"translation": [-2.25, -1, -0.75],
|
||||
"scale": [0.75, 0.75, 0.75]
|
||||
},
|
||||
"gui": {
|
||||
"rotation": [30, 45, 0],
|
||||
"translation": [-0.5, 3.5, 0]
|
||||
},
|
||||
"fixed": {
|
||||
"rotation": [0, 90, 0],
|
||||
"translation": [-1.25, 4.25, -1]
|
||||
}
|
||||
},
|
||||
"groups": [
|
||||
{
|
||||
"name": "core",
|
||||
"origin": [8, 8, 8],
|
||||
"children": [0, 1]
|
||||
},
|
||||
{
|
||||
"name": "core",
|
||||
"origin": [8, 8, 8],
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"name": "amplifier_core",
|
||||
"origin": [8, 8, 8],
|
||||
"children": [2, 3]
|
||||
}
|
||||
]
|
||||
}
|
243
src/main/resources/assets/create/models/item/terrain_zapper.json
Normal file
243
src/main/resources/assets/create/models/item/terrain_zapper.json
Normal file
|
@ -0,0 +1,243 @@
|
|||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "create:item/placement_handgun",
|
||||
"textures": {
|
||||
"0": "create:block/andesite_alloy_mesh",
|
||||
"1": "block/smooth_stone_slab_side",
|
||||
"particle": "block/obsidian",
|
||||
"3_0": "block/obsidian",
|
||||
"mesh": "create:block/terrain_zapper_mesh"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "Connector",
|
||||
"from": [6.5, 4, 0],
|
||||
"to": [9.5, 5, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 3, 1], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 11, 1], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 3, 1], "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 11, 1], "texture": "#0"},
|
||||
"up": {"uv": [0, 0, 3, 11], "texture": "#0"},
|
||||
"down": {"uv": [0, 0, 3, 11], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Rod Back Cap",
|
||||
"from": [6.5, 4, 14],
|
||||
"to": [9.5, 7, 15],
|
||||
"rotation": {"angle": -45, "axis": "z", "origin": [8, 5.5, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 3, 3], "texture": "#mesh"},
|
||||
"east": {"uv": [8, 13, 9, 16], "texture": "#mesh"},
|
||||
"south": {"uv": [2, 7, 5, 10], "texture": "#mesh"},
|
||||
"west": {"uv": [2, 8, 3, 11], "texture": "#mesh"},
|
||||
"up": {"uv": [3, 9, 6, 10], "texture": "#mesh"},
|
||||
"down": {"uv": [7, 7, 10, 8], "texture": "#mesh"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Rod Back Cap",
|
||||
"from": [7, 4.5, 15],
|
||||
"to": [9, 6.5, 17],
|
||||
"rotation": {"angle": -45, "axis": "z", "origin": [8, 5.5, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 2, 2], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 2, 2], "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 2, 2], "texture": "#0"},
|
||||
"up": {"uv": [0, 0, 2, 2], "texture": "#0"},
|
||||
"down": {"uv": [0, 0, 2, 2], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Connector",
|
||||
"from": [6.5, 6, 0],
|
||||
"to": [9.5, 7, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 3, 1], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 11, 1], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 3, 1], "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 11, 1], "texture": "#0"},
|
||||
"up": {"uv": [0, 0, 3, 11], "texture": "#0"},
|
||||
"down": {"uv": [0, 0, 3, 11], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Connector",
|
||||
"from": [5.75, 4, 6],
|
||||
"to": [10.25, 8, 8],
|
||||
"rotation": {"angle": 45, "axis": "x", "origin": [8, 4, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 4.5, 4], "texture": "#mesh"},
|
||||
"east": {"uv": [12, 3, 16, 5], "rotation": 90, "texture": "#mesh"},
|
||||
"south": {"uv": [4, 7, 8.5, 11], "texture": "#mesh"},
|
||||
"west": {"uv": [0, 3, 4, 5], "rotation": 270, "texture": "#mesh"},
|
||||
"up": {"uv": [5, 3, 9.5, 5], "texture": "#mesh"},
|
||||
"down": {"uv": [5, 3, 9.5, 5], "texture": "#mesh"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Connector",
|
||||
"from": [5.75, 4, 8],
|
||||
"to": [10.25, 6, 10],
|
||||
"rotation": {"angle": 45, "axis": "x", "origin": [8, 4, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 4.5, 2], "texture": "#mesh"},
|
||||
"east": {"uv": [12, 3, 14, 5], "rotation": 180, "texture": "#mesh"},
|
||||
"south": {"uv": [5, 3, 9.5, 5], "rotation": 180, "texture": "#mesh"},
|
||||
"west": {"uv": [4, 3, 6, 5], "rotation": 180, "texture": "#mesh"},
|
||||
"up": {"uv": [5, 4, 9.5, 6], "texture": "#mesh"},
|
||||
"down": {"uv": [0, 3, 4.5, 5], "texture": "#mesh"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Rod Back Cap",
|
||||
"from": [6, 4.5, 9],
|
||||
"to": [10, 6.5, 11],
|
||||
"rotation": {"angle": 0, "axis": "z", "origin": [8, 5.5, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 4, 2], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 2, 2], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 4, 2], "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 2, 2], "texture": "#0"},
|
||||
"up": {"uv": [0, 0, 4, 2], "texture": "#0"},
|
||||
"down": {"uv": [0, 0, 4, 2], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Grip",
|
||||
"from": [7.1, 1, 12],
|
||||
"to": [8.9, 5, 15],
|
||||
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 2, 14]},
|
||||
"faces": {
|
||||
"north": {"uv": [5, 7, 6.8, 11], "texture": "#1"},
|
||||
"east": {"uv": [13, 7, 16, 11], "texture": "#1"},
|
||||
"south": {"uv": [7, 7, 8.8, 11], "texture": "#1"},
|
||||
"west": {"uv": [16, 7, 13, 11], "texture": "#1"},
|
||||
"up": {"uv": [5, 2, 6.8, 5], "texture": "#1"},
|
||||
"down": {"uv": [7, 11, 8.8, 14], "texture": "#1"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Trigger",
|
||||
"from": [7.4, 3, 11],
|
||||
"to": [8.6, 6, 13],
|
||||
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 2, 14]},
|
||||
"faces": {
|
||||
"north": {"uv": [6, 4, 7, 7], "texture": "#3_0"},
|
||||
"east": {"uv": [6, 4, 8, 7], "texture": "#3_0"},
|
||||
"south": {"uv": [6, 4, 7, 7], "texture": "#3_0"},
|
||||
"west": {"uv": [5, 4, 7, 7], "texture": "#3_0"},
|
||||
"up": {"uv": [6, 6, 7, 8], "texture": "#3_0"},
|
||||
"down": {"uv": [5, 6, 6, 8], "texture": "#3_0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Scope",
|
||||
"from": [7.5, 7.5, 5.5],
|
||||
"to": [8.5, 8.5, 10.5],
|
||||
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, 4]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 1, 1], "texture": "#1"},
|
||||
"east": {"uv": [8, 1, 9, 6], "rotation": 90, "texture": "#mesh"},
|
||||
"south": {"uv": [0, 0, 1, 1], "texture": "#1"},
|
||||
"west": {"uv": [7, 1, 8, 6], "rotation": 270, "texture": "#mesh"},
|
||||
"up": {"uv": [7, 1, 8, 6], "texture": "#mesh"},
|
||||
"down": {"uv": [7, 1, 8, 6], "texture": "#mesh"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Scope Connector",
|
||||
"from": [7.5, 7, 7],
|
||||
"to": [8.5, 8, 8],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 1, 1], "texture": "#mesh"},
|
||||
"east": {"uv": [0, 0, 1, 1], "texture": "#mesh"},
|
||||
"south": {"uv": [0, 0, 1, 1], "texture": "#mesh"},
|
||||
"west": {"uv": [0, 0, 1, 1], "texture": "#mesh"},
|
||||
"up": {"uv": [0, 0, 1, 1], "texture": "#mesh"},
|
||||
"down": {"uv": [0, 0, 1, 1], "texture": "#mesh"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Amplifier Connector",
|
||||
"from": [6.5, 2, 2],
|
||||
"to": [9.5, 3, 9],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8.5, 8, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [3, 8, 6, 9], "texture": "#mesh"},
|
||||
"east": {"uv": [0, 12, 7, 13], "rotation": 180, "texture": "#mesh"},
|
||||
"south": {"uv": [1, 8, 4, 9], "texture": "#mesh"},
|
||||
"west": {"uv": [0, 12, 7, 13], "rotation": 180, "texture": "#mesh"},
|
||||
"up": {"uv": [3, 7, 10, 10], "rotation": 90, "texture": "#mesh"},
|
||||
"down": {"uv": [3, 7, 10, 10], "rotation": 90, "texture": "#mesh"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Amplifier Connector",
|
||||
"from": [6.5, 3, 7],
|
||||
"to": [9.5, 4, 9],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8.5, 8, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 3, 1], "texture": "#mesh"},
|
||||
"east": {"uv": [0, 0, 2, 1], "texture": "#mesh"},
|
||||
"south": {"uv": [0, 0, 3, 1], "texture": "#mesh"},
|
||||
"west": {"uv": [0, 0, 2, 1], "texture": "#mesh"},
|
||||
"up": {"uv": [0, 0, 3, 2], "texture": "#mesh"},
|
||||
"down": {"uv": [0, 0, 3, 2], "texture": "#mesh"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"display": {
|
||||
"thirdperson_righthand": {
|
||||
"rotation": [1, 0, 0],
|
||||
"translation": [0, 4, -2.5],
|
||||
"scale": [0.8, 0.8, 0.8]
|
||||
},
|
||||
"thirdperson_lefthand": {
|
||||
"rotation": [1, 0, 0],
|
||||
"translation": [0, 4, -2.5],
|
||||
"scale": [0.8, 0.8, 0.8]
|
||||
},
|
||||
"firstperson_righthand": {
|
||||
"rotation": [10, 0, 10],
|
||||
"translation": [1, 4, 1]
|
||||
},
|
||||
"firstperson_lefthand": {
|
||||
"rotation": [10, 0, 10],
|
||||
"translation": [1, 4, 1]
|
||||
},
|
||||
"ground": {
|
||||
"rotation": [0, 0, 90],
|
||||
"translation": [-2.25, -1, -0.75],
|
||||
"scale": [0.75, 0.75, 0.75]
|
||||
},
|
||||
"gui": {
|
||||
"rotation": [30, 45, 0],
|
||||
"translation": [-0.5, 3.5, 0]
|
||||
},
|
||||
"fixed": {
|
||||
"rotation": [0, 90, 0],
|
||||
"translation": [-1.25, 4.25, -1]
|
||||
}
|
||||
},
|
||||
"groups": [0, 1, 2, 3, 4, 5, 6,
|
||||
{
|
||||
"name": "placement_handgun",
|
||||
"origin": [8, 8, 8],
|
||||
"children": [7, 8]
|
||||
},
|
||||
{
|
||||
"name": "chorus_scope",
|
||||
"origin": [8, 8, 8],
|
||||
"children": [9, 10]
|
||||
},
|
||||
{
|
||||
"name": "chorus_amplifier",
|
||||
"origin": [8, 8, 8],
|
||||
"children": [11, 12]
|
||||
}
|
||||
]
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 620 B |
Binary file not shown.
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.9 KiB |
BIN
src/main/resources/assets/create/textures/gui/zapper.png
Normal file
BIN
src/main/resources/assets/create/textures/gui/zapper.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
Loading…
Reference in a new issue