dimension rail, part 1

This commit is contained in:
Ellpeck 2019-03-20 20:51:24 +01:00
parent de2e6aa23a
commit 8ebf432072
9 changed files with 389 additions and 65 deletions

View file

@ -2,11 +2,12 @@ package de.ellpeck.naturesaura.api.misc;
import de.ellpeck.naturesaura.api.NaturesAuraAPI;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.DimensionType;
import net.minecraft.world.World;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
public interface IWorldData extends ICapabilityProvider, INBTSerializable<NBTTagCompound> {
@ -18,8 +19,9 @@ public interface IWorldData extends ICapabilityProvider, INBTSerializable<NBTTag
}
static IWorldData getOverworldData(World world) {
if (!world.isRemote)
return getWorldData(DimensionManager.getWorld(DimensionType.OVERWORLD.getId()));
if (!world.isRemote) {
return getWorldData(world.getMinecraftServer().getWorld(DimensionType.OVERWORLD.getId()));
}
return getWorldData(world);
}

View file

@ -151,7 +151,7 @@ public class BlockContainerImpl extends BlockContainer implements IModItem, ICre
TileEntityImpl impl = (TileEntityImpl) tile;
int newPower = worldIn.getRedstonePowerFromNeighbors(pos);
if (impl.redstonePower != newPower)
((TileEntityImpl) tile).onRedstonePowerChange(newPower);
impl.onRedstonePowerChange(newPower);
}
}
}

View file

@ -0,0 +1,184 @@
package de.ellpeck.naturesaura.blocks;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import de.ellpeck.naturesaura.api.NaturesAuraAPI;
import de.ellpeck.naturesaura.items.ItemRangeVisualizer;
import de.ellpeck.naturesaura.items.ModItems;
import de.ellpeck.naturesaura.packet.PacketClient;
import de.ellpeck.naturesaura.packet.PacketHandler;
import de.ellpeck.naturesaura.reg.ICreativeItem;
import de.ellpeck.naturesaura.reg.IModItem;
import de.ellpeck.naturesaura.reg.IModelProvider;
import de.ellpeck.naturesaura.reg.ModRegistry;
import net.minecraft.block.BlockRailBase;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.item.EntityMinecart;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.IStringSerializable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.DimensionType;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import java.util.Random;
public class BlockDimensionRail extends BlockRailBase implements IModItem, ICreativeItem, IModelProvider {
public static final PropertyEnum<Type> TYPE = PropertyEnum.create("type", Type.class);
public static final PropertyEnum<EnumRailDirection> SHAPE = PropertyEnum.create("shape", EnumRailDirection.class, EnumRailDirection.NORTH_SOUTH, EnumRailDirection.EAST_WEST);
public BlockDimensionRail() {
super(false);
ModRegistry.add(this);
}
@Override
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
ItemStack stack = playerIn.getHeldItem(hand);
if (stack.getItem() == ModItems.RANGE_VISUALIZER) {
if (!worldIn.isRemote) {
Type type = state.getValue(TYPE);
BlockPos goalPos = this.getGoalCoords(worldIn, pos, type);
PacketHandler.sendTo(playerIn,
new PacketClient(0, type.goalDim, goalPos.getX(), goalPos.getY(), goalPos.getZ()));
}
return true;
}
return false;
}
@Override
public void onMinecartPass(World world, EntityMinecart cart, BlockPos pos) {
if (world.isRemote)
return;
if (cart.isBeingRidden())
return;
IBlockState state = world.getBlockState(pos);
Type type = state.getValue(TYPE);
if (!type.canUseHere(world.provider.getDimensionType()))
return;
BlockPos goalCoords = this.getGoalCoords(world, pos, type);
cart.changeDimension(type.goalDim, (newWorld, entity, yaw) ->
entity.moveToBlockPosAndAngles(goalCoords, yaw, entity.rotationPitch));
}
private BlockPos getGoalCoords(World world, BlockPos pos, Type type) {
MinecraftServer server = world.getMinecraftServer();
if (type == Type.NETHER) {
// travel to the nether from the overworld
return new BlockPos(pos.getX() / 8, pos.getY() / 2, pos.getZ() / 8);
} else if (type == Type.END) {
// travel to the end from the overworld
WorldServer end = server.getWorld(type.goalDim);
return end.getSpawnCoordinate().up(8);
} else {
if (world.provider.getDimensionType() == DimensionType.NETHER) {
// travel to the overworld from the nether
return new BlockPos(pos.getX() * 8, pos.getY() * 2, pos.getZ() * 8);
} else {
// travel to the overworld from the end
World overworld = server.getWorld(type.goalDim);
return overworld.getTopSolidOrLiquidBlock(overworld.getSpawnPoint());
}
}
}
@Override
public IProperty<EnumRailDirection> getShapeProperty() {
return SHAPE;
}
@Override
public boolean isFlexibleRail(IBlockAccess world, BlockPos pos) {
return false;
}
@Override
public boolean canMakeSlopes(IBlockAccess world, BlockPos pos) {
return false;
}
@Override
protected BlockStateContainer createBlockState() {
return new BlockStateContainer(this, TYPE, SHAPE);
}
@Override
public int getMetaFromState(IBlockState state) {
int meta = 0;
meta |= state.getValue(SHAPE).getMetadata();
meta |= state.getValue(TYPE).ordinal() << 1;
return meta;
}
@Override
public IBlockState getStateFromMeta(int meta) {
return this.getDefaultState()
.withProperty(SHAPE, EnumRailDirection.byMetadata(meta & 1))
.withProperty(TYPE, Type.values()[meta >> 1]);
}
@Override
public String getBaseName() {
return "dimension_rail";
}
@Override
public void onPreInit(FMLPreInitializationEvent event) {
}
@Override
public void onInit(FMLInitializationEvent event) {
}
@Override
public void onPostInit(FMLPostInitializationEvent event) {
}
public enum Type implements IStringSerializable {
OVERWORLD("overworld", DimensionType.OVERWORLD, DimensionType.NETHER, DimensionType.THE_END),
NETHER("nether", DimensionType.NETHER, DimensionType.OVERWORLD),
END("end", DimensionType.THE_END, DimensionType.OVERWORLD);
private final String name;
private final int goalDim;
private final DimensionType[] canUseDims;
Type(String name, DimensionType goalDim, DimensionType... canUseDims) {
this.name = name;
this.goalDim = goalDim.getId();
this.canUseDims = canUseDims;
}
public boolean canUseHere(DimensionType dimension) {
for (DimensionType dim : this.canUseDims)
if (dim == dimension)
return true;
return false;
}
@Override
public String getName() {
return this.name;
}
}
}

View file

@ -54,4 +54,5 @@ public final class ModBlocks {
public static final Block FIREWORK_GENERATOR = new BlockFireworkGenerator();
public static final Block PROJECTILE_GENERATOR = new BlockProjectileGenerator();
public static final Block CHUNK_LOADER = ModConfig.enabledFeatures.chunkLoader ? new BlockChunkLoader() : null;
public static final Block DIMENSION_RAIL = new BlockDimensionRail();
}

View file

@ -9,6 +9,7 @@ import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk;
import de.ellpeck.naturesaura.api.aura.container.IAuraContainer;
import de.ellpeck.naturesaura.api.aura.type.IAuraType;
import de.ellpeck.naturesaura.api.render.IVisualizable;
import de.ellpeck.naturesaura.blocks.BlockDimensionRail;
import de.ellpeck.naturesaura.blocks.tiles.TileEntityGratedChute;
import de.ellpeck.naturesaura.blocks.tiles.TileEntityNatureAltar;
import de.ellpeck.naturesaura.blocks.tiles.TileEntityRFConverter;
@ -120,10 +121,7 @@ public class ClientEvents {
Minecraft mc = Minecraft.getMinecraft();
if (mc.world == null) {
ParticleHandler.clearParticles();
if (!ItemRangeVisualizer.VISUALIZED_BLOCKS.isEmpty())
ItemRangeVisualizer.VISUALIZED_BLOCKS.clear();
if (!ItemRangeVisualizer.VISUALIZED_ENTITIES.isEmpty())
ItemRangeVisualizer.VISUALIZED_ENTITIES.clear();
ItemRangeVisualizer.clear();
} else if (!mc.isGamePaused()) {
if (mc.world.getTotalWorldTime() % 20 == 0) {
mc.profiler.func_194340_a(() -> NaturesAura.MOD_ID + ":spawnExcessParticles");
@ -156,44 +154,57 @@ public class ClientEvents {
mc.profiler.endSection();
}
if (Helper.isHoldingItem(mc.player, ModItems.RANGE_VISUALIZER) && mc.world.getTotalWorldTime() % 5 == 0) {
NaturesAuraAPI.IInternalHooks inst = NaturesAuraAPI.instance();
inst.setParticleSpawnRange(512);
inst.setParticleDepth(false);
for (BlockPos pos : ItemRangeVisualizer.VISUALIZED_RAILS.get(mc.world.provider.getDimension())) {
NaturesAuraAPI.instance().spawnMagicParticle(
pos.getX() + mc.world.rand.nextFloat(),
pos.getY() + mc.world.rand.nextFloat(),
pos.getZ() + mc.world.rand.nextFloat(),
0F, 0F, 0F, 0xe0faff, mc.world.rand.nextFloat() * 5 + 1, 100, 0F, false, true);
}
inst.setParticleDepth(true);
inst.setParticleSpawnRange(32);
}
mc.profiler.func_194340_a(() -> NaturesAura.MOD_ID + ":updateParticles");
ParticleHandler.updateParticles();
mc.profiler.endSection();
if (mc.player != null) {
if (Compat.baubles) {
IItemHandler baubles = BaublesApi.getBaublesHandler(mc.player);
for (int i = 0; i < baubles.getSlots(); i++) {
ItemStack slot = baubles.getStackInSlot(i);
if (!slot.isEmpty()) {
if (slot.getItem() instanceof ItemAuraCache)
heldCache = slot;
else if (slot.getItem() == ModItems.EYE)
heldEye = slot;
else if (slot.getItem() == ModItems.EYE_IMPROVED)
heldOcular = slot;
}
}
}
for (int i = 0; i < mc.player.inventory.getSizeInventory(); i++) {
ItemStack slot = mc.player.inventory.getStackInSlot(i);
if (Compat.baubles) {
IItemHandler baubles = BaublesApi.getBaublesHandler(mc.player);
for (int i = 0; i < baubles.getSlots(); i++) {
ItemStack slot = baubles.getStackInSlot(i);
if (!slot.isEmpty()) {
if (slot.getItem() instanceof ItemAuraCache)
heldCache = slot;
else if (slot.getItem() == ModItems.EYE && i <= 8)
else if (slot.getItem() == ModItems.EYE)
heldEye = slot;
else if (slot.getItem() == ModItems.EYE_IMPROVED)
heldOcular = slot;
}
}
}
if (!heldOcular.isEmpty() && mc.world.getTotalWorldTime() % 20 == 0) {
SHOWING_EFFECTS.clear();
Helper.getAuraChunksInArea(mc.world, mc.player.getPosition(), 100,
chunk -> chunk.getActiveEffectIcons(mc.player, SHOWING_EFFECTS));
for (int i = 0; i < mc.player.inventory.getSizeInventory(); i++) {
ItemStack slot = mc.player.inventory.getStackInSlot(i);
if (!slot.isEmpty()) {
if (slot.getItem() instanceof ItemAuraCache)
heldCache = slot;
else if (slot.getItem() == ModItems.EYE && i <= 8)
heldEye = slot;
else if (slot.getItem() == ModItems.EYE_IMPROVED)
heldOcular = slot;
}
}
if (!heldOcular.isEmpty() && mc.world.getTotalWorldTime() % 20 == 0) {
SHOWING_EFFECTS.clear();
Helper.getAuraChunksInArea(mc.world, mc.player.getPosition(), 100,
chunk -> chunk.getActiveEffectIcons(mc.player, SHOWING_EFFECTS));
}
}
}
}
@ -243,33 +254,32 @@ public class ClientEvents {
GL11.glPopMatrix();
}
if (mc.objectMouseOver != null) {
if (Helper.isHoldingItem(mc.player, ModItems.RANGE_VISUALIZER)) {
GL11.glPushMatrix();
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBegin(GL11.GL_QUADS);
for (BlockPos pos : ItemRangeVisualizer.VISUALIZED_BLOCKS) {
if (!mc.world.isBlockLoaded(pos))
continue;
IBlockState state = mc.world.getBlockState(pos);
Block block = state.getBlock();
if (!(block instanceof IVisualizable))
continue;
this.renderVisualize((IVisualizable) block, mc.world, pos);
}
for (Entity entity : ItemRangeVisualizer.VISUALIZED_ENTITIES) {
if (entity.isDead || !(entity instanceof IVisualizable))
continue;
this.renderVisualize((IVisualizable) entity, mc.world, entity.getPosition());
}
GL11.glEnd();
GL11.glPopAttrib();
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glPopMatrix();
if (Helper.isHoldingItem(mc.player, ModItems.RANGE_VISUALIZER)) {
int dim = mc.world.provider.getDimension();
GL11.glPushMatrix();
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBegin(GL11.GL_QUADS);
for (BlockPos pos : ItemRangeVisualizer.VISUALIZED_BLOCKS.get(dim)) {
if (!mc.world.isBlockLoaded(pos))
continue;
IBlockState state = mc.world.getBlockState(pos);
Block block = state.getBlock();
if (!(block instanceof IVisualizable))
continue;
this.renderVisualize((IVisualizable) block, mc.world, pos);
}
for (Entity entity : ItemRangeVisualizer.VISUALIZED_ENTITIES.get(dim)) {
if (entity.isDead || !(entity instanceof IVisualizable))
continue;
this.renderVisualize((IVisualizable) entity, mc.world, entity.getPosition());
}
GL11.glEnd();
GL11.glPopAttrib();
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glPopMatrix();
}
GL11.glPopMatrix();

View file

@ -1,6 +1,9 @@
package de.ellpeck.naturesaura.items;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import de.ellpeck.naturesaura.api.render.IVisualizable;
import de.ellpeck.naturesaura.blocks.BlockDimensionRail;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
@ -20,8 +23,9 @@ import java.util.Set;
public class ItemRangeVisualizer extends ItemImpl {
public static final Set<BlockPos> VISUALIZED_BLOCKS = new HashSet<>();
public static final Set<Entity> VISUALIZED_ENTITIES = new HashSet<>();
public static final ListMultimap<Integer, BlockPos> VISUALIZED_BLOCKS = ArrayListMultimap.create();
public static final ListMultimap<Integer, Entity> VISUALIZED_ENTITIES = ArrayListMultimap.create();
public static final ListMultimap<Integer, BlockPos> VISUALIZED_RAILS = ArrayListMultimap.create();
public ItemRangeVisualizer() {
super("range_visualizer");
@ -33,16 +37,26 @@ public class ItemRangeVisualizer extends ItemImpl {
IBlockState state = worldIn.getBlockState(pos);
Block block = state.getBlock();
if (block instanceof IVisualizable) {
int dim = worldIn.provider.getDimension();
if (worldIn.isRemote)
if (VISUALIZED_BLOCKS.contains(pos))
VISUALIZED_BLOCKS.remove(pos);
if (VISUALIZED_BLOCKS.containsEntry(dim, pos))
VISUALIZED_BLOCKS.remove(dim, pos);
else
VISUALIZED_BLOCKS.add(pos);
VISUALIZED_BLOCKS.put(dim, pos);
return EnumActionResult.SUCCESS;
}
return EnumActionResult.PASS;
}
public static void clear() {
if (!VISUALIZED_BLOCKS.isEmpty())
VISUALIZED_BLOCKS.clear();
if (!VISUALIZED_ENTITIES.isEmpty())
VISUALIZED_ENTITIES.clear();
if (!VISUALIZED_RAILS.isEmpty())
VISUALIZED_RAILS.clear();
}
@SubscribeEvent
public void onInteract(PlayerInteractEvent.EntityInteractSpecific event) {
ItemStack stack = event.getItemStack();
@ -51,10 +65,11 @@ public class ItemRangeVisualizer extends ItemImpl {
Entity entity = event.getTarget();
if (entity instanceof IVisualizable) {
if (entity.world.isRemote) {
if (VISUALIZED_ENTITIES.contains(entity))
VISUALIZED_ENTITIES.remove(entity);
int dim = entity.world.provider.getDimension();
if (VISUALIZED_ENTITIES.containsEntry(dim, entity))
VISUALIZED_ENTITIES.remove(dim, entity);
else
VISUALIZED_ENTITIES.add(entity);
VISUALIZED_ENTITIES.put(dim, entity);
}
event.getEntityPlayer().swingArm(event.getHand());
event.setCancellationResult(EnumActionResult.SUCCESS);

View file

@ -0,0 +1,69 @@
package de.ellpeck.naturesaura.packet;
import de.ellpeck.naturesaura.NaturesAura;
import de.ellpeck.naturesaura.items.ItemRangeVisualizer;
import io.netty.buffer.ByteBuf;
import net.minecraft.client.Minecraft;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class PacketClient implements IMessage {
private int type;
private int[] data;
public PacketClient(int type, int... data) {
this.type = type;
this.data = data;
}
public PacketClient() {
}
@Override
public void fromBytes(ByteBuf buf) {
this.type = buf.readByte();
this.data = new int[buf.readByte()];
for (int i = 0; i < this.data.length; i++)
this.data[i] = buf.readInt();
}
@Override
public void toBytes(ByteBuf buf) {
buf.writeByte(this.type);
buf.writeByte(this.data.length);
for (int i : this.data)
buf.writeInt(i);
}
public static class Handler implements IMessageHandler<PacketClient, IMessage> {
@Override
@SideOnly(Side.CLIENT)
public IMessage onMessage(PacketClient message, MessageContext ctx) {
NaturesAura.proxy.scheduleTask(() -> {
World world = Minecraft.getMinecraft().world;
if (world != null) {
switch (message.type) {
case 0: // dimension rail visualization
int goalDim = message.data[0];
BlockPos goalPos = new BlockPos(message.data[1], message.data[2], message.data[3]);
if (ItemRangeVisualizer.VISUALIZED_RAILS.containsEntry(goalDim, goalPos))
ItemRangeVisualizer.VISUALIZED_RAILS.remove(goalDim, goalPos);
else
ItemRangeVisualizer.VISUALIZED_RAILS.put(goalDim, goalPos);
break;
}
}
});
return null;
}
}
}

View file

@ -19,6 +19,7 @@ public final class PacketHandler {
network.registerMessage(PacketParticleStream.Handler.class, PacketParticleStream.class, 0, Side.CLIENT);
network.registerMessage(PacketParticles.Handler.class, PacketParticles.class, 1, Side.CLIENT);
network.registerMessage(PacketAuraChunk.Handler.class, PacketAuraChunk.class, 2, Side.CLIENT);
network.registerMessage(PacketClient.Handler.class, PacketClient.class, 3, Side.CLIENT);
}
public static void sendToAllLoaded(World world, BlockPos pos, IMessage message) {

View file

@ -0,0 +1,42 @@
{
"forge_marker": 1,
"defaults": {
"model": "minecraft:rail_flat",
"transform": "forge:default-block"
},
"variants": {
"normal": [{}],
"inventory": [
{
"model": "builtin/generated",
"textures": {
"layer0": "naturesaura:blocks/dimension_rail_overworld"
},
"transform": "forge:default-item"
}
],
"shape": {
"north_south": {},
"east_west": {
"y": 90
}
},
"type": {
"overworld": {
"textures": {
"rail": "naturesaura:blocks/dimension_rail_overworld"
}
},
"nether": {
"textures": {
"rail": "naturesaura:blocks/dimension_rail_nether"
}
},
"end": {
"textures": {
"rail": "naturesaura:blocks/dimension_rail_end"
}
}
}
}
}