generated from Nekojimi/ForgeModTemplate
WIP: prototype item teleportation to random dimensions, with safe landing.
This commit is contained in:
parent
21392fc84b
commit
1f9a053f68
|
@ -0,0 +1,64 @@
|
|||
package moe.nekojimi.dimensionwalker;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.minecraft.client.renderer.item.ItemProperties;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.commands.TeleportCommand;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.NetherPortalBlock;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
public class DimensionwalkerItem extends Item
|
||||
{
|
||||
private static DeferredRegister<Level> DIMENSION_REGISTER = DeferredRegister.create(Registry.DIMENSION_REGISTRY, DimensionwalkerMod.MODID);
|
||||
|
||||
private static final org.slf4j.Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public DimensionwalkerItem() {
|
||||
super(new Item.Properties().tab(CreativeModeTab.TAB_TOOLS));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InteractionResultHolder<ItemStack> use(Level level, @NotNull Player player, @NotNull InteractionHand hand)
|
||||
{
|
||||
if (!level.isClientSide())
|
||||
{
|
||||
MinecraftServer server = level.getServer();
|
||||
if (server != null)
|
||||
{
|
||||
Iterable<ServerLevel> allLevels = server.getAllLevels();
|
||||
List<ServerLevel> levels = new java.util.ArrayList<>(StreamSupport.stream(allLevels.spliterator(), false).toList());
|
||||
levels.remove((ServerLevel) level);
|
||||
ServerLevel destination = levels.get(new Random().nextInt(levels.size()));
|
||||
// server.getPlayerList().getPlayer(player.getUUID()).teleportTo(destination, player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
|
||||
ServerPlayer serverPlayer = server.getPlayerList().getPlayer(player.getUUID());
|
||||
if (serverPlayer != null)
|
||||
serverPlayer.changeDimension(destination, DimensionwalkerTeleporter.instance());
|
||||
else
|
||||
LOGGER.warn("Can't teleport, serverPlayer == null");
|
||||
}
|
||||
else
|
||||
LOGGER.warn("Can't teleport, server == null");
|
||||
}
|
||||
return super.use(level, player, hand);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package moe.nekojimi.dimensionwalker;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.event.server.ServerStartingEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
// The value here should match an entry in the META-INF/mods.toml file
|
||||
@Mod(DimensionwalkerMod.MODID)
|
||||
public class DimensionwalkerMod
|
||||
{
|
||||
// Define mod id in a common place for everything to reference
|
||||
public static final String MODID = "examplemod";
|
||||
// Directly reference a slf4j logger
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID);
|
||||
|
||||
public static final RegistryObject<Item> DIMENSIONWALKER_GLOVE_ITEM = ITEMS.register("dimensionwalker_glove", ()->new DimensionwalkerItem() );
|
||||
|
||||
public DimensionwalkerMod()
|
||||
{
|
||||
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
|
||||
// Register the commonSetup method for modloading
|
||||
modEventBus.addListener(this::commonSetup);
|
||||
|
||||
// Register the Deferred Register to the mod event bus so items get registered
|
||||
ITEMS.register(modEventBus);
|
||||
|
||||
// Register ourselves for server and other game events we are interested in
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
}
|
||||
|
||||
private void commonSetup(final FMLCommonSetupEvent event)
|
||||
{
|
||||
// Some common setup code
|
||||
LOGGER.info("HELLO FROM COMMON SETUP");
|
||||
LOGGER.info("DIRT BLOCK >> {}", ForgeRegistries.BLOCKS.getKey(Blocks.DIRT));
|
||||
}
|
||||
|
||||
// You can use SubscribeEvent and let the Event Bus discover methods to call
|
||||
@SubscribeEvent
|
||||
public void onServerStarting(ServerStartingEvent event)
|
||||
{
|
||||
// Do something when the server starts
|
||||
LOGGER.info("HELLO from server starting");
|
||||
|
||||
Iterable<ServerLevel> levels = event.getServer().getAllLevels();
|
||||
levels.forEach(serverLevel ->
|
||||
{
|
||||
LOGGER.info(serverLevel.dimension().toString() + " scale: " + serverLevel.dimensionType().coordinateScale());
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
package moe.nekojimi.dimensionwalker;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.border.WorldBorder;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.portal.PortalInfo;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.common.util.ITeleporter;
|
||||
import org.apache.http.io.SessionOutputBuffer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class DimensionwalkerTeleporter implements ITeleporter
|
||||
{
|
||||
private static DimensionwalkerTeleporter INSTANCE = null;
|
||||
|
||||
@Override
|
||||
public Entity placeEntity(Entity entity, ServerLevel currentWorld, ServerLevel destWorld, float yaw, Function<Boolean, Entity> repositionEntity)
|
||||
{
|
||||
return repositionEntity.apply(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PortalInfo getPortalInfo(Entity entity, ServerLevel destWorld, Function<ServerLevel, PortalInfo> defaultPortalInfo)
|
||||
{
|
||||
// return ITeleporter.super.getPortalInfo(entity, destWorld, defaultPortalInfo);
|
||||
|
||||
BlockPos startPos = new BlockPos(entity.getBlockX(), entity.getBlockY(), entity.getBlockZ());
|
||||
System.out.println("Current player position: " + startPos);
|
||||
// ChunkAccess chunk = destWorld.getChunk(startPos);
|
||||
// int maxHeight = startPos.getY();
|
||||
// destWorld.get
|
||||
// for (Heightmap.Types type : Heightmap.Types.values())
|
||||
// {
|
||||
// int height = chunk.getHeight(type,startPos.getX(),startPos.getZ());
|
||||
// System.out.println("Heightmap type: " + type.name() + ", height: " + height);
|
||||
// if (height > maxHeight)
|
||||
// maxHeight = height;
|
||||
// }
|
||||
BlockPos blockPos = findSafePosition(destWorld,startPos);
|
||||
if (blockPos == null)
|
||||
blockPos = startPos;
|
||||
return new PortalInfo(new Vec3((double)blockPos.getX() + 0.5D, (double)blockPos.getY()+1.0D, (double)blockPos.getZ() + 0.5D), entity.getDeltaMovement(), entity.getYRot(), entity.getXRot());
|
||||
}
|
||||
|
||||
public @Nullable BlockPos findSafePosition(ServerLevel destWorld, BlockPos startPos)
|
||||
{
|
||||
// List<BlockPos> candidates = new ArrayList<>();
|
||||
|
||||
WorldBorder worldborder = destWorld.getWorldBorder();
|
||||
int worldHeight = Math.min(destWorld.getMaxBuildHeight(), destWorld.getMinBuildHeight() + destWorld.getLogicalHeight()) - 1;
|
||||
|
||||
outer:
|
||||
for (BlockPos.MutableBlockPos pos : BlockPos.spiralAround(startPos, 16, Direction.EAST, Direction.SOUTH))
|
||||
{
|
||||
if (pos == null)
|
||||
return null;
|
||||
ChunkAccess chunk = destWorld.getChunk(pos);
|
||||
int terrainHeight = chunk.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES,pos.getX(),pos.getZ());
|
||||
int freeBlocksAbove = 999;
|
||||
int startY = Math.min(worldHeight, terrainHeight);
|
||||
System.out.println("Starting search for safe destination at Y=" + startY);
|
||||
for (int y = startY; y >= destWorld.getMinBuildHeight(); y--)
|
||||
{
|
||||
pos.setY(y);
|
||||
|
||||
// check that y is solid
|
||||
BlockState blockState = chunk.getBlockState(pos);
|
||||
if (blockState.getMaterial().isSolid())
|
||||
{
|
||||
if (worldborder.isWithinBounds(pos) && y < worldHeight-3 && freeBlocksAbove >= 2)
|
||||
{
|
||||
System.out.println("Found safe destination! pos: " + pos + " material: " + blockState.getMaterial() + " state: " + blockState);
|
||||
return pos;
|
||||
// candidates.add(pos);
|
||||
// if (candidates.size() >= 16)
|
||||
// break outer;
|
||||
}
|
||||
freeBlocksAbove = 0;
|
||||
}
|
||||
else if (blockState.getMaterial().isLiquid() || !blockState.isAir())
|
||||
{
|
||||
freeBlocksAbove = 0; // liquid blocks aren't free
|
||||
}
|
||||
else
|
||||
{
|
||||
freeBlocksAbove++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (candidates.size() > 0)
|
||||
// {
|
||||
// candidates.sort(Comparator.comparingDouble(a -> a.distSqr(startPos)));
|
||||
// return candidates.get(0);
|
||||
// }
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ITeleporter instance()
|
||||
{
|
||||
if (INSTANCE == null)
|
||||
INSTANCE = new DimensionwalkerTeleporter();
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package moe.nekojimi.dimensionwalker;
|
||||
|
||||
public class Peachy
|
||||
{
|
||||
Peachy()
|
||||
{
|
||||
System.out.println("I'm Peachy!");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue