Made jars placeable

This commit is contained in:
Sollace 2024-03-30 02:19:54 +00:00
parent 1fd1782051
commit f0b2a8a550
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
41 changed files with 996 additions and 245 deletions

BIN
assets/models/body.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

BIN
assets/models/cork.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

View file

@ -0,0 +1 @@
{"meta":{"format_version":"4.9","model_format":"java_block","box_uv":false},"name":"jar","parent":"","ambientocclusion":true,"front_gui_light":false,"visible_box":[1,1,0],"variable_placeholders":"","variable_placeholder_buttons":[],"unhandled_root_fields":{},"resolution":{"width":16,"height":16},"elements":[{"name":"cube","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[4,0,4],"to":[12,12,12],"autouv":0,"color":3,"origin":[0,0,0],"faces":{"north":{"uv":[0,0,8,12],"texture":0},"east":{"uv":[0,0,8,12],"texture":0},"south":{"uv":[0,0,8,12],"texture":0},"west":{"uv":[0,0,8,12],"texture":0},"up":{"uv":[8,0,16,8],"texture":0},"down":{"uv":[8,0,16,8],"texture":0}},"type":"cube","uuid":"c02d32c0-74ac-27ba-627e-83de2a9500f7"},{"name":"cube","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[6,13,6],"to":[10,16,10],"autouv":0,"color":3,"origin":[0,0,0],"faces":{"north":{"uv":[0,4,4,7],"texture":1},"east":{"uv":[0,4,4,7],"texture":1},"south":{"uv":[0,4,4,7],"texture":1},"west":{"uv":[0,4,4,7],"texture":1},"up":{"uv":[0,0,4,4],"texture":1},"down":{"uv":[4,0,8,4],"texture":1}},"type":"cube","uuid":"147c96d5-ae15-7e40-dcb7-c635e6e80eed"},{"name":"cube","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[5,13,5],"to":[11,14,11],"autouv":0,"color":3,"origin":[0,0,0],"faces":{"north":{"uv":[0,0,8,1],"texture":0},"east":{"uv":[0,0,8,1],"texture":0},"south":{"uv":[0,0,8,1],"texture":0},"west":{"uv":[0,0,8,1],"texture":0},"up":{"uv":[8,0,16,8],"texture":0},"down":{"uv":[8,0,16,8],"texture":0}},"type":"cube","uuid":"7642fef8-ce7e-d79f-f450-01de2526fca5"},{"name":"cube","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[6,12,6],"to":[10,13,10],"autouv":0,"color":3,"origin":[0,0,0],"faces":{"north":{"uv":[0,0,8,1],"texture":0},"east":{"uv":[0,0,8,1],"texture":0},"south":{"uv":[0,0,8,1],"texture":0},"west":{"uv":[0,0,8,1],"texture":0},"up":{"uv":[8,0,16,8],"texture":0},"down":{"uv":[8,0,16,8],"texture":0}},"type":"cube","uuid":"e1e878a3-7fdb-79f6-e2c8-b591a94cec41"}],"outliner":["c02d32c0-74ac-27ba-627e-83de2a9500f7","7642fef8-ce7e-d79f-f450-01de2526fca5","e1e878a3-7fdb-79f6-e2c8-b591a94cec41","147c96d5-ae15-7e40-dcb7-c635e6e80eed"],"textures":[{"path":"","name":"body","folder":"block","namespace":"","id":"0","width":16,"height":16,"uv_width":16,"uv_height":16,"particle":true,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":false,"uuid":"c3fc3ff5-2bb6-a5d1-88ff-7d0d48a4200c","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAKxJREFUOE/Nk70NxCAMhe0qiCKCCRiA/UdhAFgARIGg8sknJbpI/CS6K47Sz/54fggkIoLJCSHAvu+glLp0pZQg5wwYYyStNfYYrHGdhxHx0sMXM+QEHIVPGAN6w8dlPHMCek4eAUYrLB1478kYM8zga8AyxJkD1hgwfcYVYLTekRk658ha281gpv0WUEqBWiu01t7gbdtACAFSShi5Ox3M/sEdrbv7ncH/cfACoGWX3cV5e7AAAAAASUVORK5CYII="},{"path":"","name":"cork","folder":"block","namespace":"","id":"1","width":16,"height":16,"uv_width":16,"uv_height":16,"particle":false,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":false,"uuid":"1faf1369-230e-ed4a-f210-037c1820f194","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAFJJREFUOE9jXDwj8z8DHhCbMZ0RnzwjyABRYW6wmtdvv4JpZD59DKDICztWl6CEgUdoD14/o1sGDgNkQUJ+pr4B+PxPjBxJ/sVm4KgBDAzDIAwAlBIoEQohE0IAAAAASUVORK5CYII="}]}

BIN
assets/models/jar_body.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

File diff suppressed because one or more lines are too long

BIN
assets/models/jar_cork.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

View file

@ -0,0 +1 @@
{"meta":{"format_version":"4.9","model_format":"java_block","box_uv":false},"name":"jar","parent":"","ambientocclusion":true,"front_gui_light":false,"visible_box":[1,1,0],"variable_placeholders":"","variable_placeholder_buttons":[],"unhandled_root_fields":{},"resolution":{"width":16,"height":16},"elements":[{"name":"cube","box_uv":false,"rescale":true,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[6,1,7.5],"to":[11,11,7.5],"autouv":0,"color":5,"rotation":[0,-45,0],"origin":[8,5,7],"faces":{"north":{"uv":[3,0,13,16],"texture":0},"east":{"uv":[0,0,0,8],"texture":0},"south":{"uv":[3,0,13,16],"texture":0},"west":{"uv":[0,0,0,8],"texture":0},"up":{"uv":[0,0,6,0],"texture":0},"down":{"uv":[0,0,6,0],"texture":0}},"type":"cube","uuid":"52fdb109-7055-1f3c-d1a1-788daf976643"},{"name":"cube","box_uv":false,"rescale":true,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[5,1,7.5],"to":[10,11,7.5],"autouv":0,"color":5,"rotation":[0,45,0],"origin":[8,5,7],"faces":{"north":{"uv":[3,0,13,16],"texture":0},"east":{"uv":[0,0,0,8],"texture":0},"south":{"uv":[3,0,13,16],"texture":0},"west":{"uv":[0,0,0,8],"texture":0},"up":{"uv":[0,0,6,0],"rotation":180,"texture":0},"down":{"uv":[0,0,6,0],"rotation":180,"texture":0}},"type":"cube","uuid":"67ba2407-52e4-4b13-579c-0e7675265bb9"}],"outliner":["52fdb109-7055-1f3c-d1a1-788daf976643","67ba2407-52e4-4b13-579c-0e7675265bb9"],"textures":[{"path":"/home/sollace/Documents/GitRepos/minecraft_mods/Unicopia/src/main/resources/assets/unicopia/textures/block/lightning_jar_filling.png","name":"lightning_jar_filling.png","folder":"block","namespace":"unicopia","id":"2","width":16,"height":16,"uv_width":16,"uv_height":16,"particle":false,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":true,"uuid":"2c8fdd18-9bd4-2276-cdc1-d86d0605d22d","relative_path":"../../../src/main/resources/assets/unicopia/textures/block/lightning_jar_filling.png","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAN9JREFUOE9jZCASOH7T/L+f6zojunIMAWzmObxR/c/IxcJAlgE+3/X+f/j7l4GV6R/pBnh/0vv/59d/hl9cf7BqBrkWrxdABnxj+Y1TM14DQJq//vrOwMfLz7CJ/QxOi7BKgEKc5wcLw3u2fwxHeK6C1YDEuP6wMqC7CKcB2GIDZMBWvksoejAMANmErBnkEhD4zP6bgZGRESM88BoA1/zvBzi8D4jcwp+QkG0HJRrfd7pg14DCgqh0ADMApBnEZvsGcT5Z6QBXqBOVF9C9gi+/4Y1GbJmHoAuQw4GYnA4AMBBxEZobGUEAAAAASUVORK5CYII="}]}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
{"meta":{"format_version":"4.9","model_format":"java_block","box_uv":false},"name":"jar","parent":"","ambientocclusion":true,"front_gui_light":false,"visible_box":[1,1,0],"variable_placeholders":"","variable_placeholder_buttons":[],"unhandled_root_fields":{},"resolution":{"width":16,"height":16},"elements":[{"name":"cube","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[4,0,4],"to":[12,10,12],"autouv":0,"color":4,"inflate":-0.09999999999999964,"origin":[0,0,0],"faces":{"north":{"uv":[0,2,8,12],"texture":2},"east":{"uv":[0,6,8,16],"texture":2},"south":{"uv":[8,6,16,16],"texture":2},"west":{"uv":[8,0,16,10],"texture":2},"up":{"uv":[4,3,12,11],"texture":2},"down":{"uv":[8,4,16,12],"texture":2}},"type":"cube","uuid":"e15b3907-6195-1f3b-0c48-23c6b4642fc6"}],"outliner":["e15b3907-6195-1f3b-0c48-23c6b4642fc6"],"textures":[{"path":"/home/sollace/Documents/GitRepos/minecraft_mods/Unicopia/assets/models/body.png","name":"body.png","folder":"","namespace":"","id":"0","width":16,"height":16,"uv_width":16,"uv_height":16,"particle":true,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":true,"uuid":"c3fc3ff5-2bb6-a5d1-88ff-7d0d48a4200c","relative_path":"../body.png","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAKxJREFUOE/Nk70NxCAMhe0qiCKCCRiA/UdhAFgARIGg8sknJbpI/CS6K47Sz/54fggkIoLJCSHAvu+glLp0pZQg5wwYYyStNfYYrHGdhxHx0sMXM+QEHIVPGAN6w8dlPHMCek4eAUYrLB1478kYM8zga8AyxJkD1hgwfcYVYLTekRk658ha281gpv0WUEqBWiu01t7gbdtACAFSShi5Ox3M/sEdrbv7ncH/cfACoGWX3cV5e7AAAAAASUVORK5CYII="},{"path":"/home/sollace/Documents/GitRepos/minecraft_mods/Unicopia/assets/models/cork.png","name":"cork.png","folder":"","namespace":"","id":"1","width":16,"height":16,"uv_width":16,"uv_height":16,"particle":false,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":true,"uuid":"1faf1369-230e-ed4a-f210-037c1820f194","relative_path":"../cork.png","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAFJJREFUOE9jXDwj8z8DHhCbMZ0RnzwjyABRYW6wmtdvv4JpZD59DKDICztWl6CEgUdoD14/o1sGDgNkQUJ+pr4B+PxPjBxJ/sVm4KgBDAzDIAwAlBIoEQohE0IAAAAASUVORK5CYII="},{"path":"/home/sollace/Documents/GitRepos/minecraft_mods/Unicopia/src/main/resources/assets/unicopia/textures/item/jar_filling_zap.png","name":"jar_filling_zap.png","folder":"item","namespace":"unicopia","id":"2","width":16,"height":16,"uv_width":16,"uv_height":16,"particle":false,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":false,"uuid":"62c06d20-77c5-befb-bb95-8e5da5394d9c","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAudJREFUOE8dkUlrXWUYgJ/3G849J7dJSxZuG2s6aMDaUsWWNjVpBS2luHDtyp1UcOhfEKTZ1LYIURQXjQYkEkwduhVd6S8oxUXAJpCBeO/NGb7hlfgPnkHOmvfUiMepBwJ3ph0ej3YRPew5+9UnSN9CY4gnL0FpcBo5vzjCeEHOmA9UJaBJuTftKHAUGeoqc/7BPTgUyPsgJ+boTEEkU6rj3OJTysIiZ/37moPly5mSnjEgBYN2n5d/+RSXgAQ5QDw5R2GFQWOZ/WIL6Ql2lJFz9iNdfM4zsg3jFAy6louP7kMRyZ2AgfqZWXAlRlsuLw7wpdDEQH10Ffnj+C31PY+2LT4Lp79fgBIkQZICfeEyQSsYNlxZ3mX4b83EkYqm6Rge/wn569SHqjZRq+fC6gK66Vgff5ep9A3MzLLTBY5UgVcXa1KKRBImQH5xDVGH/Pn8LTUkXvr5M1I0uKbj73yTZ48/IfmEsZFXvt6jGAniDYOwTz72A9rvQzbI76c+1gs/3icMa/wERAE3dYOailwPmFvbxu5kJBz0F0ZnVkl1S9Xr0wWD6GOUCCogCvnYWxjfgkZeX27Y3tzDO0cMGTPzkNh3tHVNUULvtbtIfoKKeNLUVYwYJEW6kePGbyM2Hm9RVI5oDGlqhewMgsWKoXd1gUiH1GFeSyvQjJGrhjeWO/55uoVTh+9bjGTs9K80YmhDTRk69PodnPW0MSIarimu4NrKiO31baJP9IqCHJV4Yol8gC8lsR5Qjo1Tzt2mIRNjwHhF3vzuinaaECvs7uxgjaE6+pCNPGRsYpxcJ9QbNAYmr37Org7pmTFaavyB8vzSrDpbsbe5RVNF3NEVovXQtPjeIVpa3t7cYO2dbzHqyKYhqSekfUpXIReXLqlJke3JB7geqHdIryDWSmkjxlYcnr/NXmhIVrCq/H/NZBwVcvrRunYSKLGkImOi4LynDcrk9bsMm33koIFrKUIP1Y7sWqz0ydLyH7DGczPZHbGfAAAAAElFTkSuQmCC","relative_path":"../../../src/main/resources/assets/unicopia/textures/item/jar_filling_zap.png"}]}

View file

@ -43,6 +43,7 @@ public interface UTags {
TagKey<Block> FRAGILE = block("fragile"); TagKey<Block> FRAGILE = block("fragile");
TagKey<Block> INTERESTING = block("interesting"); TagKey<Block> INTERESTING = block("interesting");
TagKey<Block> CATAPULT_IMMUNE = block("catapult_immune"); TagKey<Block> CATAPULT_IMMUNE = block("catapult_immune");
TagKey<Block> JARS = block("jars");
TagKey<Block> CRYSTAL_HEART_BASE = block("crystal_heart_base"); TagKey<Block> CRYSTAL_HEART_BASE = block("crystal_heart_base");
TagKey<Block> CRYSTAL_HEART_ORNAMENT = block("crystal_heart_ornament"); TagKey<Block> CRYSTAL_HEART_ORNAMENT = block("crystal_heart_ornament");

View file

@ -0,0 +1,216 @@
package com.minelittlepony.unicopia.block;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.block.InventoryProvider;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.SidedInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
public class ItemJarBlock extends JarBlock implements BlockEntityProvider, InventoryProvider {
public ItemJarBlock(Settings settings) {
super(settings);
}
@Override
public BlockRenderType getRenderType(BlockState state) {
return BlockRenderType.MODEL;
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
if (hand == Hand.OFF_HAND) {
return ActionResult.PASS;
}
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).map(data -> {
ItemStack stack = player.getStackInHand(hand);
if (stack.isEmpty()) {
return data.removeItem(world, pos);
}
return data.insertItem(world, pos, player.isCreative() ? stack.copyWithCount(1) : stack.split(1));
}).orElse(ActionResult.PASS);
}
@Deprecated
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if (!moved && !state.isOf(newState.getBlock())) {
world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).ifPresent(data -> {
data.getStacks().forEach(stack -> {
dropStack(world, pos, stack);
});
});
}
super.onStateReplaced(state, world, pos, newState, moved);
}
@Override
public boolean hasComparatorOutput(BlockState state) {
return true;
}
@Override
public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).map(data -> Math.min(16, data.getStacks().size())).orElse(0);
}
@Deprecated
@Override
public boolean onSyncedBlockEvent(BlockState state, World world, BlockPos pos, int type, int data) {
super.onSyncedBlockEvent(state, world, pos, type, data);
BlockEntity blockEntity = world.getBlockEntity(pos);
return blockEntity != null && blockEntity.onSyncedBlockEvent(type, data);
}
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return new TileData(pos, state);
}
@Override
public SidedInventory getInventory(BlockState state, WorldAccess world, BlockPos pos) {
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).orElse(null);
}
public static class TileData extends BlockEntity implements SidedInventory {
private static final int[] SLOTS = IntStream.range(0, 16).toArray();
private final List<ItemStack> stacks = new ArrayList<>();
public TileData(BlockPos pos, BlockState state) {
super(UBlockEntities.ITEM_JAR, pos, state);
}
public ActionResult insertItem(World world, BlockPos pos, ItemStack stack) {
if (stacks.size() >= size()) {
return ActionResult.FAIL;
}
stacks.add(stack);
markDirty();
return ActionResult.SUCCESS;
}
public ActionResult removeItem(World world, BlockPos pos) {
if (stacks.isEmpty()) {
return ActionResult.FAIL;
}
dropStack(world, pos, stacks.remove(0));
markDirty();
return ActionResult.SUCCESS;
}
public List<ItemStack> getStacks() {
return stacks;
}
@Override
public int size() {
return 15;
}
@Override
public boolean isEmpty() {
return stacks.isEmpty();
}
@Override
public ItemStack getStack(int slot) {
return slot < 0 || slot >= stacks.size() ? ItemStack.EMPTY : stacks.get(slot);
}
@Override
public ItemStack removeStack(int slot, int amount) {
if (slot < 0 || slot >= stacks.size()) {
try {
ItemStack stack = stacks.get(slot);
ItemStack removed = stack.split(1);
if (stack.isEmpty()) {
stacks.remove(slot);
}
return removed;
} finally {
markDirty();
}
}
return ItemStack.EMPTY;
}
@Override
public ItemStack removeStack(int slot) {
if (slot < 0 || slot >= stacks.size()) {
try {
return stacks.remove(slot);
} finally {
markDirty();
}
}
return ItemStack.EMPTY;
}
@Override
public void setStack(int slot, ItemStack stack) {
if (slot >= stacks.size()) {
if (stacks.size() >= size()) {
dropStack(getWorld(), getPos(), stack);
} else {
stacks.add(stack);
}
} else {
ItemStack existing = stacks.get(slot);
if (!ItemStack.canCombine(existing, stack)) {
dropStack(getWorld(), getPos(), stack);
} else {
existing.setCount(existing.getCount() + stack.split(Math.max(0, existing.getMaxCount() - existing.getCount())).getCount());
if (!stack.isEmpty()) {
dropStack(getWorld(), getPos(), stack);
}
}
}
}
@Override
public boolean canPlayerUse(PlayerEntity player) {
return false;
}
@Override
public void clear() {
stacks.clear();
markDirty();
}
@Override
public int[] getAvailableSlots(Direction side) {
return SLOTS;
}
@Override
public boolean canInsert(int slot, ItemStack stack, Direction dir) {
return (slot >= 0 && slot < size()) && (slot >= stacks.size() || (
ItemStack.canCombine(stacks.get(slot), stack)
&& (stacks.get(slot).getCount() + stack.getCount()) <= Math.min(stacks.get(slot).getMaxCount(), stack.getMaxCount())
));
}
@Override
public boolean canExtract(int slot, ItemStack stack, Direction dir) {
return true;
}
}
}

View file

@ -0,0 +1,82 @@
package com.minelittlepony.unicopia.block;
import java.util.Optional;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.item.WeatherJarItem;
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import net.minecraft.block.AbstractGlassBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.explosion.Explosion;
public class JarBlock extends AbstractGlassBlock {
private static final VoxelShape SHAPE = VoxelShapes.union(
Block.createCuboidShape(4, 0, 4, 12, 12, 12),
Block.createCuboidShape(6, 12, 6, 10, 16, 10),
Block.createCuboidShape(5, 13, 5, 11, 14, 11)
);
public JarBlock(Settings settings) {
super(settings);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return SHAPE;
}
@Override
public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) {
return super.isSideInvisible(state, stateFrom, direction);
}
@Override
public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random random) {
if (this == UBlocks.LIGHTNING_JAR) {
world.addParticle(new LightningBoltParticleEffect(true, 10, 1, 0.6F, Optional.empty()), pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 0, 0, 0);
}
}
@Deprecated
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
super.onStateReplaced(state, world, pos, newState, moved);
}
@Override
public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) {
super.onBreak(world, pos, state, player);
}
@Override
public void onDestroyedByExplosion(World world, BlockPos pos, Explosion explosion) {
if (asItem() instanceof WeatherJarItem jar) {
jar.releaseContents(world, pos);
}
}
@Override
public void afterBreak(World world, PlayerEntity player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
super.afterBreak(world, player, pos, state, blockEntity, tool);
if (!EnchantmentHelper.hasSilkTouch(tool) && !player.shouldCancelInteraction()) {
if (asItem() instanceof WeatherJarItem jar) {
jar.releaseContents(world, pos);
}
}
}
}

View file

@ -15,6 +15,7 @@ public interface UBlockEntities {
BlockEntityType<CloudBedBlock.Tile> FANCY_BED = create("fancy_bed", BlockEntityType.Builder.create(CloudBedBlock.Tile::new, UBlocks.CLOTH_BED, UBlocks.CLOUD_BED)); BlockEntityType<CloudBedBlock.Tile> FANCY_BED = create("fancy_bed", BlockEntityType.Builder.create(CloudBedBlock.Tile::new, UBlocks.CLOTH_BED, UBlocks.CLOUD_BED));
BlockEntityType<ChestBlockEntity> CLOUD_CHEST = create("cloud_chest", BlockEntityType.Builder.create(CloudChestBlock.TileData::new, UBlocks.CLOUD_CHEST)); BlockEntityType<ChestBlockEntity> CLOUD_CHEST = create("cloud_chest", BlockEntityType.Builder.create(CloudChestBlock.TileData::new, UBlocks.CLOUD_CHEST));
BlockEntityType<HiveBlock.TileData> HIVE_STORAGE = create("hive_storage", BlockEntityType.Builder.create(HiveBlock.TileData::new, UBlocks.HIVE)); BlockEntityType<HiveBlock.TileData> HIVE_STORAGE = create("hive_storage", BlockEntityType.Builder.create(HiveBlock.TileData::new, UBlocks.HIVE));
BlockEntityType<ItemJarBlock.TileData> ITEM_JAR = create("item_jar", BlockEntityType.Builder.create(ItemJarBlock.TileData::new, UBlocks.JAR));
static <T extends BlockEntity> BlockEntityType<T> create(String id, Builder<T> builder) { static <T extends BlockEntity> BlockEntityType<T> create(String id, Builder<T> builder) {
return Registry.register(Registries.BLOCK_ENTITY_TYPE, id, builder.build(null)); return Registry.register(Registries.BLOCK_ENTITY_TYPE, id, builder.build(null));

View file

@ -253,6 +253,11 @@ public interface UBlocks {
Block CLOUD_DOOR = register("cloud_door", new CloudDoorBlock(Settings.copy(CLOUD), CLOUD.getDefaultState(), UWoodTypes.CLOUD), ItemGroups.FUNCTIONAL); Block CLOUD_DOOR = register("cloud_door", new CloudDoorBlock(Settings.copy(CLOUD), CLOUD.getDefaultState(), UWoodTypes.CLOUD), ItemGroups.FUNCTIONAL);
Block SPECTRAL_FIRE = register("spectral_fire", new SpectralFireBlock(Settings.copy(Blocks.SOUL_FIRE))); Block SPECTRAL_FIRE = register("spectral_fire", new SpectralFireBlock(Settings.copy(Blocks.SOUL_FIRE)));
Block JAR = register("jar", new ItemJarBlock(Settings.copy(Blocks.GLASS)));
Block CLOUD_JAR = register("cloud_jar", new JarBlock(Settings.copy(Blocks.GLASS)));
Block STORM_JAR = register("storm_jar", new JarBlock(Settings.copy(Blocks.GLASS)));
Block LIGHTNING_JAR = register("lightning_jar", new JarBlock(Settings.copy(Blocks.GLASS)));
Block ZAP_JAR = register("zap_jar", new JarBlock(Settings.copy(Blocks.GLASS)));
Block WORM_BLOCK = register("worm_block", new FallingBlock(Settings.create().hardness(0.1F).resistance(0).requiresTool().sounds(BlockSoundGroup.MUD)), ItemGroups.NATURAL); Block WORM_BLOCK = register("worm_block", new FallingBlock(Settings.create().hardness(0.1F).resistance(0).requiresTool().sounds(BlockSoundGroup.MUD)), ItemGroups.NATURAL);
EdibleBlock HAY_BLOCK = register("hay_block", new EdibleBlock(new Identifier("hay_block"), new Identifier("wheat"), true)); EdibleBlock HAY_BLOCK = register("hay_block", new EdibleBlock(new Identifier("hay_block"), new Identifier("wheat"), true));
@ -305,7 +310,10 @@ public interface UBlocks {
OxidizableBlocksRegistry.registerWaxableBlockPair(ZAP_SLAB, WAXED_ZAP_SLAB); OxidizableBlocksRegistry.registerWaxableBlockPair(ZAP_SLAB, WAXED_ZAP_SLAB);
OxidizableBlocksRegistry.registerWaxableBlockPair(ZAP_FENCE, WAXED_ZAP_FENCE); OxidizableBlocksRegistry.registerWaxableBlockPair(ZAP_FENCE, WAXED_ZAP_FENCE);
OxidizableBlocksRegistry.registerWaxableBlockPair(ZAP_FENCE_GATE, WAXED_ZAP_FENCE_GATE); OxidizableBlocksRegistry.registerWaxableBlockPair(ZAP_FENCE_GATE, WAXED_ZAP_FENCE_GATE);
Collections.addAll(TRANSLUCENT_BLOCKS, WEATHER_VANE, CHITIN_SPIKES, PLUNDER_VINE, PLUNDER_VINE_BUD, CLAM_SHELL, SCALLOP_SHELL, TURRET_SHELL, CURING_JOKE, SPECTRAL_FIRE); Collections.addAll(TRANSLUCENT_BLOCKS,
WEATHER_VANE, CHITIN_SPIKES, PLUNDER_VINE, PLUNDER_VINE_BUD, CLAM_SHELL, SCALLOP_SHELL, TURRET_SHELL, CURING_JOKE, SPECTRAL_FIRE,
JAR, CLOUD_JAR, STORM_JAR, LIGHTNING_JAR, ZAP_JAR
);
TintedBlock.REGISTRY.add(PALM_LEAVES); TintedBlock.REGISTRY.add(PALM_LEAVES);
FlammableBlockRegistry.getDefaultInstance().add(GREEN_APPLE_LEAVES, 30, 60); FlammableBlockRegistry.getDefaultInstance().add(GREEN_APPLE_LEAVES, 30, 60);

View file

@ -116,6 +116,7 @@ public interface URenderers {
BlockEntityRendererFactories.register(UBlockEntities.WEATHER_VANE, WeatherVaneBlockEntityRenderer::new); BlockEntityRendererFactories.register(UBlockEntities.WEATHER_VANE, WeatherVaneBlockEntityRenderer::new);
BlockEntityRendererFactories.register(UBlockEntities.FANCY_BED, CloudBedBlockEntityRenderer::new); BlockEntityRendererFactories.register(UBlockEntities.FANCY_BED, CloudBedBlockEntityRenderer::new);
BlockEntityRendererFactories.register(UBlockEntities.CLOUD_CHEST, CloudChestBlockEntityRenderer::new); BlockEntityRendererFactories.register(UBlockEntities.CLOUD_CHEST, CloudChestBlockEntityRenderer::new);
BlockEntityRendererFactories.register(UBlockEntities.ITEM_JAR, ItemJarBlockEntityRenderer::new);
register(URenderers::renderJarItem, UItems.FILLED_JAR); register(URenderers::renderJarItem, UItems.FILLED_JAR);
register(URenderers::renderBedItem, UItems.CLOTH_BED, UItems.CLOUD_BED); register(URenderers::renderBedItem, UItems.CLOTH_BED, UItems.CLOUD_BED);

View file

@ -0,0 +1,49 @@
package com.minelittlepony.unicopia.client.render.entity;
import java.util.List;
import com.minelittlepony.unicopia.block.ItemJarBlock;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
import net.minecraft.client.render.model.json.ModelTransformationMode;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.RotationAxis;
import net.minecraft.util.math.random.Random;
public class ItemJarBlockEntityRenderer implements BlockEntityRenderer<ItemJarBlock.TileData> {
public ItemJarBlockEntityRenderer(BlockEntityRendererFactory.Context ctx) {
}
@Override
public void render(ItemJarBlock.TileData entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
List<ItemStack> stacks = entity.getStacks();
float itemScale = 0.35F;
matrices.push();
matrices.translate(0.5, 0, 0.5);
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
matrices.scale(itemScale, itemScale, itemScale);
Random rng = Random.create(entity.getPos().asLong());
float y = 0;
for (ItemStack stack : stacks) {
matrices.push();
matrices.translate((rng.nextFloat() - 0.5F) * 0.5F, (rng.nextFloat() - 0.5F) * 0.8F, -0.05 + y);
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees((rng.nextFloat() * 360) - 180));
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees((rng.nextFloat() * 360) - 180));
y -= 0.1F;
MinecraftClient.getInstance().getItemRenderer().renderItem(stack, ModelTransformationMode.FIXED, light, overlay, matrices, vertices, entity.getWorld(), 0);
matrices.pop();
}
matrices.pop();
}
}

View file

@ -34,6 +34,7 @@ public interface BlockModels {
Model DOOR_RIGHT = block("door_right", TextureKey.BOTTOM, TextureKey.TOP); Model DOOR_RIGHT = block("door_right", TextureKey.BOTTOM, TextureKey.TOP);
Model TEMPLATE_PILLAR = block("template_pillar", TextureKey.SIDE); Model TEMPLATE_PILLAR = block("template_pillar", TextureKey.SIDE);
Model TEMPLATE_PILLAR_END = block("template_pillar_end", "_end", TextureKey.BOTTOM, TextureKey.TOP, TextureKey.END); Model TEMPLATE_PILLAR_END = block("template_pillar_end", "_end", TextureKey.BOTTOM, TextureKey.TOP, TextureKey.END);
Identifier TEMPLATE_JAR = Unicopia.id("block/template_jar");
Factory CROP = Factory.of(TextureMap::crop, Models.CROP); Factory CROP = Factory.of(TextureMap::crop, Models.CROP);
Factory CUBE_ALL = Factory.of(TextureMap::all, Models.CUBE_ALL); Factory CUBE_ALL = Factory.of(TextureMap::all, Models.CUBE_ALL);

View file

@ -35,6 +35,7 @@ import net.minecraft.data.client.Models;
import net.minecraft.data.client.MultipartBlockStateSupplier; import net.minecraft.data.client.MultipartBlockStateSupplier;
import net.minecraft.data.client.TextureMap; import net.minecraft.data.client.TextureMap;
import net.minecraft.data.client.TexturedModel; import net.minecraft.data.client.TexturedModel;
import net.minecraft.data.client.VariantSettings;
import net.minecraft.data.client.VariantsBlockStateSupplier; import net.minecraft.data.client.VariantsBlockStateSupplier;
import net.minecraft.data.client.When; import net.minecraft.data.client.When;
import net.minecraft.item.Item; import net.minecraft.item.Item;
@ -177,6 +178,18 @@ public class UBlockStateModelGenerator extends BlockStateModelGenerator {
registerWithStagesBuiltinModels(UBlocks.MYSTERIOUS_EGG, PileBlock.COUNT, 1, 2, 3); registerWithStagesBuiltinModels(UBlocks.MYSTERIOUS_EGG, PileBlock.COUNT, 1, 2, 3);
excludeFromSimpleItemModelGeneration(UBlocks.MYSTERIOUS_EGG); excludeFromSimpleItemModelGeneration(UBlocks.MYSTERIOUS_EGG);
FireModels.registerSoulFire(this, UBlocks.SPECTRAL_FIRE, Blocks.SOUL_FIRE); FireModels.registerSoulFire(this, UBlocks.SPECTRAL_FIRE, Blocks.SOUL_FIRE);
blockStateCollector.accept(createSingletonBlockState(UBlocks.JAR, BlockModels.TEMPLATE_JAR));
registerWeatherJar(UBlocks.CLOUD_JAR);
registerWeatherJar(UBlocks.STORM_JAR);
registerWeatherJar(UBlocks.ZAP_JAR);
registerWeatherJar(UBlocks.LIGHTNING_JAR);
}
public void registerWeatherJar(Block jar) {
blockStateCollector.accept(MultipartBlockStateSupplier.create(jar)
.with(BlockStateVariant.create().put(VariantSettings.MODEL, BlockModels.TEMPLATE_JAR))
.with(BlockStateVariant.create().put(VariantSettings.MODEL, ModelIds.getBlockSubModelId(jar, "_filling"))));
} }
@SafeVarargs @SafeVarargs

View file

@ -40,11 +40,12 @@ public class UBlockTagProvider extends FabricTagProvider.BlockTagProvider {
}; };
getOrCreateTagBuilder(UTags.CATAPULT_IMMUNE).add(Blocks.BEDROCK).forceAddTag(BlockTags.DOORS).forceAddTag(BlockTags.TRAPDOORS); getOrCreateTagBuilder(UTags.CATAPULT_IMMUNE).add(Blocks.BEDROCK).forceAddTag(BlockTags.DOORS).forceAddTag(BlockTags.TRAPDOORS);
getOrCreateTagBuilder(UTags.JARS).add(UBlocks.JAR, UBlocks.CLOUD_JAR, UBlocks.STORM_JAR, UBlocks.LIGHTNING_JAR, UBlocks.ZAP_JAR);
getOrCreateTagBuilder(BlockTags.CROPS).add(crops); getOrCreateTagBuilder(BlockTags.CROPS).add(crops);
getOrCreateTagBuilder(BlockTags.BEE_GROWABLES).add(crops); getOrCreateTagBuilder(BlockTags.BEE_GROWABLES).add(crops);
getOrCreateTagBuilder(BlockTags.MAINTAINS_FARMLAND).add(crops); getOrCreateTagBuilder(BlockTags.MAINTAINS_FARMLAND).add(crops);
getOrCreateTagBuilder(BlockTags.NEEDS_DIAMOND_TOOL).add(UBlocks.FROSTED_OBSIDIAN); getOrCreateTagBuilder(BlockTags.NEEDS_DIAMOND_TOOL).add(UBlocks.FROSTED_OBSIDIAN);
getOrCreateTagBuilder(BlockTags.PICKAXE_MINEABLE).add(UBlocks.ROCKS, UBlocks.FROSTED_OBSIDIAN, UBlocks.WEATHER_VANE); getOrCreateTagBuilder(BlockTags.PICKAXE_MINEABLE).add(UBlocks.ROCKS, UBlocks.FROSTED_OBSIDIAN, UBlocks.WEATHER_VANE).forceAddTag(UTags.JARS);
getOrCreateTagBuilder(BlockTags.DRAGON_IMMUNE).add(UBlocks.FROSTED_OBSIDIAN, UBlocks.GOLDEN_OAK_LOG, UBlocks.GOLDEN_OAK_LEAVES); getOrCreateTagBuilder(BlockTags.DRAGON_IMMUNE).add(UBlocks.FROSTED_OBSIDIAN, UBlocks.GOLDEN_OAK_LOG, UBlocks.GOLDEN_OAK_LEAVES);
getOrCreateTagBuilder(BlockTags.FIRE).add(UBlocks.SPECTRAL_FIRE); getOrCreateTagBuilder(BlockTags.FIRE).add(UBlocks.SPECTRAL_FIRE);
getOrCreateTagBuilder(BlockTags.HOE_MINEABLE).add(UBlocks.HAY_BLOCK).addOptional(Unicopia.id("rice_block")).addOptional(Unicopia.id("straw_block")); getOrCreateTagBuilder(BlockTags.HOE_MINEABLE).add(UBlocks.HAY_BLOCK).addOptional(Unicopia.id("rice_block")).addOptional(Unicopia.id("straw_block"));
@ -67,6 +68,7 @@ public class UBlockTagProvider extends FabricTagProvider.BlockTagProvider {
getOrCreateTagBuilder(UTags.FRAGILE) getOrCreateTagBuilder(UTags.FRAGILE)
.forceAddTag(ConventionalBlockTags.GLASS_BLOCKS) .forceAddTag(ConventionalBlockTags.GLASS_BLOCKS)
.forceAddTag(ConventionalBlockTags.GLASS_PANES) .forceAddTag(ConventionalBlockTags.GLASS_PANES)
.forceAddTag(UTags.JARS)
.add(Blocks.VINE, Blocks.LILY_PAD); .add(Blocks.VINE, Blocks.LILY_PAD);
getOrCreateTagBuilder(UTags.INTERESTING).add( getOrCreateTagBuilder(UTags.INTERESTING).add(

View file

@ -81,6 +81,11 @@ public class UBlockLootTableProvider extends FabricBlockLootTableProvider {
tree.pot().ifPresent(this::addPottedPlantDrops); tree.pot().ifPresent(this::addPottedPlantDrops);
}); });
// jars
List.of(
UBlocks.JAR, UBlocks.CLOUD_JAR, UBlocks.STORM_JAR, UBlocks.LIGHTNING_JAR, UBlocks.STORM_JAR
).forEach(jar -> addDrop(jar, UBlockLootTableProvider::dropsWithSilkTouch));
// doors // doors
List.of( List.of(
UBlocks.CLOUD_DOOR, UBlocks.CRYSTAL_DOOR, UBlocks.CLOUD_DOOR, UBlocks.CRYSTAL_DOOR,

View file

@ -0,0 +1,60 @@
package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.entity.IItemEntity;
import com.minelittlepony.unicopia.entity.ItemImpl;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.minecraft.block.Block;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LightningEntity;
import net.minecraft.entity.Entity.RemovalReason;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
public class EmptyJarItem extends BlockItem implements ItemImpl.GroundTickCallback {
public EmptyJarItem(Block block, Settings settings) {
super(block, settings);
}
@Override
public ActionResult onGroundTick(IItemEntity item) {
ItemEntity entity = item.get().asEntity();
BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getCutout(), UBlocks.CLOUD_JAR, UBlocks.STORM_JAR, UBlocks.LIGHTNING_JAR, UBlocks.ZAP_JAR);
entity.setInvulnerable(true);
if (!entity.getWorld().isClient
&& !entity.isRemoved()
&& entity.getItemAge() > 100
&& entity.getWorld().isThundering()
&& entity.getWorld().isSkyVisible(entity.getBlockPos())
&& entity.getWorld().random.nextInt(130) == 0) {
LightningEntity lightning = EntityType.LIGHTNING_BOLT.create(entity.getWorld());
lightning.refreshPositionAfterTeleport(entity.getX(), entity.getY(), entity.getZ());
entity.remove(RemovalReason.DISCARDED);
entity.getWorld().spawnEntity(lightning);
ItemEntity neu = EntityType.ITEM.create(entity.getWorld());
neu.copyPositionAndRotation(entity);
neu.setStack(new ItemStack(this == UItems.RAIN_CLOUD_JAR ? UItems.STORM_CLOUD_JAR : UItems.LIGHTNING_JAR));
neu.setInvulnerable(true);
entity.getWorld().spawnEntity(neu);
ItemEntity copy = EntityType.ITEM.create(entity.getWorld());
copy.copyPositionAndRotation(entity);
copy.setInvulnerable(true);
copy.setStack(entity.getStack());
copy.getStack().decrement(1);
entity.getWorld().spawnEntity(copy);
}
return ActionResult.PASS;
}
}

View file

@ -1,10 +1,11 @@
package com.minelittlepony.unicopia.item; package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.entity.IItemEntity; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.entity.Living;
import com.minelittlepony.unicopia.entity.mob.ButterflyEntity; import com.minelittlepony.unicopia.entity.mob.ButterflyEntity;
import com.minelittlepony.unicopia.entity.mob.UEntities; import com.minelittlepony.unicopia.entity.mob.UEntities;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -20,16 +21,20 @@ import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.particle.ParticleTypes; import net.minecraft.particle.ParticleTypes;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundEvent;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.world.WorldEvents; import net.minecraft.world.WorldEvents;
public class FilledJarItem extends JarItem implements ChameleonItem { public class FilledJarItem extends ProjectileItem implements ProjectileDelegate.HitListener, ChameleonItem {
public FilledJarItem(Settings settings) { public FilledJarItem(Settings settings) {
super(settings, false, false, false); super(settings, 0);
}
@Override
public SoundEvent getThrowSound(ItemStack stack) {
return USounds.ENTITY_JAR_THROW;
} }
@Override @Override
@ -42,20 +47,8 @@ public class FilledJarItem extends JarItem implements ChameleonItem {
return false; return false;
} }
@Override
public ActionResult onGroundTick(IItemEntity item) {
return ActionResult.PASS;
}
@Override
protected float getProjectileDamage(ItemStack stack) {
return 0;
}
@Override @Override
public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) { public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) {
super.onImpact(projectile, hit);
Entity entity = hit.getEntity(); Entity entity = hit.getEntity();
if (!entity.isAttackable() || !(projectile instanceof FlyingItemEntity)) { if (!entity.isAttackable() || !(projectile instanceof FlyingItemEntity)) {

View file

@ -5,37 +5,19 @@ import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.projectile.PhysicsBodyProjectileEntity; import com.minelittlepony.unicopia.projectile.PhysicsBodyProjectileEntity;
import net.minecraft.block.DispenserBlock;
import net.minecraft.block.dispenser.ProjectileDispenserBehavior;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity; import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvent;
import net.minecraft.util.math.Position;
import net.minecraft.world.World; import net.minecraft.world.World;
public class HeavyProjectileItem extends ProjectileItem { public class HeavyProjectileItem extends ProjectileItem {
public HeavyProjectileItem(Settings settings, float projectileDamage) { public HeavyProjectileItem(Settings settings, float projectileDamage) {
super(settings, projectileDamage); super(settings, projectileDamage);
DispenserBlock.registerBehavior(this, new ProjectileDispenserBehavior(){
@Override
protected ProjectileEntity createProjectile(World world, Position position, ItemStack stack) {
ProjectileEntity projectile = HeavyProjectileItem.this.createProjectile(stack, world, null);
projectile.setPosition(position.getX(), position.getY(), position.getZ());
return projectile;
}
@Override
protected float getVariation() {
return 0;
}
});
} }
@Override @Override
protected PhysicsBodyProjectileEntity createProjectile(ItemStack stack, World world, @Nullable PlayerEntity player) { public PhysicsBodyProjectileEntity createProjectile(ItemStack stack, World world, @Nullable PlayerEntity player) {
PhysicsBodyProjectileEntity projectile = player == null ? new PhysicsBodyProjectileEntity(world) : new PhysicsBodyProjectileEntity(world, player); PhysicsBodyProjectileEntity projectile = player == null ? new PhysicsBodyProjectileEntity(world) : new PhysicsBodyProjectileEntity(world, player);
if (player != null) { if (player != null) {
projectile.setVelocity(player, player.getPitch(), player.getYaw(), 0, 1.5F, 1); projectile.setVelocity(player, player.getPitch(), player.getYaw(), 0, 1.5F, 1);
@ -46,7 +28,7 @@ public class HeavyProjectileItem extends ProjectileItem {
} }
@Override @Override
protected SoundEvent getThrowSound(ItemStack stack) { public SoundEvent getThrowSound(ItemStack stack) {
return USounds.ENTITY_JAR_THROW; return USounds.ENTITY_JAR_THROW;
} }
} }

View file

@ -74,7 +74,7 @@ public class HorseShoeItem extends HeavyProjectileItem {
} }
@Override @Override
protected PhysicsBodyProjectileEntity createProjectile(ItemStack stack, World world, @Nullable PlayerEntity player) { public PhysicsBodyProjectileEntity createProjectile(ItemStack stack, World world, @Nullable PlayerEntity player) {
PhysicsBodyProjectileEntity projectile = super.createProjectile(stack, world, player); PhysicsBodyProjectileEntity projectile = super.createProjectile(stack, world, player);
projectile.setDamageType(UDamageTypes.HORSESHOE); projectile.setDamageType(UDamageTypes.HORSESHOE);
@ -99,7 +99,7 @@ public class HorseShoeItem extends HeavyProjectileItem {
} }
@Override @Override
protected SoundEvent getThrowSound(ItemStack stack) { public SoundEvent getThrowSound(ItemStack stack) {
return USounds.Vanilla.ITEM_TRIDENT_THROW; return USounds.Vanilla.ITEM_TRIDENT_THROW;
} }

View file

@ -29,7 +29,7 @@ public class JarInsertRecipe extends ItemCombinationRecipe {
@Override @Override
protected boolean isInsertItem(ItemStack stack) { protected boolean isInsertItem(ItemStack stack) {
return !(stack.getItem() instanceof JarItem); return !(stack.getItem() instanceof EmptyJarItem);
} }
@Override @Override

View file

@ -1,150 +0,0 @@
package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.AwaitTickQueue;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.entity.IItemEntity;
import com.minelittlepony.unicopia.entity.ItemImpl;
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LightningEntity;
import net.minecraft.entity.Entity.RemovalReason;
import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.ChunkSectionPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.Heightmap;
import net.minecraft.world.WorldEvents;
public class JarItem extends ProjectileItem implements ItemImpl.GroundTickCallback, ProjectileDelegate.HitListener {
private final boolean rain;
private final boolean thunder;
private final boolean lightning;
public JarItem(Settings settings, boolean rain, boolean thunder, boolean lightning) {
super(settings, 0.5F);
this.rain = rain;
this.thunder = thunder;
this.lightning = lightning;
}
@Override
public ActionResult onGroundTick(IItemEntity item) {
ItemEntity entity = item.get().asEntity();
entity.setInvulnerable(true);
if (!lightning
&& !entity.getWorld().isClient
&& !entity.isRemoved()
&& entity.getItemAge() > 100
&& entity.getWorld().isThundering()
&& entity.getWorld().isSkyVisible(entity.getBlockPos())
&& entity.getWorld().random.nextInt(130) == 0) {
LightningEntity lightning = EntityType.LIGHTNING_BOLT.create(entity.getWorld());
lightning.refreshPositionAfterTeleport(entity.getX(), entity.getY(), entity.getZ());
entity.remove(RemovalReason.DISCARDED);
entity.getWorld().spawnEntity(lightning);
ItemEntity neu = EntityType.ITEM.create(entity.getWorld());
neu.copyPositionAndRotation(entity);
neu.setStack(new ItemStack(this == UItems.RAIN_CLOUD_JAR ? UItems.STORM_CLOUD_JAR : UItems.LIGHTNING_JAR));
neu.setInvulnerable(true);
entity.getWorld().spawnEntity(neu);
ItemEntity copy = EntityType.ITEM.create(entity.getWorld());
copy.copyPositionAndRotation(entity);
copy.setInvulnerable(true);
copy.setStack(entity.getStack());
copy.getStack().decrement(1);
entity.getWorld().spawnEntity(copy);
}
return ActionResult.PASS;
}
@Override
protected SoundEvent getThrowSound(ItemStack stack) {
return USounds.ENTITY_JAR_THROW;
}
@Override
public void onImpact(MagicProjectileEntity projectile) {
if (!projectile.getWorld().isClient()) {
ServerWorld world = (ServerWorld)projectile.getWorld();
if (rain || thunder) {
// clear weather time = number of ticks for which the weather is clear
// rain time = ticks until rain gets toggled (reset the tick after toggling)
// thunder time = ticks until thundering gets toggled (reset the tick after toggling)
// clear weather time
// Number of ticks weather must stay clear.
// Raining and thundering, and raining/thundering times are kept to false and 0
// when clear weather time is <= 0
// - wait for thunder time to reach zero then toggle thundering
// - wait for rain time to reach zero then toggle raining
// when thunder time is <= 0
// - randomly pick a new value for thunder time
// when rain time is <= 0
// - randomly pick a new value for rain time
world.setWeather(0, 0, rain, thunder);
if (thunder) {
for (int i = world.random.nextInt(7); i > 0; i--) {
AwaitTickQueue.scheduleTask(world, w -> {
LightningEntity bolt = EntityType.LIGHTNING_BOLT.create(world);
bolt.setCosmetic(true);
bolt.refreshPositionAfterTeleport(Vec3d.ofBottomCenter(world.getTopPosition(Heightmap.Type.MOTION_BLOCKING, world.getRandomPosInChunk(
ChunkSectionPos.getBlockCoord(ChunkSectionPos.getSectionCoord(projectile.getX())),
0,
ChunkSectionPos.getBlockCoord(ChunkSectionPos.getSectionCoord(projectile.getZ())),
15
)).up(32)));
world.spawnEntity(bolt);
}, 15 + world.random.nextInt(12));
}
}
}
if (lightning) {
LightningEntity lightning = EntityType.LIGHTNING_BOLT.create(world);
lightning.refreshPositionAfterTeleport(projectile.getX(), projectile.getY(), projectile.getZ());
world.spawnEntity(lightning);
}
}
if (lightning) {
ParticleUtils.spawnParticle(projectile.getWorld(), LightningBoltParticleEffect.DEFAULT, projectile.getPos(), Vec3d.ZERO);
}
if (rain || thunder) {
projectile.getWorld().syncWorldEvent(WorldEvents.SPLASH_POTION_SPLASHED, projectile.getBlockPos(), thunder ? 0x888888 : 0xF8F8F8);
for (int i = projectile.getWorld().random.nextInt(3) + 1; i >= 0; i--) {
ParticleUtils.spawnParticle(projectile.getWorld(), UParticles.CLOUDS_ESCAPING,
projectile.getX(), projectile.getY(), projectile.getZ(),
projectile.getWorld().random.nextFloat() - 0.5,
0,
projectile.getWorld().random.nextFloat() - 0.5
);
}
}
projectile.getWorld().syncWorldEvent(WorldEvents.BLOCK_BROKEN, projectile.getBlockPos(), Block.getRawIdFromState(Blocks.GLASS.getDefaultState()));
}
}

View file

@ -10,13 +10,12 @@ import net.minecraft.item.ItemStack;
import net.minecraft.world.World; import net.minecraft.world.World;
public class MuffinItem extends HeavyProjectileItem { public class MuffinItem extends HeavyProjectileItem {
public MuffinItem(Settings settings, float projectileDamage) { public MuffinItem(Settings settings, float projectileDamage) {
super(settings, projectileDamage); super(settings, projectileDamage);
} }
@Override @Override
protected PhysicsBodyProjectileEntity createProjectile(ItemStack stack, World world, @Nullable PlayerEntity player) { public PhysicsBodyProjectileEntity createProjectile(ItemStack stack, World world, @Nullable PlayerEntity player) {
PhysicsBodyProjectileEntity projectile = super.createProjectile(stack, world, player); PhysicsBodyProjectileEntity projectile = super.createProjectile(stack, world, player);
projectile.setBouncy(); projectile.setBouncy();
projectile.setDamage(0); projectile.setDamage(0);

View file

@ -1,72 +1,34 @@
package com.minelittlepony.unicopia.item; package com.minelittlepony.unicopia.item;
import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.projectile.Projectile;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.util.SoundEmitter;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.stat.Stats;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult; import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World; import net.minecraft.world.World;
abstract class ProjectileItem extends Item { abstract class ProjectileItem extends Item implements Projectile {
private final float projectileDamage; private final float projectileDamage;
public ProjectileItem(Settings settings, float projectileDamage) { public ProjectileItem(Settings settings, float projectileDamage) {
super(settings); super(settings);
this.projectileDamage = projectileDamage; this.projectileDamage = projectileDamage;
Projectile.makeDispensable(this);
} }
@Override @Override
public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) { public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
if (isFood() && !player.shouldCancelInteraction()) {
if (isFood() && !player.isSneaking()) {
return super.use(world, player, hand); return super.use(world, player, hand);
} }
ItemStack stack = player.getStackInHand(hand); return triggerThrow(world, player, hand);
SoundEmitter.playSoundAt(player,
getThrowSound(stack), SoundCategory.NEUTRAL,
0.5F,
0.4F / (world.random.nextFloat() * 0.4F + 0.8F));
if (!world.isClient) {
world.spawnEntity(createProjectile(stack.copyWithCount(1), world, player));
}
player.incrementStat(Stats.USED.getOrCreateStat(this));
if (!player.isCreative()) {
stack.decrement(1);
}
return TypedActionResult.success(stack, world.isClient());
} }
protected ProjectileEntity createProjectile(ItemStack stack, World world, @Nullable PlayerEntity player) { @Override
MagicProjectileEntity projectile = player == null ? new MagicProjectileEntity(world) : new MagicProjectileEntity(world, player); public float getProjectileDamage(ItemStack stack) {
projectile.setItem(stack);
projectile.setThrowDamage(getProjectileDamage(stack));
projectile.setMaxAge(-1);
if (player != null) {
projectile.setVelocity(player, player.getPitch(), player.getYaw(), 0, 1.5F, 1);
}
return projectile;
}
protected abstract SoundEvent getThrowSound(ItemStack stack);
protected float getProjectileDamage(ItemStack stack) {
return projectileDamage; return projectileDamage;
} }
} }

View file

@ -50,12 +50,12 @@ public interface UItems {
FriendshipBraceletItem FRIENDSHIP_BRACELET = register("friendship_bracelet", new FriendshipBraceletItem(new FabricItemSettings().rarity(Rarity.UNCOMMON)), ItemGroups.TOOLS); FriendshipBraceletItem FRIENDSHIP_BRACELET = register("friendship_bracelet", new FriendshipBraceletItem(new FabricItemSettings().rarity(Rarity.UNCOMMON)), ItemGroups.TOOLS);
Item PLUNDER_VINE = register("plunder_vine", new BlockItem(UBlocks.PLUNDER_VINE_BUD, new Item.Settings())); Item PLUNDER_VINE = register("plunder_vine", new BlockItem(UBlocks.PLUNDER_VINE_BUD, new Item.Settings()));
Item EMPTY_JAR = register("empty_jar", new JarItem(new Item.Settings().fireproof(), false, false, false), ItemGroups.FUNCTIONAL); Item EMPTY_JAR = register("empty_jar", new EmptyJarItem(UBlocks.JAR, new Item.Settings().fireproof()), ItemGroups.FUNCTIONAL);
FilledJarItem FILLED_JAR = register("filled_jar", new FilledJarItem(new Item.Settings().maxCount(16).fireproof().recipeRemainder(EMPTY_JAR))); FilledJarItem FILLED_JAR = register("filled_jar", new FilledJarItem(new Item.Settings().maxCount(16).fireproof().recipeRemainder(EMPTY_JAR)));
Item RAIN_CLOUD_JAR = register("rain_cloud_jar", new JarItem(new Item.Settings().maxCount(16).fireproof().recipeRemainder(EMPTY_JAR), true, false, false), ItemGroups.FUNCTIONAL); Item RAIN_CLOUD_JAR = register("rain_cloud_jar", new WeatherJarItem(UBlocks.CLOUD_JAR, new Item.Settings().maxCount(16).fireproof().recipeRemainder(EMPTY_JAR), WeatherJarItem.Type.RAIN), ItemGroups.FUNCTIONAL);
Item STORM_CLOUD_JAR = register("storm_cloud_jar", new JarItem(new Item.Settings().maxCount(16).fireproof().recipeRemainder(EMPTY_JAR), true, true, false), ItemGroups.FUNCTIONAL); Item STORM_CLOUD_JAR = register("storm_cloud_jar", new WeatherJarItem(UBlocks.STORM_JAR, new Item.Settings().maxCount(16).fireproof().recipeRemainder(EMPTY_JAR), WeatherJarItem.Type.THUNDER), ItemGroups.FUNCTIONAL);
Item LIGHTNING_JAR = register("lightning_jar", new JarItem(new Item.Settings().maxCount(16).fireproof().recipeRemainder(EMPTY_JAR), false, false, true), ItemGroups.FUNCTIONAL); Item LIGHTNING_JAR = register("lightning_jar", new WeatherJarItem(UBlocks.LIGHTNING_JAR, new Item.Settings().maxCount(16).fireproof().recipeRemainder(EMPTY_JAR), WeatherJarItem.Type.LIGHTNING), ItemGroups.FUNCTIONAL);
Item ZAP_APPLE_JAM_JAR = register("zap_apple_jam_jar", new JarItem(new Item.Settings().maxCount(16).fireproof().recipeRemainder(EMPTY_JAR), false, false, true), ItemGroups.FUNCTIONAL); Item ZAP_APPLE_JAM_JAR = register("zap_apple_jam_jar", new WeatherJarItem(UBlocks.ZAP_JAR, new Item.Settings().maxCount(16).fireproof().recipeRemainder(EMPTY_JAR), WeatherJarItem.Type.LIGHTNING), ItemGroups.FUNCTIONAL);
Item TOAST = register("toast", new Item(new Item.Settings().maxCount(16).food(UFoodComponents.TOAST)), ItemGroups.FOOD_AND_DRINK); Item TOAST = register("toast", new Item(new Item.Settings().maxCount(16).food(UFoodComponents.TOAST)), ItemGroups.FOOD_AND_DRINK);
Item BURNED_TOAST = register("burned_toast", new Item(new Item.Settings().maxCount(16).food(UFoodComponents.BURNED_TOAST)), ItemGroups.FOOD_AND_DRINK); Item BURNED_TOAST = register("burned_toast", new Item(new Item.Settings().maxCount(16).food(UFoodComponents.BURNED_TOAST)), ItemGroups.FOOD_AND_DRINK);

View file

@ -0,0 +1,136 @@
package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.AwaitTickQueue;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.Projectile;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LightningEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.AliasedBlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkSectionPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.Heightmap;
import net.minecraft.world.World;
import net.minecraft.world.WorldEvents;
public class WeatherJarItem extends AliasedBlockItem implements Projectile, ProjectileDelegate.HitListener {
private final Type type;
public WeatherJarItem(Block block, Settings settings, Type type) {
super(block, settings);
this.type = type;
Projectile.makeDispensable(this);
}
@Override
public SoundEvent getThrowSound(ItemStack stack) {
return USounds.ENTITY_JAR_THROW;
}
@Override
public float getProjectileDamage(ItemStack stack) {
return 0.5F;
}
@Override
public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
if (player.shouldCancelInteraction()) {
return super.use(world, player, hand);
}
return triggerThrow(world, player, hand);
}
@Override
public void onImpact(MagicProjectileEntity projectile) {
releaseContents(projectile.getWorld(), projectile.getBlockPos());
}
public void releaseContents(World world, BlockPos pos) {
if (!world.isClient()) {
ServerWorld sw = (ServerWorld)world;
if (type == Type.RAIN || type == Type.THUNDER) {
// clear weather time = number of ticks for which the weather is clear
// rain time = ticks until rain gets toggled (reset the tick after toggling)
// thunder time = ticks until thundering gets toggled (reset the tick after toggling)
// clear weather time
// Number of ticks weather must stay clear.
// Raining and thundering, and raining/thundering times are kept to false and 0
// when clear weather time is <= 0
// - wait for thunder time to reach zero then toggle thundering
// - wait for rain time to reach zero then toggle raining
// when thunder time is <= 0
// - randomly pick a new value for thunder time
// when rain time is <= 0
// - randomly pick a new value for rain time
sw.setWeather(0, 0, type == Type.RAIN, type == Type.THUNDER);
if (type == Type.THUNDER) {
for (int i = world.random.nextInt(7); i > 0; i--) {
AwaitTickQueue.scheduleTask(world, w -> {
LightningEntity bolt = EntityType.LIGHTNING_BOLT.create(world);
bolt.setCosmetic(true);
bolt.refreshPositionAfterTeleport(Vec3d.ofBottomCenter(world.getTopPosition(Heightmap.Type.MOTION_BLOCKING, world.getRandomPosInChunk(
ChunkSectionPos.getBlockCoord(ChunkSectionPos.getSectionCoord(pos.getX())),
0,
ChunkSectionPos.getBlockCoord(ChunkSectionPos.getSectionCoord(pos.getZ())),
15
)).up(32)));
world.spawnEntity(bolt);
}, 15 + world.random.nextInt(12));
}
}
}
if (type == Type.LIGHTNING) {
LightningEntity lightning = EntityType.LIGHTNING_BOLT.create(world);
lightning.refreshPositionAfterTeleport(pos.getX(), pos.getY(), pos.getZ());
world.spawnEntity(lightning);
}
}
Vec3d centerPos = pos.toCenterPos();
if (type == Type.LIGHTNING) {
ParticleUtils.spawnParticle(world, LightningBoltParticleEffect.DEFAULT, centerPos, Vec3d.ZERO);
}
if (type == Type.RAIN || type == Type.THUNDER) {
world.syncWorldEvent(WorldEvents.SPLASH_POTION_SPLASHED, pos, type == Type.THUNDER ? 0x888888 : 0xF8F8F8);
for (int i = world.random.nextInt(3) + 1; i >= 0; i--) {
ParticleUtils.spawnParticle(world, UParticles.CLOUDS_ESCAPING,
centerPos.getX(), centerPos.getY(), centerPos.getZ(),
world.random.nextFloat() - 0.5,
0,
world.random.nextFloat() - 0.5
);
}
}
world.syncWorldEvent(WorldEvents.BLOCK_BROKEN, pos, Block.getRawIdFromState(Blocks.GLASS.getDefaultState()));
}
public enum Type {
RAIN,
THUNDER,
LIGHTNING
}
}

View file

@ -0,0 +1,73 @@
package com.minelittlepony.unicopia.projectile;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.util.SoundEmitter;
import net.minecraft.block.DispenserBlock;
import net.minecraft.block.dispenser.ProjectileDispenserBehavior;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.stat.Stats;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.math.Position;
import net.minecraft.world.World;
public interface Projectile extends ItemConvertible {
static void makeDispensable(Projectile projectile) {
DispenserBlock.registerBehavior(projectile.asItem(), new ProjectileDispenserBehavior(){
@Override
protected ProjectileEntity createProjectile(World world, Position position, ItemStack stack) {
ProjectileEntity p = projectile.createProjectile(stack, world, null);
p.setPosition(position.getX(), position.getY(), position.getZ());
return p;
}
@Override
protected float getVariation() {
return 0;
}
});
}
default TypedActionResult<ItemStack> triggerThrow(World world, PlayerEntity player, Hand hand) {
ItemStack stack = player.getStackInHand(hand);
SoundEmitter.playSoundAt(player,
getThrowSound(stack), SoundCategory.NEUTRAL,
0.5F,
0.4F / (world.random.nextFloat() * 0.4F + 0.8F));
if (!world.isClient) {
world.spawnEntity(createProjectile(stack.copyWithCount(1), world, player));
}
player.incrementStat(Stats.USED.getOrCreateStat(asItem()));
if (!player.isCreative()) {
stack.decrement(1);
}
return TypedActionResult.success(stack, world.isClient());
}
default ProjectileEntity createProjectile(ItemStack stack, World world, @Nullable PlayerEntity player) {
MagicProjectileEntity projectile = player == null ? new MagicProjectileEntity(world) : new MagicProjectileEntity(world, player);
projectile.setItem(stack);
projectile.setThrowDamage(getProjectileDamage(stack));
projectile.setMaxAge(-1);
if (player != null) {
projectile.setVelocity(player, player.getPitch(), player.getYaw(), 0, 1.5F, 1);
}
return projectile;
}
SoundEvent getThrowSound(ItemStack stack);
float getProjectileDamage(ItemStack stack);
}

View file

@ -81,12 +81,17 @@
"item.unicopia.plunder_vine": "Plunder Vine", "item.unicopia.plunder_vine": "Plunder Vine",
"item.unicopia.empty_jar": "Glass Jar", "item.unicopia.empty_jar": "Glass Jar",
"block.unicopia.jar": "Glass Jar",
"item.unicopia.filled_jar": "%s in a Jar", "item.unicopia.filled_jar": "%s in a Jar",
"item.unicopia.rain_cloud_jar": "Rain in a Jar", "item.unicopia.rain_cloud_jar": "Rain in a Jar",
"item.unicopia.cloud_jar": "Rain in a Jar",
"item.unicopia.storm_cloud_jar": "Storm in a Jar", "item.unicopia.storm_cloud_jar": "Storm in a Jar",
"block.unicopia.storm_jar": "Storm in a Jar",
"item.unicopia.lightning_jar": "Lightning in a Jar", "item.unicopia.lightning_jar": "Lightning in a Jar",
"block.unicopia.lightning_jar": "Lightning in a Jar",
"item.unicopia.zap_apple_jam_jar": "Zap Apple Jam", "item.unicopia.zap_apple_jam_jar": "Zap Apple Jam",
"block.unicopia.zap_jar": "Jar of Zap Apple Jam",
"item.unicopia.toast": "Toast", "item.unicopia.toast": "Toast",
"item.unicopia.burned_toast": "Burned Toast", "item.unicopia.burned_toast": "Burned Toast",
"item.unicopia.jam_toast": "Toast with Zap Apple Jam", "item.unicopia.jam_toast": "Toast with Zap Apple Jam",

View file

@ -0,0 +1,56 @@
{
"textures": {
"cloud": "unicopia:block/cloud",
"particle": "#cloud"
},
"elements": [
{
"from": [5.1, 6.1, 5.1],
"to": [9.9, 8.9, 8.9],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#cloud"},
"east": {"uv": [0, 6, 8, 16], "texture": "#cloud"},
"south": {"uv": [8, 6, 16, 16], "texture": "#cloud"},
"west": {"uv": [8, 0, 16, 10], "texture": "#cloud"},
"up": {"uv": [4, 3, 12, 11], "texture": "#cloud"},
"down": {"uv": [8, 4, 16, 12], "texture": "#cloud"}
}
},
{
"from": [6.1, 4.1, 7.1],
"to": [11.9, 6.9, 10.9],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#cloud"},
"east": {"uv": [0, 6, 8, 16], "texture": "#cloud"},
"south": {"uv": [8, 6, 16, 16], "texture": "#cloud"},
"west": {"uv": [8, 0, 16, 10], "texture": "#cloud"},
"up": {"uv": [4, 3, 12, 11], "texture": "#cloud"},
"down": {"uv": [8, 4, 16, 12], "texture": "#cloud"}
}
},
{
"from": [6.1, 8.1, 7.1],
"to": [9.9, 9.9, 9.9],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#cloud"},
"east": {"uv": [0, 6, 8, 16], "texture": "#cloud"},
"south": {"uv": [8, 6, 16, 16], "texture": "#cloud"},
"west": {"uv": [8, 0, 16, 10], "texture": "#cloud"},
"up": {"uv": [4, 3, 12, 11], "texture": "#cloud"},
"down": {"uv": [8, 4, 16, 12], "texture": "#cloud"}
}
},
{
"from": [6.1, 7.1, 8.1],
"to": [10.9, 8.9, 10.9],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#cloud"},
"east": {"uv": [0, 6, 8, 16], "texture": "#cloud"},
"south": {"uv": [8, 6, 16, 16], "texture": "#cloud"},
"west": {"uv": [8, 0, 16, 10], "texture": "#cloud"},
"up": {"uv": [4, 3, 12, 11], "texture": "#cloud"},
"down": {"uv": [8, 4, 16, 12], "texture": "#cloud"}
}
}
]
}

View file

@ -0,0 +1,34 @@
{
"textures": {
"filling": "unicopia:block/lightning_jar_filling",
"particle": "#filling"
},
"elements": [
{
"from": [6, 1, 7.5],
"to": [11, 11, 7.5],
"rotation": {"angle": -45, "axis": "y", "origin": [8, 5, 7], "rescale": true},
"faces": {
"north": {"uv": [3, 0, 13, 16], "texture": "#filling"},
"east": {"uv": [0, 0, 0, 8], "texture": "#filling"},
"south": {"uv": [3, 0, 13, 16], "texture": "#filling"},
"west": {"uv": [0, 0, 0, 8], "texture": "#filling"},
"up": {"uv": [0, 0, 6, 0], "texture": "#filling"},
"down": {"uv": [0, 0, 6, 0], "texture": "#filling"}
}
},
{
"from": [5, 1, 7.5],
"to": [10, 11, 7.5],
"rotation": {"angle": 45, "axis": "y", "origin": [8, 5, 7], "rescale": true},
"faces": {
"north": {"uv": [3, 0, 13, 16], "texture": "#filling"},
"east": {"uv": [0, 0, 0, 8], "texture": "#filling"},
"south": {"uv": [3, 0, 13, 16], "texture": "#filling"},
"west": {"uv": [0, 0, 0, 8], "texture": "#filling"},
"up": {"uv": [0, 0, 6, 0], "rotation": 180, "texture": "#filling"},
"down": {"uv": [0, 0, 6, 0], "rotation": 180, "texture": "#filling"}
}
}
]
}

View file

@ -0,0 +1,140 @@
{
"textures": {
"cloud": "unicopia:block/cloud",
"particle": "#cloud"
},
"elements": [
{
"from": [4.1, 3.1, 4.1],
"to": [11.9, 11.9, 11.9],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#cloud"},
"east": {"uv": [0, 6, 8, 16], "texture": "#cloud"},
"south": {"uv": [8, 6, 16, 16], "texture": "#cloud"},
"west": {"uv": [8, 0, 16, 10], "texture": "#cloud"},
"up": {"uv": [4, 3, 12, 11], "texture": "#cloud"},
"down": {"uv": [8, 4, 16, 12], "texture": "#cloud"}
}
},
{
"from": [6.1, 2.1, 5.1],
"to": [10.9, 2.9, 10.9],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#cloud"},
"east": {"uv": [0, 6, 8, 16], "texture": "#cloud"},
"south": {"uv": [8, 6, 16, 16], "texture": "#cloud"},
"west": {"uv": [8, 0, 16, 10], "texture": "#cloud"},
"up": {"uv": [4, 3, 12, 11], "texture": "#cloud"},
"down": {"uv": [8, 4, 16, 12], "texture": "#cloud"}
}
},
{
"from": [7.1, 11.1, 6.1],
"to": [12.9, 13.9, 9.9],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#cloud"},
"east": {"uv": [0, 6, 8, 16], "texture": "#cloud"},
"south": {"uv": [8, 6, 16, 16], "texture": "#cloud"},
"west": {"uv": [8, 0, 16, 10], "texture": "#cloud"},
"up": {"uv": [4, 3, 12, 11], "texture": "#cloud"},
"down": {"uv": [8, 4, 16, 12], "texture": "#cloud"}
}
},
{
"from": [3, 9, 10],
"to": [5, 11, 12],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#cloud"},
"east": {"uv": [0, 6, 8, 16], "texture": "#cloud"},
"south": {"uv": [8, 6, 16, 16], "texture": "#cloud"},
"west": {"uv": [8, 0, 16, 10], "texture": "#cloud"},
"up": {"uv": [4, 3, 12, 11], "texture": "#cloud"},
"down": {"uv": [8, 4, 16, 12], "texture": "#cloud"}
}
},
{
"from": [3.1, 10.1, 7.1],
"to": [8.9, 12.9, 10.9],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#cloud"},
"east": {"uv": [0, 6, 8, 16], "texture": "#cloud"},
"south": {"uv": [8, 6, 16, 16], "texture": "#cloud"},
"west": {"uv": [8, 0, 16, 10], "texture": "#cloud"},
"up": {"uv": [4, 3, 12, 11], "texture": "#cloud"},
"down": {"uv": [8, 4, 16, 12], "texture": "#cloud"}
}
},
{
"from": [11, 10, 9],
"to": [13, 12, 11],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#cloud"},
"east": {"uv": [0, 6, 8, 16], "texture": "#cloud"},
"south": {"uv": [8, 6, 16, 16], "texture": "#cloud"},
"west": {"uv": [8, 0, 16, 10], "texture": "#cloud"},
"up": {"uv": [4, 3, 12, 11], "texture": "#cloud"},
"down": {"uv": [8, 4, 16, 12], "texture": "#cloud"}
}
},
{
"from": [9, 13, 7],
"to": [11, 15, 9],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#cloud"},
"east": {"uv": [0, 6, 8, 16], "texture": "#cloud"},
"south": {"uv": [8, 6, 16, 16], "texture": "#cloud"},
"west": {"uv": [8, 0, 16, 10], "texture": "#cloud"},
"up": {"uv": [4, 3, 12, 11], "texture": "#cloud"},
"down": {"uv": [8, 4, 16, 12], "texture": "#cloud"}
}
},
{
"from": [5, 13, 7],
"to": [7, 15, 9],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#cloud"},
"east": {"uv": [0, 6, 8, 16], "texture": "#cloud"},
"south": {"uv": [8, 6, 16, 16], "texture": "#cloud"},
"west": {"uv": [8, 0, 16, 10], "texture": "#cloud"},
"up": {"uv": [4, 3, 12, 11], "texture": "#cloud"},
"down": {"uv": [8, 4, 16, 12], "texture": "#cloud"}
}
},
{
"from": [3, 8, 5],
"to": [5, 10, 7],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#cloud"},
"east": {"uv": [0, 6, 8, 16], "texture": "#cloud"},
"south": {"uv": [8, 6, 16, 16], "texture": "#cloud"},
"west": {"uv": [8, 0, 16, 10], "texture": "#cloud"},
"up": {"uv": [4, 3, 12, 11], "texture": "#cloud"},
"down": {"uv": [8, 4, 16, 12], "texture": "#cloud"}
}
},
{
"from": [6.1, 10.1, 7.1],
"to": [9.9, 11.9, 9.9],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#cloud"},
"east": {"uv": [0, 6, 8, 16], "texture": "#cloud"},
"south": {"uv": [8, 6, 16, 16], "texture": "#cloud"},
"west": {"uv": [8, 0, 16, 10], "texture": "#cloud"},
"up": {"uv": [4, 3, 12, 11], "texture": "#cloud"},
"down": {"uv": [8, 4, 16, 12], "texture": "#cloud"}
}
},
{
"from": [6.1, 11.1, 9.1],
"to": [10.9, 12.9, 11.9],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#cloud"},
"east": {"uv": [0, 6, 8, 16], "texture": "#cloud"},
"south": {"uv": [8, 6, 16, 16], "texture": "#cloud"},
"west": {"uv": [8, 0, 16, 10], "texture": "#cloud"},
"up": {"uv": [4, 3, 12, 11], "texture": "#cloud"},
"down": {"uv": [8, 4, 16, 12], "texture": "#cloud"}
}
}
]
}

View file

@ -0,0 +1,57 @@
{
"textures": {
"body": "unicopia:block/jar_body",
"cork": "unicopia:block/jar_cork",
"particle": "#body"
},
"elements": [
{
"from": [4, 0, 4],
"to": [12, 12, 12],
"faces": {
"north": {"uv": [0, 0, 8, 12], "texture": "#body"},
"east": {"uv": [0, 0, 8, 12], "texture": "#body"},
"south": {"uv": [0, 0, 8, 12], "texture": "#body"},
"west": {"uv": [0, 0, 8, 12], "texture": "#body"},
"up": {"uv": [8, 0, 16, 8], "texture": "#body"},
"down": {"uv": [8, 0, 16, 8], "texture": "#body"}
}
},
{
"from": [5, 13, 5],
"to": [11, 14, 11],
"faces": {
"north": {"uv": [0, 0, 8, 1], "texture": "#body"},
"east": {"uv": [0, 0, 8, 1], "texture": "#body"},
"south": {"uv": [0, 0, 8, 1], "texture": "#body"},
"west": {"uv": [0, 0, 8, 1], "texture": "#body"},
"up": {"uv": [8, 0, 16, 8], "texture": "#body"},
"down": {"uv": [8, 0, 16, 8], "texture": "#body"}
}
},
{
"from": [6, 12, 6],
"to": [10, 13, 10],
"faces": {
"north": {"uv": [0, 0, 8, 1], "texture": "#body"},
"east": {"uv": [0, 0, 8, 1], "texture": "#body"},
"south": {"uv": [0, 0, 8, 1], "texture": "#body"},
"west": {"uv": [0, 0, 8, 1], "texture": "#body"},
"up": {"uv": [8, 0, 16, 8], "texture": "#body"},
"down": {"uv": [8, 0, 16, 8], "texture": "#body"}
}
},
{
"from": [6, 13, 6],
"to": [10, 16, 10],
"faces": {
"north": {"uv": [0, 4, 4, 7], "texture": "#cork"},
"east": {"uv": [0, 4, 4, 7], "texture": "#cork"},
"south": {"uv": [0, 4, 4, 7], "texture": "#cork"},
"west": {"uv": [0, 4, 4, 7], "texture": "#cork"},
"up": {"uv": [0, 0, 4, 4], "texture": "#cork"},
"down": {"uv": [4, 0, 8, 4], "texture": "#cork"}
}
}
]
}

View file

@ -0,0 +1,20 @@
{
"textures": {
"filling": "unicopia:block/zap_jar_filling",
"particle": "#filling"
},
"elements": [
{
"from": [4.1, 0.1, 4.1],
"to": [11.9, 9.9, 11.9],
"faces": {
"north": {"uv": [0, 2, 8, 12], "texture": "#filling"},
"east": {"uv": [0, 6, 8, 16], "texture": "#filling"},
"south": {"uv": [8, 6, 16, 16], "texture": "#filling"},
"west": {"uv": [8, 0, 16, 10], "texture": "#filling"},
"up": {"uv": [4, 3, 12, 11], "texture": "#filling"},
"down": {"uv": [8, 4, 16, 12], "texture": "#filling"}
}
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB