Proper Directions

- Added layer of abstraction for Directional Blocks
- Added Cocoa Logs
- Added improved item tooltip framework
This commit is contained in:
simibubi 2019-08-18 17:02:29 +02:00
parent 4cfd7a1bb9
commit ce7356798c
26 changed files with 508 additions and 127 deletions

View file

@ -21,6 +21,7 @@ import com.simibubi.create.modules.contraptions.relays.CogWheelBlock;
import com.simibubi.create.modules.contraptions.relays.EncasedBeltBlock;
import com.simibubi.create.modules.contraptions.relays.GearboxBlock;
import com.simibubi.create.modules.contraptions.relays.GearshifterBlock;
import com.simibubi.create.modules.gardens.CocoaLogBlock;
import com.simibubi.create.modules.schematics.block.CreativeCrateBlock;
import com.simibubi.create.modules.schematics.block.SchematicTableBlock;
import com.simibubi.create.modules.schematics.block.SchematicannonBlock;
@ -81,6 +82,9 @@ public enum AllBlocks {
SYMMETRY_CROSSPLANE(new CrossPlaneSymmetryBlock()),
SYMMETRY_TRIPLEPLANE(new TriplePlaneSymmetryBlock()),
// Gardens
COCOA_LOG(new CocoaLogBlock()),
// Palettes
ANDESITE_BRICKS(new Block(Properties.from(Blocks.ANDESITE))),
DIORITE_BRICKS(new Block(Properties.from(Blocks.DIORITE))),

View file

@ -1,10 +1,10 @@
package com.simibubi.create;
import com.simibubi.create.modules.contraptions.relays.BeltItem;
import com.simibubi.create.modules.curiosities.item.TreeFertilizerItem;
import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunItem;
import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunItemRenderer;
import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunModel;
import com.simibubi.create.modules.gardens.TreeFertilizerItem;
import com.simibubi.create.modules.schematics.item.BlueprintAndQuillItem;
import com.simibubi.create.modules.schematics.item.BlueprintItem;
import com.simibubi.create.modules.symmetry.SymmetryWandItem;

View file

@ -0,0 +1,38 @@
package com.simibubi.create.foundation.block;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.DirectionalBlock;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
public class ProperDirectionalBlock extends DirectionalBlock {
protected ProperDirectionalBlock(Properties p_i48415_1_) {
super(p_i48415_1_);
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(FACING);
super.fillStateContainer(builder);
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
return getDefaultState().with(FACING, context.getNearestLookingDirection());
}
@Override
public BlockState rotate(BlockState state, Rotation rot) {
return state.with(FACING, rot.rotate(state.get(FACING)));
}
@Override
public BlockState mirror(BlockState state, Mirror mirrorIn) {
return state.rotate(mirrorIn.toRotation(state.get(FACING)));
}
}

View file

@ -0,0 +1,39 @@
package com.simibubi.create.foundation.item;
import java.util.List;
import com.simibubi.create.foundation.utility.ItemDescription;
import com.simibubi.create.foundation.utility.ItemDescription.Palette;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public abstract class ItemWithToolTip extends Item {
protected TooltipCache tooltip;
public ItemWithToolTip(Properties properties) {
super(properties);
tooltip = new TooltipCache();
}
@Override
@OnlyIn(value = Dist.CLIENT)
public void addInformation(ItemStack stack, World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
ItemDescription itemDescription = this.tooltip.getOrCreate(this::getDescription);
itemDescription.addInformation(tooltip);
super.addInformation(stack, worldIn, tooltip, flagIn);
}
protected abstract ItemDescription getDescription();
protected String h(String s, Palette palette) {
return ItemDescription.hightlight(s, palette);
}
}

View file

@ -0,0 +1,17 @@
package com.simibubi.create.foundation.item;
import java.util.function.Supplier;
import com.simibubi.create.foundation.utility.ItemDescription;
public class TooltipCache {
private ItemDescription toolTip;
public ItemDescription getOrCreate(Supplier<ItemDescription> factory) {
if (toolTip == null)
toolTip = factory.get();
return toolTip;
}
}

View file

@ -0,0 +1,190 @@
package com.simibubi.create.foundation.utility;
import static net.minecraft.util.text.TextFormatting.AQUA;
import static net.minecraft.util.text.TextFormatting.BLUE;
import static net.minecraft.util.text.TextFormatting.DARK_GRAY;
import static net.minecraft.util.text.TextFormatting.DARK_GREEN;
import static net.minecraft.util.text.TextFormatting.DARK_PURPLE;
import static net.minecraft.util.text.TextFormatting.DARK_RED;
import static net.minecraft.util.text.TextFormatting.GOLD;
import static net.minecraft.util.text.TextFormatting.GRAY;
import static net.minecraft.util.text.TextFormatting.GREEN;
import static net.minecraft.util.text.TextFormatting.LIGHT_PURPLE;
import static net.minecraft.util.text.TextFormatting.RED;
import static net.minecraft.util.text.TextFormatting.STRIKETHROUGH;
import static net.minecraft.util.text.TextFormatting.WHITE;
import static net.minecraft.util.text.TextFormatting.YELLOW;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
public class ItemDescription {
public static final int maxCharsPerLine = 35;
public static ITextComponent trim = new StringTextComponent(
WHITE + "" + STRIKETHROUGH + " ");
public enum Palette {
Blue(BLUE, AQUA), Green(DARK_GREEN, GREEN), Yellow(GOLD, YELLOW), Red(DARK_RED, RED),
Purple(DARK_PURPLE, LIGHT_PURPLE),
;
private Palette(TextFormatting primary, TextFormatting highlight) {
color = primary;
hColor = highlight;
}
public TextFormatting color;
public TextFormatting hColor;
}
private List<ITextComponent> lines;
private List<ITextComponent> linesOnShift;
private List<ITextComponent> linesOnCtrl;
private Palette palette;
public ItemDescription(Palette palette) {
this.palette = palette;
lines = new ArrayList<>();
linesOnShift = new ArrayList<>();
linesOnCtrl = new ArrayList<>();
trim = new StringTextComponent(WHITE + "" + STRIKETHROUGH + " ");
}
public ItemDescription withSummary(String summary) {
add(linesOnShift, cutString(summary, palette.color));
linesOnShift.add(trim);
return this;
}
public ItemDescription withBehaviour(String condition, String behaviour) {
add(linesOnShift, GRAY + condition);
add(linesOnShift, cutString(behaviour, palette.hColor, 1));
return this;
}
public ItemDescription withControl(String condition, String action) {
add(linesOnCtrl, GRAY + condition);
add(linesOnCtrl, cutString(action, palette.color, 1));
return this;
}
public ItemDescription createTabs() {
boolean hasDescription = !linesOnShift.isEmpty();
boolean hasControls = !linesOnCtrl.isEmpty();
if (hasDescription || hasControls) {
for (List<ITextComponent> list : Arrays.asList(lines, linesOnShift, linesOnCtrl)) {
boolean shift = list == linesOnShift;
boolean ctrl = list == linesOnCtrl;
String tabs = DARK_GRAY + "Hold ";
if (hasDescription)
tabs += "<" + (shift ? palette.hColor : palette.color) + "Shift" + DARK_GRAY + ">";
if (hasDescription && hasControls)
tabs += " or ";
if (hasControls)
tabs += "<" + (ctrl ? palette.hColor : palette.color) + "Control" + DARK_GRAY + ">";
list.add(0, new StringTextComponent(tabs));
if (shift || ctrl)
list.add(1, trim);
}
}
if (!hasDescription)
linesOnShift = lines;
if (!hasControls)
linesOnCtrl = lines;
return this;
}
public static String hightlight(String s, Palette palette) {
return palette.hColor + s + palette.color;
}
public List<String> cutString(String s, TextFormatting defaultColor) {
return cutString(s, defaultColor, 0);
}
public List<String> cutString(String s, TextFormatting defaultColor, int indent) {
String lineStart = defaultColor.toString();
for (int i = 0; i < indent; i++)
lineStart += " ";
String[] words = s.split(" ");
List<String> lines = new ArrayList<>();
StringBuilder currentLine = new StringBuilder(lineStart);
boolean firstWord = true;
for (int i = 0; i < words.length; i++) {
String word = words[i];
boolean lastWord = i == words.length - 1;
if (!lastWord && !firstWord && currentLine.length() + word.length() > maxCharsPerLine) {
lines.add(currentLine.toString());
currentLine = new StringBuilder(lineStart);
firstWord = true;
}
currentLine.append((firstWord ? "" : " ") + word);
firstWord = false;
}
if (!firstWord) {
lines.add(currentLine.toString());
}
return lines;
}
public static void add(List<ITextComponent> infoList, List<String> textLines) {
textLines.forEach(s -> add(infoList, s));
}
public static void add(List<ITextComponent> infoList, String line) {
infoList.add(new StringTextComponent(line));
}
public Palette getPalette() {
return palette;
}
public List<ITextComponent> addInformation(List<ITextComponent> tooltip) {
if (Screen.hasShiftDown()) {
tooltip.addAll(linesOnShift);
return tooltip;
}
if (Screen.hasControlDown()) {
tooltip.addAll(linesOnCtrl);
return tooltip;
}
tooltip.addAll(lines);
return tooltip;
}
public List<ITextComponent> getLines() {
return lines;
}
public List<ITextComponent> getLinesOnCtrl() {
return linesOnCtrl;
}
public List<ITextComponent> getLinesOnShift() {
return linesOnShift;
}
}

View file

@ -1,23 +1,14 @@
package com.simibubi.create.modules.contraptions.base;
import com.simibubi.create.foundation.block.IRenderUtilityBlock;
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.DirectionalBlock;
import net.minecraft.block.material.Material;
import net.minecraft.state.StateContainer.Builder;
public class HalfAxisBlock extends DirectionalBlock implements IRenderUtilityBlock {
public class HalfAxisBlock extends ProperDirectionalBlock implements IRenderUtilityBlock {
public HalfAxisBlock() {
super(Properties.create(Material.ROCK));
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(FACING);
super.fillStateContainer(builder);
}
}

View file

@ -2,12 +2,12 @@ package com.simibubi.create.modules.contraptions.receivers.constructs;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IWithoutBlockItem;
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonBlock.PistonState;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.DirectionalBlock;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.state.EnumProperty;
@ -23,7 +23,7 @@ import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
public class MechanicalPistonHeadBlock extends DirectionalBlock implements IWithoutBlockItem {
public class MechanicalPistonHeadBlock extends ProperDirectionalBlock implements IWithoutBlockItem {
public static final EnumProperty<PistonType> TYPE = BlockStateProperties.PISTON_TYPE;
@ -49,7 +49,7 @@ public class MechanicalPistonHeadBlock extends DirectionalBlock implements IWith
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(TYPE, FACING);
builder.add(TYPE);
super.fillStateContainer(builder);
}

View file

@ -1,21 +1,17 @@
package com.simibubi.create.modules.contraptions.receivers.constructs;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonBlock.PistonState;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.DirectionalBlock;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
@ -23,7 +19,7 @@ import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
public class PistonPoleBlock extends DirectionalBlock {
public class PistonPoleBlock extends ProperDirectionalBlock {
public PistonPoleBlock() {
super(Properties.from(Blocks.PISTON_HEAD));
@ -88,25 +84,9 @@ public class PistonPoleBlock extends DirectionalBlock {
return VoxelShapes.empty();
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(FACING);
super.fillStateContainer(builder);
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
return getDefaultState().with(FACING, context.getFace().getOpposite());
}
@Override
public BlockState rotate(BlockState state, Rotation rot) {
return state.with(FACING, rot.rotate(state.get(FACING)));
}
@Override
public BlockState mirror(BlockState state, Mirror mirrorIn) {
return state.rotate(mirrorIn.toRotation(state.get(FACING)));
}
}

View file

@ -3,27 +3,25 @@ package com.simibubi.create.modules.contraptions.redstone;
import java.util.Random;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior;
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonTileEntity;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.DirectionalBlock;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.TickPriority;
import net.minecraft.world.World;
public class ContactBlock extends DirectionalBlock implements IHaveMovementBehavior {
public class ContactBlock extends ProperDirectionalBlock implements IHaveMovementBehavior {
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
@ -34,7 +32,7 @@ public class ContactBlock extends DirectionalBlock implements IHaveMovementBehav
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(FACING, POWERED);
builder.add(POWERED);
super.fillStateContainer(builder);
}
@ -85,16 +83,6 @@ public class ContactBlock extends DirectionalBlock implements IHaveMovementBehav
return AllBlocks.CONTACT.typeOf(blockState) && blockState.get(FACING) == direction.getOpposite();
}
@Override
public BlockState rotate(BlockState state, Rotation rot) {
return state.with(FACING, rot.rotate(state.get(FACING)));
}
@Override
public BlockState mirror(BlockState state, Mirror mirrorIn) {
return state.rotate(mirrorIn.toRotation(state.get(FACING)));
}
@Override
public boolean canProvidePower(BlockState state) {
return state.get(POWERED);

View file

@ -22,8 +22,8 @@ import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.event.TickEvent.ClientTickEvent;
import net.minecraftforge.event.TickEvent.Phase;
import net.minecraftforge.event.TickEvent.RenderTickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@ -33,7 +33,7 @@ public class BeltItemHandler {
private static Random r = new Random();
@SubscribeEvent
public static void onRenderTick(RenderTickEvent event) {
public static void onClientTick(ClientTickEvent event) {
if (event.phase == Phase.START)
return;
@ -42,6 +42,8 @@ public class BeltItemHandler {
if (player == null || world == null)
return;
if (Minecraft.getInstance().currentScreen != null)
return;
for (Hand hand : Hand.values()) {
ItemStack heldItem = player.getHeldItem(hand);
@ -91,6 +93,7 @@ public class BeltItemHandler {
double x = Math.abs(diff.x);
double y = Math.abs(diff.y);
double z = Math.abs(diff.z);
float length = (float) Math.max(x, Math.max(y, z));
Vec3d step = diff.normalize();
int sames = ((x == y) ? 1 : 0) + ((y == z) ? 1 : 0) + ((z == x) ? 1 : 0);
@ -118,9 +121,10 @@ public class BeltItemHandler {
}
for (float f = 0; f < actualDiff.length(); f += .25f) {
step = new Vec3d(Math.signum(step.x), Math.signum(step.y), Math.signum(step.z));
for (float f = 0; f < length; f += .0625f) {
Vec3d position = start.add(step.scale(f));
if (r.nextInt(100) == 0) {
if (r.nextInt(10) == 0) {
world.addParticle(new RedstoneParticleData(canConnect ? .3f : .9f, canConnect ? .9f : .3f, .5f, 1),
position.x + .5f, position.y + .5f, position.z + .5f, 0, 0, 0);
}

View file

@ -12,19 +12,21 @@ import com.simibubi.create.AllItems;
import com.simibubi.create.AllPackets;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.item.ItemWithToolTip;
import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.KeyboardHelper;
import com.simibubi.create.foundation.utility.ItemDescription;
import com.simibubi.create.foundation.utility.ItemDescription.Palette;
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.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.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
@ -59,10 +61,19 @@ import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.network.PacketDistributor;
public class BuilderGunItem extends Item {
public class BuilderGunItem extends ItemWithToolTip {
public static enum ComponentTier {
None, BlazeBrass, ChorusChrome
None(TextFormatting.DARK_GRAY + "Andesite Alloy"), BlazeBrass(TextFormatting.GOLD + "Blaze Brass"),
ChorusChrome(TextFormatting.LIGHT_PURPLE + "Chorus Chrome"),
;
protected String displayName;
private ComponentTier(String displayName) {
this.displayName = displayName;
}
}
public static enum Components {
@ -78,39 +89,38 @@ public class BuilderGunItem extends Item {
return UseAction.NONE;
}
@Override
protected ItemDescription getDescription() {
Palette palette = Palette.Purple;
return new ItemDescription(palette).withSummary("Novel gadget for placing or exchanging blocks at a distance.")
.withControl("L-Click at Block", "Sets blocks placed by the tool to the targeted block.")
.withControl("R-Click at Block",
h("Places", palette) + " or " + h("Replaces", palette) + " the targeted block.")
.withControl("R-Click while Sneaking", "Opens the " + h("Configuration", palette) + " Interface")
.createTabs();
}
@Override
@OnlyIn(Dist.CLIENT)
public void addInformation(ItemStack stack, World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
if (KeyboardHelper.isKeyDown(KeyboardHelper.LSHIFT)) {
if (stack.getOrCreateTag().contains("BlockUsed")) {
BlockState state = NBTUtil.readBlockState(stack.getTag().getCompound("BlockUsed"));
tooltip.add(new StringTextComponent(TextFormatting.BLUE + "Using Block: " + TextFormatting.WHITE
+ new TranslationTextComponent(state.getBlock().getTranslationKey()).getFormattedText()));
} else {
tooltip.add(new StringTextComponent(TextFormatting.BLUE + "Hit a Block to set the material."));
}
tooltip.add(new StringTextComponent(""));
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "Places or Replaces Blocks at a range."));
tooltip.add(new StringTextComponent(
TextFormatting.GRAY + "> [Left-Click] to set the material used by the gun"));
tooltip.add(new StringTextComponent(
TextFormatting.GRAY + "> [Right-Click] to place/replace blocks with the material"));
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "> [Shift-Right-Click] to configure"));
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "Craft with components to upgrade."));
tooltip.add(new StringTextComponent(""));
if (stack.hasTag() && stack.getTag().contains("BlockUsed")) {
String usedblock = NBTUtil.readBlockState(stack.getTag().getCompound("BlockUsed")).getBlock()
.getTranslationKey();
ItemDescription.add(tooltip, TextFormatting.DARK_GRAY + "Using: " + TextFormatting.GRAY
+ new TranslationTextComponent(usedblock).getFormattedText());
}
super.addInformation(stack, worldIn, tooltip, flagIn);
Palette palette = Palette.Purple;
if (Screen.hasShiftDown()) {
ItemDescription.add(tooltip, palette.color + "Component Tiers:");
for (Components c : Components.values()) {
ComponentTier tier = getTier(c, stack);
tooltip.add(new StringTextComponent(
TextFormatting.AQUA + "" + TextFormatting.ITALIC + c.name() + ": " + TextFormatting.GRAY
+ (tier == ComponentTier.None ? (c == Components.Body ? "Andesite Alloy" : "Missing")
: tier.name())));
ItemDescription.add(tooltip, "> " + TextFormatting.GRAY + c.name() + ": " + tier.displayName);
}
} else {
tooltip.add(new StringTextComponent(TextFormatting.DARK_GRAY + "< Hold Shift >"));
}
super.addInformation(stack, worldIn, tooltip, flagIn);
}
@Override
@ -208,7 +218,8 @@ public class BuilderGunItem extends 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 barrelPosNoTransform = new Vec3d(mainHand == (player.getPrimaryHand() == HandSide.RIGHT) ? -.35f : .35f,
-0.1f, 1);
Vec3d barrelPos = start.add(barrelPosNoTransform.rotatePitch(pitch).rotateYaw(yaw));
// Client side - Shoot visual laser

View file

@ -0,0 +1,85 @@
package com.simibubi.create.modules.gardens;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.IGrowable;
import net.minecraft.block.RotatedPillarBlock;
import net.minecraft.state.IntegerProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
public class CocoaLogBlock extends RotatedPillarBlock implements IGrowable {
public static IntegerProperty AGE = BlockStateProperties.AGE_0_2;
private static final int GROWTH_CHANCE = 20;
public CocoaLogBlock() {
super(Properties.from(Blocks.JUNGLE_LOG).tickRandomly());
}
@Override
public boolean canGrow(IBlockReader arg0, BlockPos arg1, BlockState state, boolean arg3) {
return true;
}
@Override
public void tick(BlockState state, World worldIn, BlockPos pos, Random random) {
if (!worldIn.isAreaLoaded(pos, 1))
return; // Forge: prevent loading unloaded chunks when checking neighbor's light
grow(worldIn, random, pos, state);
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(AGE);
super.fillStateContainer(builder);
}
@Override
public boolean canUseBonemeal(World arg0, Random arg1, BlockPos arg2, BlockState arg3) {
return true;
}
@Override
public void grow(World world, Random random, BlockPos pos, BlockState state) {
if (random.nextInt(100 / GROWTH_CHANCE) != 0)
return;
int age = state.get(AGE);
if (age < 2) {
world.setBlockState(pos, state.with(AGE, age + 1));
return;
}
List<Direction> shuffledDirections = Arrays.asList(Direction.values());
Collections.shuffle(shuffledDirections);
for (Direction facing : shuffledDirections) {
if (facing.getAxis().isVertical())
continue;
if (facing.getAxis() == state.get(AXIS))
continue;
if (!world.getBlockState(pos.offset(facing)).getMaterial().isReplaceable())
continue;
world.setBlockState(pos.offset(facing),
Blocks.COCOA.getDefaultState().with(BlockStateProperties.HORIZONTAL_FACING, facing.getOpposite())
.with(BlockStateProperties.AGE_0_2, 0));
break;
}
}
}

View file

@ -1,4 +1,4 @@
package com.simibubi.create.modules.curiosities.item;
package com.simibubi.create.modules.gardens;
import java.util.Collections;
import java.util.HashMap;
@ -6,19 +6,18 @@ import java.util.List;
import java.util.Random;
import java.util.function.Predicate;
import com.simibubi.create.foundation.utility.KeyboardHelper;
import com.simibubi.create.foundation.item.ItemWithToolTip;
import com.simibubi.create.foundation.utility.ItemDescription;
import com.simibubi.create.foundation.utility.ItemDescription.Palette;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.SaplingBlock;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.BoneMealItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.item.crafting.RecipeManager;
import net.minecraft.scoreboard.Scoreboard;
@ -27,30 +26,22 @@ import net.minecraft.util.ActionResultType;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.EmptyTickList;
import net.minecraft.world.ITickList;
import net.minecraft.world.World;
import net.minecraft.world.storage.MapData;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class TreeFertilizerItem extends Item {
public class TreeFertilizerItem extends ItemWithToolTip {
public TreeFertilizerItem(Properties properties) {
super(properties);
}
@Override
@OnlyIn(Dist.CLIENT)
public void addInformation(ItemStack stack, World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
if (KeyboardHelper.isKeyDown(KeyboardHelper.LSHIFT))
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "Tree won't grow? Try this on it."));
else
tooltip.add(new StringTextComponent(TextFormatting.DARK_GRAY + "< Hold Shift >"));
super.addInformation(stack, worldIn, tooltip, flagIn);
protected ItemDescription getDescription() {
return new ItemDescription(Palette.Green)
.withSummary("A powerful combination of minerals suitable for common tree types.")
.withBehaviour("When used on Sapling", "Grows Trees regardless of their spacing Conditions").createTabs();
}
@Override

View file

@ -7,8 +7,10 @@ import java.util.Map;
import com.simibubi.create.AllPackets;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.item.ItemWithToolTip;
import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.KeyboardHelper;
import com.simibubi.create.foundation.utility.ItemDescription;
import com.simibubi.create.foundation.utility.ItemDescription.Palette;
import com.simibubi.create.modules.symmetry.mirror.CrossPlaneMirror;
import com.simibubi.create.modules.symmetry.mirror.EmptyMirror;
import com.simibubi.create.modules.symmetry.mirror.PlaneMirror;
@ -17,10 +19,8 @@ import com.simibubi.create.modules.symmetry.mirror.SymmetryMirror;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.nbt.CompoundNBT;
@ -32,7 +32,6 @@ import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
@ -41,7 +40,7 @@ import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.network.PacketDistributor;
public class SymmetryWandItem extends Item {
public class SymmetryWandItem extends ItemWithToolTip {
public static final String $SYMMETRY = "symmetry";
private static final String $ENABLE = "enable";
@ -51,22 +50,16 @@ public class SymmetryWandItem extends Item {
}
@Override
@OnlyIn(Dist.CLIENT)
public void addInformation(ItemStack stack, World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
if (KeyboardHelper.isKeyDown(KeyboardHelper.LSHIFT)) {
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "Perfectly mirrors your Block placement"));
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "across the configured planes."));
tooltip.add(new StringTextComponent(""));
tooltip.add(
new StringTextComponent(TextFormatting.GRAY + "> [Right-Click] on ground to place/move mirror"));
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "> [Right-Click] in air to remove mirror"));
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "> [Shift-Right-Click] to configure"));
tooltip.add(new StringTextComponent(""));
tooltip.add(new StringTextComponent(TextFormatting.DARK_GRAY + "Active while held in the Hotbar"));
} else
tooltip.add(new StringTextComponent(TextFormatting.DARK_GRAY + "< Hold Shift >"));
super.addInformation(stack, worldIn, tooltip, flagIn);
protected ItemDescription getDescription() {
Palette palette = Palette.Purple;
return new ItemDescription(palette)
.withSummary("Perfectly mirrors your Block placement across the configured planes.")
.withBehaviour("When in Hotbar", "Stays Active")
.withControl("R-Click on Ground",
h("Creates", palette) + " or " + h("Moves", palette) + " the Mirror")
.withControl("R-Click in the Air", h("Removes", palette) + " the active Mirror")
.withControl("R-Click while Sneaking", "Opens the " + h("Configuration Screen", palette))
.createTabs();
}
@Override

View file

@ -0,0 +1,15 @@
{
"forge_marker": 1,
"variants": {
"age": {
"0": { "model": "create:block/cocoa_log_0" },
"1": { "model": "create:block/cocoa_log_1" },
"2": { "model": "create:block/cocoa_log_2" }
},
"axis": {
"y": {},
"x": { "x": 90, "y": 90 },
"z": { "x": 90 }
}
}
}

View file

@ -59,5 +59,7 @@
"block.create.schematic_table": "Schematic Table",
"block.create.creative_crate": "Schematicannon Creatifier",
"block.create.cocoa_log": "Cocoa Jungle Log",
"itemGroup.create": "Create"
}

View file

@ -0,0 +1,6 @@
{
"parent": "block/cube_column",
"textures": {
"end": "block/jungle_log_top"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "create:block/cocoa_log",
"textures": {
"side": "create:block/cocoa_log_0"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "create:block/cocoa_log",
"textures": {
"side": "create:block/cocoa_log_1"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "create:block/cocoa_log",
"textures": {
"side": "create:block/cocoa_log_2"
}
}

View file

@ -0,0 +1,3 @@
{
"parent": "create:block/cocoa_log_2"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 B

View file

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"create:cocoa_log"
]
}