generated from tilera/1710mod
chore: add original code
This commit is contained in:
parent
da1131909f
commit
b68fd76c8f
42 changed files with 4334 additions and 4 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,3 +2,4 @@
|
||||||
.idea
|
.idea
|
||||||
build
|
build
|
||||||
run
|
run
|
||||||
|
bin
|
19
LICENSE
Normal file
19
LICENSE
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) 2012 Alex "immibis" Campbell
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
14
build.gradle
14
build.gradle
|
@ -23,9 +23,9 @@ apply plugin: 'maven-publish'
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
|
||||||
version = "1.0"
|
version = "0.2"
|
||||||
group= "modgroup"
|
group= "tinycarts"
|
||||||
archivesBaseName = "modid"
|
archivesBaseName = "com.immibis"
|
||||||
|
|
||||||
minecraft {
|
minecraft {
|
||||||
version = "1.7.10-10.13.4.1614-1.7.10"
|
version = "1.7.10-10.13.4.1614-1.7.10"
|
||||||
|
@ -34,10 +34,16 @@ minecraft {
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven { url = "https://maven.tilera.xyz" }
|
maven { url = "https://maven.tilera.xyz" }
|
||||||
|
maven {
|
||||||
|
url = "https://s3.tilera.xyz/cdn/minecraft/libs/"
|
||||||
|
metadataSources {
|
||||||
|
artifact()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation 'com.immibis:immibis-core:59.1.4:deobf'
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
|
|
65
src/main/java/mods/immibis/subworlds/ClientFakeEntities.java
Normal file
65
src/main/java/mods/immibis/subworlds/ClientFakeEntities.java
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
package mods.immibis.subworlds;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
import cpw.mods.fml.common.FMLCommonHandler;
|
||||||
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import cpw.mods.fml.common.gameevent.TickEvent;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
// maintains a list of fake entities on the client. there is no server equivalent.
|
||||||
|
// on the server, fake entities are updated and destroyed by whatever created them.
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class ClientFakeEntities {
|
||||||
|
private static Map<Integer, FakeEntity> ents = new HashMap<Integer, FakeEntity>();
|
||||||
|
|
||||||
|
public static void debug(String s) {
|
||||||
|
System.out.println("[SubWorlds CFE Debug] "+s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void add(FakeEntity ent) {
|
||||||
|
debug("Add CFE "+ent.entityID+": "+ent);
|
||||||
|
ents.put(ent.entityID, ent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FakeEntity remove(int entID) {
|
||||||
|
debug("Remove CFE "+entID);
|
||||||
|
return ents.remove(entID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void reset() {
|
||||||
|
debug("Reset CFEs");
|
||||||
|
ents.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FakeEntity get(int entID) {
|
||||||
|
return ents.get(entID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
FMLCommonHandler.instance().bus().register(new ClientTickHandler());
|
||||||
|
MinecraftForge.EVENT_BUS.register(new EventListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ClientTickHandler {
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onClientTickEnd(TickEvent.ClientTickEvent evt) {
|
||||||
|
if(evt.phase != TickEvent.Phase.END) return;
|
||||||
|
for(FakeEntity e : ents.values())
|
||||||
|
e.tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// must be public or forge throws errors
|
||||||
|
public static class EventListener {
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onRWL(RenderWorldLastEvent evt) {
|
||||||
|
for(FakeEntity e : ents.values())
|
||||||
|
e.renderBase(evt.partialTicks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
src/main/java/mods/immibis/subworlds/ExitTeleporter.java
Normal file
27
src/main/java/mods/immibis/subworlds/ExitTeleporter.java
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package mods.immibis.subworlds;
|
||||||
|
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
|
import net.minecraft.world.Teleporter;
|
||||||
|
import net.minecraft.world.WorldServer;
|
||||||
|
|
||||||
|
public class ExitTeleporter extends Teleporter {
|
||||||
|
public WorldServer world;
|
||||||
|
public double x, y, z;
|
||||||
|
|
||||||
|
public ExitTeleporter(WorldServer par1WorldServer, double x, double y, double z) {
|
||||||
|
super(par1WorldServer);
|
||||||
|
world = par1WorldServer;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void placeInPortal(Entity par1Entity, double par2, double par4, double par6, float par8) {
|
||||||
|
if(par1Entity instanceof EntityLivingBase)
|
||||||
|
((EntityLivingBase)par1Entity).setPositionAndUpdate(x, y, z);
|
||||||
|
else
|
||||||
|
par1Entity.setPosition(x, y, z);
|
||||||
|
}
|
||||||
|
}
|
110
src/main/java/mods/immibis/subworlds/FakeEntity.java
Normal file
110
src/main/java/mods/immibis/subworlds/FakeEntity.java
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
package mods.immibis.subworlds;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.entity.EntityClientPlayerMP;
|
||||||
|
import net.minecraft.client.renderer.entity.RenderEntity;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.network.Packet;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object which is synced with clients, like an entity, but isn't actually an entity.
|
||||||
|
* They are not automatically associated with a world.
|
||||||
|
*/
|
||||||
|
public abstract class FakeEntity {
|
||||||
|
public abstract Packet getUpdatePacket();
|
||||||
|
public abstract Packet getDescriptionPacket();
|
||||||
|
public abstract Packet getDestructionPacket();
|
||||||
|
|
||||||
|
private static AtomicInteger nextEntityID = new AtomicInteger();
|
||||||
|
|
||||||
|
public final int entityID;
|
||||||
|
public final boolean isClient;
|
||||||
|
|
||||||
|
public FakeEntity(boolean isClient) {
|
||||||
|
entityID = nextEntityID.incrementAndGet();
|
||||||
|
this.isClient = isClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FakeEntity(boolean isClient, int entityID) {
|
||||||
|
this.entityID = entityID;
|
||||||
|
this.isClient = isClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<EntityPlayerMP> trackingPlayers = new HashSet<EntityPlayerMP>();
|
||||||
|
|
||||||
|
public final void setTrackingPlayers(Set<EntityPlayerMP> _new) {
|
||||||
|
for(EntityPlayerMP pl : _new)
|
||||||
|
if(!trackingPlayers.contains(pl)) {
|
||||||
|
Packet packet = getDescriptionPacket();
|
||||||
|
if(packet != null)
|
||||||
|
pl.playerNetServerHandler.netManager.channel().write(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(EntityPlayerMP pl : trackingPlayers)
|
||||||
|
if(!_new.contains(pl)) {
|
||||||
|
Packet packet = getDestructionPacket();
|
||||||
|
if(packet != null)
|
||||||
|
pl.playerNetServerHandler.netManager.channel().write(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
trackingPlayers.clear();
|
||||||
|
trackingPlayers.addAll(_new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick() {
|
||||||
|
if(!isClient) {
|
||||||
|
Packet p = getUpdatePacket();
|
||||||
|
|
||||||
|
if(p != null)
|
||||||
|
for(EntityPlayerMP pl : trackingPlayers)
|
||||||
|
pl.playerNetServerHandler.netManager.channel().write(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
protected static RenderEntity defaultRender;
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
protected static Entity defaultRenderEntity;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
RenderEntity rd = new RenderEntity();
|
||||||
|
defaultRender = rd;
|
||||||
|
defaultRenderEntity = new Entity(null) {
|
||||||
|
{
|
||||||
|
boundingBox.setBounds(-1, -1, -1, 1, 1, 1);
|
||||||
|
lastTickPosX = lastTickPosY = lastTickPosZ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override protected void entityInit() {}
|
||||||
|
@Override protected void readEntityFromNBT(NBTTagCompound var1) {}
|
||||||
|
@Override protected void writeEntityToNBT(NBTTagCompound var1) {}
|
||||||
|
};
|
||||||
|
} catch(Error e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
// rendering origin is at world coordinates: -pl_x,-pl_y,-pl_z
|
||||||
|
public void render(double pl_x, double pl_y, double pl_z, float partialTick) {
|
||||||
|
defaultRender.doRender(defaultRenderEntity, 3, 3, 3, 0, partialTick);
|
||||||
|
defaultRender.doRender(defaultRenderEntity, -pl_x-2, -pl_y-2, -pl_z-2, 0, partialTick);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
void renderBase(float partialTick) {
|
||||||
|
EntityClientPlayerMP pl = Minecraft.getMinecraft().thePlayer;
|
||||||
|
double pl_x = pl.lastTickPosX + (pl.posX - pl.lastTickPosX) * partialTick;
|
||||||
|
double pl_y = pl.lastTickPosY + (pl.posY - pl.lastTickPosY) * partialTick;
|
||||||
|
double pl_z = pl.lastTickPosZ + (pl.posZ - pl.lastTickPosZ) * partialTick;
|
||||||
|
render(pl_x, pl_y, pl_z, partialTick);
|
||||||
|
}
|
||||||
|
}
|
52
src/main/java/mods/immibis/subworlds/SubWorldsMod.java
Normal file
52
src/main/java/mods/immibis/subworlds/SubWorldsMod.java
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
package mods.immibis.subworlds;
|
||||||
|
|
||||||
|
import mods.immibis.core.api.porting.SidedProxy;
|
||||||
|
import mods.immibis.subworlds.dw.DWEntity;
|
||||||
|
import mods.immibis.subworlds.dw.DWEntityRenderer;
|
||||||
|
import mods.immibis.subworlds.dw.DWManager;
|
||||||
|
import mods.immibis.subworlds.mws.MWSManager;
|
||||||
|
import cpw.mods.fml.client.registry.RenderingRegistry;
|
||||||
|
import cpw.mods.fml.common.FMLCommonHandler;
|
||||||
|
import cpw.mods.fml.common.Mod;
|
||||||
|
import cpw.mods.fml.common.Mod.EventHandler;
|
||||||
|
import cpw.mods.fml.common.Mod.Instance;
|
||||||
|
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||||
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import cpw.mods.fml.common.network.FMLNetworkEvent;
|
||||||
|
import cpw.mods.fml.common.registry.EntityRegistry;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@Mod(version="0.0", dependencies="required-after:ImmibisCore", modid=SubWorldsMod.MODID, name="SubWorlds")
|
||||||
|
public class SubWorldsMod {
|
||||||
|
|
||||||
|
public static final String MODID = "SubWorlds";
|
||||||
|
|
||||||
|
@Instance(MODID)
|
||||||
|
public static SubWorldsMod INSTANCE;
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void onClientConnectedToServer(FMLNetworkEvent.ClientConnectedToServerEvent evt) {
|
||||||
|
ClientFakeEntities.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public static class ClientProxy {
|
||||||
|
public ClientProxy() {
|
||||||
|
ClientFakeEntities.init();
|
||||||
|
RenderingRegistry.registerEntityRenderingHandler(DWEntity.class, new DWEntityRenderer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void init(FMLInitializationEvent evt) {
|
||||||
|
DWManager.init();
|
||||||
|
MWSManager.init();
|
||||||
|
|
||||||
|
FMLCommonHandler.instance().bus().register(this);
|
||||||
|
|
||||||
|
SidedProxy.instance.createSidedObject("mods.immibis.subworlds.SubWorldsMod$ClientProxy", null);
|
||||||
|
EntityRegistry.registerModEntity(DWEntity.class, "detachedWorld", 0, this, 200, 5, true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package mods.immibis.subworlds.dw;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import mods.immibis.subworlds.SubWorldsMod;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.common.ForgeChunkManager;
|
||||||
|
import net.minecraftforge.common.ForgeChunkManager.LoadingCallback;
|
||||||
|
import net.minecraftforge.common.ForgeChunkManager.OrderedLoadingCallback;
|
||||||
|
import net.minecraftforge.common.ForgeChunkManager.Ticket;
|
||||||
|
import cpw.mods.fml.relauncher.ReflectionHelper;
|
||||||
|
|
||||||
|
public class ChunkLoadingCallback implements LoadingCallback, OrderedLoadingCallback {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ticketsLoaded(List<Ticket> tickets, World world) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Ticket> ticketsLoaded(List<Ticket> tickets, World world, int maxTicketCount) {
|
||||||
|
// do not keep chunks loaded through world reloads
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChunkLoadingCallback() {
|
||||||
|
try {
|
||||||
|
boolean overridesEnabled = ReflectionHelper.getPrivateValue(ForgeChunkManager.class, null, "overridesEnabled");
|
||||||
|
|
||||||
|
Map<String, Integer> ticketConstraints = ReflectionHelper.getPrivateValue(ForgeChunkManager.class, null, "ticketConstraints");
|
||||||
|
Map<String, Integer> chunkConstraints = ReflectionHelper.getPrivateValue(ForgeChunkManager.class, null, "chunkConstraints");
|
||||||
|
|
||||||
|
if(!overridesEnabled) {
|
||||||
|
ticketConstraints.clear();
|
||||||
|
chunkConstraints.clear();
|
||||||
|
ReflectionHelper.findField(ForgeChunkManager.class, "overridesEnabled").set(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
String modid = SubWorldsMod.MODID;
|
||||||
|
|
||||||
|
ticketConstraints.put(modid, Integer.MAX_VALUE);
|
||||||
|
chunkConstraints.put(modid, Integer.MAX_VALUE);
|
||||||
|
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
ForgeChunkManager.setForcedChunkLoadingCallback(SubWorldsMod.INSTANCE, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
160
src/main/java/mods/immibis/subworlds/dw/DWChunkGenerator.java
Normal file
160
src/main/java/mods/immibis/subworlds/dw/DWChunkGenerator.java
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
package mods.immibis.subworlds.dw;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.minecraft.entity.EnumCreatureType;
|
||||||
|
import net.minecraft.init.Blocks;
|
||||||
|
import net.minecraft.util.IProgressUpdate;
|
||||||
|
import net.minecraft.world.ChunkPosition;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.WorldServer;
|
||||||
|
import net.minecraft.world.biome.BiomeGenBase;
|
||||||
|
import net.minecraft.world.chunk.Chunk;
|
||||||
|
import net.minecraft.world.chunk.IChunkProvider;
|
||||||
|
|
||||||
|
public class DWChunkGenerator implements IChunkProvider {
|
||||||
|
|
||||||
|
public static final BiomeGenBase BIOME = BiomeGenBase.plains;
|
||||||
|
|
||||||
|
public final DWWorldProvider provider;
|
||||||
|
private final int HSIZE; // chunks
|
||||||
|
|
||||||
|
private WorldServer worldObj;
|
||||||
|
//private EmptyChunk emptyChunk;
|
||||||
|
|
||||||
|
public DWChunkGenerator(WorldServer worldObj, DWWorldProvider provider) {
|
||||||
|
this.worldObj = worldObj;
|
||||||
|
this.provider = provider;
|
||||||
|
this.HSIZE = Math.max(provider.props.zsize, provider.props.xsize) / 16;
|
||||||
|
//emptyChunk = new EmptyChunk(worldObj, -10000, -10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean chunkExists(int var1, int var2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Chunk provideChunk(int var1, int var2) {
|
||||||
|
boolean outOfBounds = var1 < 0 || var2 < 0 || var1 >= HSIZE || var2 >= HSIZE;
|
||||||
|
|
||||||
|
// if(outOfBounds) return emptyChunk;
|
||||||
|
|
||||||
|
Chunk chunk = new Chunk(this.worldObj, var1, var2);
|
||||||
|
|
||||||
|
if(!outOfBounds) {
|
||||||
|
|
||||||
|
/*for(int y = 0; y < provider.props.vsize; y++) {
|
||||||
|
if(var1 == 0 && var2 == 0)
|
||||||
|
chunk.setBlockIDWithMetadata(0, y, 0, Block.stone.blockID, 0);
|
||||||
|
if(var1 == HSIZE-1 && var2 == 0)
|
||||||
|
chunk.setBlockIDWithMetadata(15, y, 0, Block.stone.blockID, 0);
|
||||||
|
if(var1 == 0 && var2 == HSIZE-1)
|
||||||
|
chunk.setBlockIDWithMetadata(0, y, 15, Block.stone.blockID, 0);
|
||||||
|
if(var1 == HSIZE-1 && var2 == HSIZE-1)
|
||||||
|
chunk.setBlockIDWithMetadata(15, y, 15, Block.stone.blockID, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int x = 0; x < 16; x++) {
|
||||||
|
if(var1 == 0) {
|
||||||
|
chunk.setBlockIDWithMetadata(0, 0, x, Block.stone.blockID, 0);
|
||||||
|
chunk.setBlockIDWithMetadata(0, provider.props.vsize-1, x, Block.stone.blockID, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(var1 == HSIZE-1) {
|
||||||
|
chunk.setBlockIDWithMetadata(15, 0, x, Block.stone.blockID, 0);
|
||||||
|
chunk.setBlockIDWithMetadata(15, provider.props.vsize-1, x, Block.stone.blockID, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(var2 == 0) {
|
||||||
|
chunk.setBlockIDWithMetadata(x, 0, 0, Block.stone.blockID, 0);
|
||||||
|
chunk.setBlockIDWithMetadata(x, provider.props.vsize-1, 0, Block.stone.blockID, 0);
|
||||||
|
}
|
||||||
|
if(var2 == HSIZE-1) {
|
||||||
|
chunk.setBlockIDWithMetadata(x, 0, 15, Block.stone.blockID, 0);
|
||||||
|
chunk.setBlockIDWithMetadata(x, provider.props.vsize-1, 15, Block.stone.blockID, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int x = 0; x < 16; x++)
|
||||||
|
for(int z = 0; z < 16; z++)
|
||||||
|
chunk.setBlockIDWithMetadata(x, 0, z, Block.stone.blockID, 0);*/
|
||||||
|
|
||||||
|
|
||||||
|
int nx = provider.props.xsize/2 - var1 * 16;
|
||||||
|
int nz = provider.props.zsize/2 - var2 * 16;
|
||||||
|
|
||||||
|
for(int dx = 0; dx < 2; dx++)
|
||||||
|
for(int dy = 0; dy < 2; dy++)
|
||||||
|
for(int dz = 0; dz < 2; dz++) {
|
||||||
|
int x = nx+dx, y = provider.props.ysize/2+dy, z = nz+dz;
|
||||||
|
if(x >= 0 && y >= 0 && z >= 0 && x < 16 && y < provider.props.ysize && z < 16)
|
||||||
|
chunk.func_150807_a(x, y, z, Blocks.stone, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk.generateSkylightMap();
|
||||||
|
|
||||||
|
Arrays.fill(chunk.getBiomeArray(), (byte)BIOME.biomeID);
|
||||||
|
|
||||||
|
chunk.isTerrainPopulated = true;
|
||||||
|
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Chunk loadChunk(int var1, int var2) {
|
||||||
|
return provideChunk(var1, var2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void populate(IChunkProvider var1, int var2, int var3) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean saveChunks(boolean var1, IProgressUpdate var2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean unloadQueuedChunks() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canSave() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String makeString() {
|
||||||
|
return "DWChunkGenerator";
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
@Override
|
||||||
|
public List getPossibleCreatures(EnumCreatureType var1, int var2, int var3, int var4) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkPosition func_147416_a(World var1, String var2, int var3, int var4, int var5) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLoadedChunkCount() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recreateStructures(int var1, int var2) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveExtraData() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
167
src/main/java/mods/immibis/subworlds/dw/DWEntity.java
Normal file
167
src/main/java/mods/immibis/subworlds/dw/DWEntity.java
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
package mods.immibis.subworlds.dw;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import mods.immibis.subworlds.FakeEntity;
|
||||||
|
import mods.immibis.subworlds.mws.MWSListener;
|
||||||
|
import mods.immibis.subworlds.mws.MWSManager;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.WorldServer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DW stands for "Detached World".
|
||||||
|
* Maximum size is always 48x48x48, this cannot easily be changed.
|
||||||
|
* There might be smaller, 16x16x16
|
||||||
|
*/
|
||||||
|
public abstract class DWEntity extends Entity {
|
||||||
|
|
||||||
|
// set of players last known to be tracking this entity which are outside it
|
||||||
|
private Set<EntityPlayerMP> trackingPlayers = new HashSet<EntityPlayerMP>();
|
||||||
|
|
||||||
|
// set of players last known to be inside this entity
|
||||||
|
private Set<EntityPlayerMP> enclosedPlayers = new HashSet<EntityPlayerMP>();
|
||||||
|
|
||||||
|
// fake entity sent to enclosed players to render the external world.
|
||||||
|
private FakeEntity externalWorldFE;
|
||||||
|
|
||||||
|
// internal world, cannot change after initialization
|
||||||
|
private WorldServer internalWorld;
|
||||||
|
|
||||||
|
//private int lastChunkX = Integer.MAX_VALUE, lastChunkZ = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
public DWEntity(World par1World) {
|
||||||
|
super(par1World);
|
||||||
|
setSize(48, 48);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int WATCHER_INDEX_DIMID = 8;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void entityInit() {
|
||||||
|
dataWatcher.addObject(WATCHER_INDEX_DIMID, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void readEntityFromNBT(NBTTagCompound var1) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeEntityToNBT(NBTTagCompound var1) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract WorldServer getInternalWorld();
|
||||||
|
protected abstract void updateExternalWorldFE(FakeEntity e);
|
||||||
|
protected abstract FakeEntity createExternalWorldFE();
|
||||||
|
protected abstract void applyGLRotation(float partialTick);
|
||||||
|
|
||||||
|
private boolean requiresInteriorLoaded = false;
|
||||||
|
public boolean requiresInteriorLoaded() {return requiresInteriorLoaded;}
|
||||||
|
|
||||||
|
/*@Override
|
||||||
|
public void setPosition(double par1, double par3, double par5) {
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setPositionAndRotation(double par1, double par3, double par5, float par7, float par8) {};
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpdate() {
|
||||||
|
|
||||||
|
this.prevPosX = this.posX;
|
||||||
|
this.prevPosY = this.posY;
|
||||||
|
this.prevPosZ = this.posZ;
|
||||||
|
|
||||||
|
/*if(worldObj.isRemote) {
|
||||||
|
posX = serverPosX / 32.0;
|
||||||
|
posY = serverPosY / 32.0;
|
||||||
|
posZ = serverPosZ / 32.0;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if(!worldObj.isRemote) {
|
||||||
|
|
||||||
|
|
||||||
|
int lastDimID = (internalWorld == null ? 0 : internalWorld.provider.dimensionId);
|
||||||
|
internalWorld = getInternalWorld();
|
||||||
|
if(internalWorld.provider.dimensionId != lastDimID)
|
||||||
|
dataWatcher.updateObject(WATCHER_INDEX_DIMID, internalWorld.provider.dimensionId);
|
||||||
|
|
||||||
|
// enclosed players see the outside world via MWS
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Set<EntityPlayerMP> nowEnclosed = new HashSet<EntityPlayerMP>(internalWorld.playerEntities);
|
||||||
|
for(final EntityPlayerMP pl : nowEnclosed)
|
||||||
|
if(!enclosedPlayers.contains(pl)) {
|
||||||
|
MWSManager.getWorldManager(worldObj).addListener(new MWSListener(pl.playerNetServerHandler.netManager) {
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
/*x = (int)DWEntity.this.comX;
|
||||||
|
y = (int)DWEntity.this.comY;
|
||||||
|
z = (int)DWEntity.this.comZ;*/
|
||||||
|
x = (int)posX;
|
||||||
|
y = (int)posY;
|
||||||
|
z = (int)posZ;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for(final EntityPlayerMP pl : enclosedPlayers)
|
||||||
|
if(!nowEnclosed.contains(pl))
|
||||||
|
MWSManager.getWorldManager(worldObj).removeListener(pl.playerNetServerHandler.netManager);
|
||||||
|
|
||||||
|
enclosedPlayers = nowEnclosed;
|
||||||
|
|
||||||
|
// tracking players see the enclosed world via MWS
|
||||||
|
|
||||||
|
Set<EntityPlayerMP> nowTracking = DWUtils.getTrackingPlayers(this);
|
||||||
|
for(final EntityPlayerMP pl : trackingPlayers)
|
||||||
|
if(!nowTracking.contains(pl))
|
||||||
|
MWSManager.getWorldManager(internalWorld).removeListener(pl.playerNetServerHandler.netManager);
|
||||||
|
trackingPlayers.retainAll(nowTracking);
|
||||||
|
|
||||||
|
for(final EntityPlayerMP pl : nowTracking)
|
||||||
|
if(!trackingPlayers.contains(pl)) {
|
||||||
|
MWSManager.getWorldManager(internalWorld).addListener(new MWSListener(pl.playerNetServerHandler.netManager) {
|
||||||
|
@Override public void update() {}
|
||||||
|
});
|
||||||
|
trackingPlayers.add(pl);
|
||||||
|
}
|
||||||
|
|
||||||
|
requiresInteriorLoaded = enclosedPlayers.size() > 0 || trackingPlayers.size() > 0;
|
||||||
|
|
||||||
|
if(externalWorldFE == null) {
|
||||||
|
externalWorldFE = createExternalWorldFE();
|
||||||
|
}
|
||||||
|
|
||||||
|
//DWWorldProvider provider = (DWWorldProvider)getInternalWorld().provider;
|
||||||
|
|
||||||
|
updateExternalWorldFE(externalWorldFE);
|
||||||
|
externalWorldFE.setTrackingPlayers(enclosedPlayers);
|
||||||
|
externalWorldFE.tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInRangeToRenderDist(double distsq) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getEnclosedDimensionClient() {
|
||||||
|
return dataWatcher.getWatchableObjectInt(WATCHER_INDEX_DIMID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onUnloadOrDestroy() {
|
||||||
|
for(final EntityPlayerMP pl : enclosedPlayers)
|
||||||
|
MWSManager.getWorldManager(worldObj).removeListener(pl.playerNetServerHandler.netManager);
|
||||||
|
if(internalWorld != null)
|
||||||
|
for(final EntityPlayerMP pl : trackingPlayers)
|
||||||
|
MWSManager.getWorldManager(internalWorld).removeListener(pl.playerNetServerHandler.netManager);
|
||||||
|
if(externalWorldFE != null)
|
||||||
|
externalWorldFE.setTrackingPlayers(Collections.<EntityPlayerMP>emptySet());
|
||||||
|
}
|
||||||
|
}
|
406
src/main/java/mods/immibis/subworlds/dw/DWEntityRenderer.java
Normal file
406
src/main/java/mods/immibis/subworlds/dw/DWEntityRenderer.java
Normal file
|
@ -0,0 +1,406 @@
|
||||||
|
package mods.immibis.subworlds.dw;
|
||||||
|
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import mods.immibis.subworlds.mws.MWSClientWorld;
|
||||||
|
import mods.immibis.subworlds.mws.MWSManager;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.WorldClient;
|
||||||
|
import net.minecraft.client.particle.EffectRenderer;
|
||||||
|
import net.minecraft.client.renderer.EntityRenderer;
|
||||||
|
import net.minecraft.client.renderer.RenderGlobal;
|
||||||
|
import net.minecraft.client.renderer.RenderHelper;
|
||||||
|
import net.minecraft.client.renderer.culling.ClippingHelperImpl;
|
||||||
|
import net.minecraft.client.renderer.culling.Frustrum;
|
||||||
|
import net.minecraft.client.renderer.entity.RenderEntity;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureMap;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraftforge.client.ForgeHooksClient;
|
||||||
|
import net.minecraftforge.client.MinecraftForgeClient;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
public class DWEntityRenderer extends RenderEntity {
|
||||||
|
private static List clipperStack = new ArrayList();
|
||||||
|
private static Field clipperInstanceField;
|
||||||
|
static {
|
||||||
|
clipperInstanceField = ClippingHelperImpl.class.getDeclaredFields()[0];
|
||||||
|
clipperInstanceField.setAccessible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void pushClipper() {
|
||||||
|
try {
|
||||||
|
clipperStack.add(clipperInstanceField.get(null));
|
||||||
|
clipperInstanceField.set(null, new ClippingHelperImpl());
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void popClipper() {
|
||||||
|
try {
|
||||||
|
clipperInstanceField.set(null, clipperStack.remove(clipperStack.size() - 1));
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doRender(Entity ent_, double x, double y, double z, float yaw, float partialTick) {
|
||||||
|
|
||||||
|
DWEntity ent = (DWEntity)ent_;
|
||||||
|
|
||||||
|
double entX = ent.prevPosX + (ent.posX - ent.prevPosX) * partialTick;
|
||||||
|
double entY = ent.prevPosY + (ent.posY - ent.prevPosY) * partialTick;
|
||||||
|
double entZ = ent.prevPosZ + (ent.posZ - ent.prevPosZ) * partialTick;
|
||||||
|
|
||||||
|
GL11.glPushMatrix();
|
||||||
|
GL11.glTranslated(x, y, z);
|
||||||
|
|
||||||
|
ent.applyGLRotation(partialTick);
|
||||||
|
|
||||||
|
int dimID = ent.getEnclosedDimensionClient();
|
||||||
|
|
||||||
|
MWSClientWorld subWorld = dimID == 0 ? null : MWSManager.getClientWorld(dimID);
|
||||||
|
if(subWorld == null)
|
||||||
|
super.doRender(ent_, 0, 0, 0, yaw, partialTick);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//System.out.println(ent.hashCode()+"\t"+ent.entityId+" at "+entX+" "+entY+" "+entZ+" "+ent.world.getBlockId(5, 0, 5));
|
||||||
|
//System.out.println("Render world "+ent.world+" for "+ent.zeppelinID);
|
||||||
|
//GL11.glTranslated(x - entX, y - entY, z - entZ);
|
||||||
|
//GL11.glTranslated(entX - x, entY - y, entZ - z);
|
||||||
|
|
||||||
|
DWWorldProvider pv = (DWWorldProvider)subWorld.provider;
|
||||||
|
GL11.glTranslatef(-pv.props.xsize/2.0f, 0, -pv.props.zsize/2.0f);
|
||||||
|
|
||||||
|
renderClientWorld(subWorld, partialTick, entX, entY, entZ, 0, 0, 0);
|
||||||
|
}
|
||||||
|
GL11.glPopMatrix();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// e_*: unused.
|
||||||
|
// pl_*: centre of rendered area (we pretend the player is here)
|
||||||
|
// pl_* is also the point in the world that will be rendered at 0,0,0.
|
||||||
|
public static void renderClientWorld(MWSClientWorld world, float partialTick, double e_x, double e_y, double e_z, double pl_x, double pl_y, double pl_z) {
|
||||||
|
Minecraft mc = Minecraft.getMinecraft();
|
||||||
|
|
||||||
|
GL11.glColor3f(1, 1, 1);
|
||||||
|
|
||||||
|
RenderGlobal oldRG = mc.renderGlobal;
|
||||||
|
EntityRenderer oldER = mc.entityRenderer;
|
||||||
|
WorldClient oldWorld = mc.theWorld;
|
||||||
|
mc.renderGlobal = world.render;
|
||||||
|
mc.entityRenderer = world.erender;
|
||||||
|
mc.theWorld = world;
|
||||||
|
int oldPass = MinecraftForgeClient.getRenderPass();
|
||||||
|
pushClipper();
|
||||||
|
|
||||||
|
|
||||||
|
// Pretend the player is at the origin (of the zeppelin world)
|
||||||
|
EntityLivingBase pl = mc.renderViewEntity;
|
||||||
|
double realX = pl.posX, realY = pl.posY, realZ = pl.posZ;
|
||||||
|
double realPrevX = pl.prevPosX, realPrevY = pl.prevPosY, realPrevZ = pl.prevPosZ;
|
||||||
|
double realLastX = pl.lastTickPosX, realLastY = pl.lastTickPosY, realLastZ = pl.lastTickPosZ;
|
||||||
|
pl.posX = pl.prevPosX = pl.lastTickPosX = pl_x;
|
||||||
|
pl.posY = pl.prevPosY = pl.lastTickPosY = pl_y;
|
||||||
|
pl.posZ = pl.prevPosZ = pl.lastTickPosZ = pl_z;
|
||||||
|
|
||||||
|
er_renderWorld(mc.entityRenderer, partialTick, 0);
|
||||||
|
|
||||||
|
popClipper();
|
||||||
|
ForgeHooksClient.setRenderPass(oldPass);
|
||||||
|
mc.theWorld = oldWorld;
|
||||||
|
mc.entityRenderer = oldER;
|
||||||
|
mc.renderGlobal = oldRG;
|
||||||
|
pl.posX = realX;
|
||||||
|
pl.posY = realY;
|
||||||
|
pl.posZ = realZ;
|
||||||
|
pl.prevPosX = realPrevX;
|
||||||
|
pl.prevPosY = realPrevY;
|
||||||
|
pl.prevPosZ = realPrevZ;
|
||||||
|
pl.lastTickPosX = realLastX;
|
||||||
|
pl.lastTickPosY = realLastY;
|
||||||
|
pl.lastTickPosZ = realLastZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void er_renderWorld(EntityRenderer self, float par1, long par2) {
|
||||||
|
Minecraft mc = Minecraft.getMinecraft();
|
||||||
|
|
||||||
|
mc.mcProfiler.startSection("lightTex");
|
||||||
|
|
||||||
|
/*if (self.lightmapUpdateNeeded)
|
||||||
|
{
|
||||||
|
self.updateLightmap(par1);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||||
|
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
if (mc.renderViewEntity == null)
|
||||||
|
{
|
||||||
|
mc.renderViewEntity = mc.thePlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
mc.mcProfiler.endStartSection("pick");
|
||||||
|
//self.getMouseOver(par1);
|
||||||
|
EntityLivingBase entitylivingbase = mc.renderViewEntity;
|
||||||
|
RenderGlobal renderglobal = mc.renderGlobal;
|
||||||
|
EffectRenderer effectrenderer = mc.effectRenderer;
|
||||||
|
double d0 = entitylivingbase.lastTickPosX + (entitylivingbase.posX - entitylivingbase.lastTickPosX) * (double)par1;
|
||||||
|
double d1 = entitylivingbase.lastTickPosY + (entitylivingbase.posY - entitylivingbase.lastTickPosY) * (double)par1;
|
||||||
|
double d2 = entitylivingbase.lastTickPosZ + (entitylivingbase.posZ - entitylivingbase.lastTickPosZ) * (double)par1;
|
||||||
|
mc.mcProfiler.endStartSection("center");
|
||||||
|
|
||||||
|
//for (int j = 0; j < 2; ++j)
|
||||||
|
//{
|
||||||
|
/*if (mc.gameSettings.anaglyph)
|
||||||
|
{
|
||||||
|
anaglyphField = j;
|
||||||
|
|
||||||
|
if (anaglyphField == 0)
|
||||||
|
{
|
||||||
|
GL11.glColorMask(false, true, true, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL11.glColorMask(true, false, false, false);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
mc.mcProfiler.endStartSection("clear");
|
||||||
|
//GL11.glViewport(0, 0, mc.displayWidth, mc.displayHeight);
|
||||||
|
//self.updateFogColor(par1);
|
||||||
|
//GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
|
||||||
|
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||||
|
mc.mcProfiler.endStartSection("camera");
|
||||||
|
//self.setupCameraTransform(par1, j);
|
||||||
|
//ActiveRenderInfo.updateRenderInfo(mc.thePlayer, mc.gameSettings.thirdPersonView == 2);
|
||||||
|
mc.mcProfiler.endStartSection("frustrum");
|
||||||
|
ClippingHelperImpl.getInstance();
|
||||||
|
|
||||||
|
/*if (mc.gameSettings.renderDistance < 2)
|
||||||
|
{
|
||||||
|
self.setupFog(-1, par1);
|
||||||
|
mc.mcProfiler.endStartSection("sky");
|
||||||
|
renderglobal.renderSky(par1);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
//GL11.glEnable(GL11.GL_FOG);
|
||||||
|
//self.setupFog(1, par1);
|
||||||
|
|
||||||
|
if (mc.gameSettings.ambientOcclusion != 0)
|
||||||
|
{
|
||||||
|
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mc.mcProfiler.endStartSection("culling");
|
||||||
|
Frustrum frustrum = new Frustrum();
|
||||||
|
frustrum.setPosition(d0, d1, d2);
|
||||||
|
mc.renderGlobal.clipRenderersByFrustum(frustrum, par1);
|
||||||
|
|
||||||
|
|
||||||
|
//if (j == 0)
|
||||||
|
//{
|
||||||
|
mc.mcProfiler.endStartSection("updatechunks");
|
||||||
|
|
||||||
|
while (!mc.renderGlobal.updateRenderers(entitylivingbase, false) && par2 != 0L)
|
||||||
|
{
|
||||||
|
long k = par2 - System.nanoTime();
|
||||||
|
|
||||||
|
if (k < 0L || k > 1000000000L)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if (entitylivingbase.posY < 128.0D)
|
||||||
|
//{
|
||||||
|
// self.renderCloudsCheck(renderglobal, par1);
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
mc.mcProfiler.endStartSection("prepareterrain");
|
||||||
|
//self.setupFog(0, par1);
|
||||||
|
//GL11.glEnable(GL11.GL_FOG);
|
||||||
|
mc.getTextureManager().bindTexture(TextureMap.locationBlocksTexture);
|
||||||
|
RenderHelper.disableStandardItemLighting();
|
||||||
|
mc.mcProfiler.endStartSection("terrain");
|
||||||
|
renderglobal.sortAndRender(entitylivingbase, 0, (double)par1);
|
||||||
|
GL11.glShadeModel(GL11.GL_FLAT);
|
||||||
|
EntityPlayer entityplayer;
|
||||||
|
|
||||||
|
if (self.debugViewDirection == 0)
|
||||||
|
{
|
||||||
|
/* XXX TODO: enable entity rendering inside DW's. renderEntities uses statics that need to be reset afterwards.
|
||||||
|
RenderHelper.enableStandardItemLighting();
|
||||||
|
mc.mcProfiler.endStartSection("entities");
|
||||||
|
ForgeHooksClient.setRenderPass(0);
|
||||||
|
renderglobal.renderEntities(entitylivingbase.getPosition(par1), frustrum, par1);
|
||||||
|
ForgeHooksClient.setRenderPass(0);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Forge: Moved down
|
||||||
|
self.enableLightmap((double)par1);
|
||||||
|
mc.mcProfiler.endStartSection("litParticles");
|
||||||
|
effectrenderer.renderLitParticles(entitylivingbase, par1);
|
||||||
|
RenderHelper.disableStandardItemLighting();
|
||||||
|
self.setupFog(0, par1);
|
||||||
|
mc.mcProfiler.endStartSection("particles");
|
||||||
|
effectrenderer.renderParticles(entitylivingbase, par1);
|
||||||
|
self.disableLightmap((double)par1);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*if (mc.objectMouseOver != null && entitylivingbase.isInsideOfMaterial(Material.water) && entitylivingbase instanceof EntityPlayer && !mc.gameSettings.hideGUI)
|
||||||
|
{
|
||||||
|
entityplayer = (EntityPlayer)entitylivingbase;
|
||||||
|
GL11.glDisable(GL11.GL_ALPHA_TEST);
|
||||||
|
mc.mcProfiler.endStartSection("outline");
|
||||||
|
if (!ForgeHooksClient.onDrawBlockHighlight(renderglobal, entityplayer, mc.objectMouseOver, 0, entityplayer.inventory.getCurrentItem(), par1))
|
||||||
|
{
|
||||||
|
renderglobal.drawSelectionBox(entityplayer, mc.objectMouseOver, 0, par1);
|
||||||
|
}
|
||||||
|
GL11.glEnable(GL11.GL_ALPHA_TEST);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GL11.glDisable(GL11.GL_BLEND);
|
||||||
|
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||||
|
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
GL11.glDepthMask(true);
|
||||||
|
//self.setupFog(0, par1);
|
||||||
|
GL11.glEnable(GL11.GL_BLEND);
|
||||||
|
GL11.glDisable(GL11.GL_CULL_FACE);
|
||||||
|
mc.getTextureManager().bindTexture(TextureMap.locationBlocksTexture);
|
||||||
|
|
||||||
|
if (mc.gameSettings.fancyGraphics)
|
||||||
|
{
|
||||||
|
mc.mcProfiler.endStartSection("water");
|
||||||
|
|
||||||
|
if (mc.gameSettings.ambientOcclusion != 0)
|
||||||
|
{
|
||||||
|
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
GL11.glColorMask(false, false, false, false);
|
||||||
|
int l = renderglobal.sortAndRender(entitylivingbase, 1, (double)par1);
|
||||||
|
|
||||||
|
|
||||||
|
/*if (mc.gameSettings.anaglyph)
|
||||||
|
{
|
||||||
|
if (anaglyphField == 0)
|
||||||
|
{
|
||||||
|
GL11.glColorMask(false, true, true, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL11.glColorMask(true, false, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else*/
|
||||||
|
|
||||||
|
{
|
||||||
|
GL11.glColorMask(true, true, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l > 0)
|
||||||
|
{
|
||||||
|
renderglobal.renderAllRenderLists(1, (double)par1);
|
||||||
|
}
|
||||||
|
|
||||||
|
GL11.glShadeModel(GL11.GL_FLAT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mc.mcProfiler.endStartSection("water");
|
||||||
|
renderglobal.sortAndRender(entitylivingbase, 1, (double)par1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* XXX TODO: enable entity rendering inside DW's. renderEntities uses statics that need to be reset afterwards.
|
||||||
|
if (self.debugViewDirection == 0) //Only render if render pass 0 happens as well.
|
||||||
|
{
|
||||||
|
RenderHelper.enableStandardItemLighting();
|
||||||
|
mc.mcProfiler.endStartSection("entities");
|
||||||
|
ForgeHooksClient.setRenderPass(1);
|
||||||
|
renderglobal.renderEntities(entitylivingbase.getPosition(par1), frustrum, par1);
|
||||||
|
ForgeHooksClient.setRenderPass(-1);
|
||||||
|
RenderHelper.disableStandardItemLighting();
|
||||||
|
} */
|
||||||
|
|
||||||
|
GL11.glDepthMask(true);
|
||||||
|
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||||
|
GL11.glDisable(GL11.GL_BLEND);
|
||||||
|
|
||||||
|
RenderHelper.enableStandardItemLighting();
|
||||||
|
|
||||||
|
/*if (self.cameraZoom == 1.0D && entitylivingbase instanceof EntityPlayer && !mc.gameSettings.hideGUI && mc.objectMouseOver != null && !entitylivingbase.isInsideOfMaterial(Material.water))
|
||||||
|
{
|
||||||
|
entityplayer = (EntityPlayer)entitylivingbase;
|
||||||
|
GL11.glDisable(GL11.GL_ALPHA_TEST);
|
||||||
|
mc.mcProfiler.endStartSection("outline");
|
||||||
|
if (!ForgeHooksClient.onDrawBlockHighlight(renderglobal, entityplayer, mc.objectMouseOver, 0, entityplayer.inventory.getCurrentItem(), par1))
|
||||||
|
{
|
||||||
|
renderglobal.drawSelectionBox(entityplayer, mc.objectMouseOver, 0, par1);
|
||||||
|
}
|
||||||
|
GL11.glEnable(GL11.GL_ALPHA_TEST);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
//mc.mcProfiler.endStartSection("destroyProgress");
|
||||||
|
//GL11.glEnable(GL11.GL_BLEND);
|
||||||
|
//GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
|
||||||
|
//renderglobal.drawBlockDamageTexture(Tessellator.instance, entitylivingbase, par1);
|
||||||
|
//GL11.glDisable(GL11.GL_BLEND);
|
||||||
|
//mc.mcProfiler.endStartSection("weather");
|
||||||
|
//self.renderRainSnow(par1);
|
||||||
|
//GL11.glDisable(GL11.GL_FOG);
|
||||||
|
|
||||||
|
//if (entitylivingbase.posY >= 128.0D)
|
||||||
|
//{
|
||||||
|
// self.renderCloudsCheck(renderglobal, par1);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//Forge: Moved section from above, now particles are the last thing to render.
|
||||||
|
/*self.enableLightmap((double)par1);
|
||||||
|
mc.mcProfiler.endStartSection("litParticles");
|
||||||
|
effectrenderer.renderLitParticles(entitylivingbase, par1);
|
||||||
|
RenderHelper.disableStandardItemLighting();
|
||||||
|
//self.setupFog(0, par1);
|
||||||
|
mc.mcProfiler.endStartSection("particles");
|
||||||
|
effectrenderer.renderParticles(entitylivingbase, par1);
|
||||||
|
self.disableLightmap((double)par1);*/
|
||||||
|
//Forge: End Move
|
||||||
|
|
||||||
|
//mc.mcProfiler.endStartSection("FRenderLast");
|
||||||
|
//ForgeHooksClient.dispatchRenderLast(renderglobal, par1);
|
||||||
|
|
||||||
|
//mc.mcProfiler.endStartSection("hand");
|
||||||
|
|
||||||
|
//if (self.cameraZoom == 1.0D)
|
||||||
|
//{
|
||||||
|
// GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
|
||||||
|
// self.renderHand(par1, j);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if (!mc.gameSettings.anaglyph)
|
||||||
|
//{
|
||||||
|
mc.mcProfiler.endSection();
|
||||||
|
//return;
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
|
//GL11.glColorMask(true, true, true, false);
|
||||||
|
//mc.mcProfiler.endSection();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
231
src/main/java/mods/immibis/subworlds/dw/DWManager.java
Normal file
231
src/main/java/mods/immibis/subworlds/dw/DWManager.java
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
package mods.immibis.subworlds.dw;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import mods.immibis.core.api.APILocator;
|
||||||
|
import mods.immibis.core.api.net.IPacket;
|
||||||
|
import mods.immibis.core.api.net.IPacketMap;
|
||||||
|
import mods.immibis.core.api.util.NBTType;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.nbt.NBTTagList;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.world.IWorldAccess;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.WorldSavedData;
|
||||||
|
import net.minecraft.world.storage.MapStorage;
|
||||||
|
import net.minecraftforge.common.DimensionManager;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
import net.minecraftforge.event.world.WorldEvent;
|
||||||
|
import cpw.mods.fml.common.FMLCommonHandler;
|
||||||
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import cpw.mods.fml.common.network.FMLNetworkEvent;
|
||||||
|
|
||||||
|
public class DWManager {
|
||||||
|
|
||||||
|
// Note: DimensionManager isn't thread safe.
|
||||||
|
// We avoid calling it from the client thread when the integrated server is running.
|
||||||
|
|
||||||
|
public static final int PROVIDER_TYPE_ID = "SpaceCraftMod".hashCode();
|
||||||
|
|
||||||
|
public static final String CHANNEL = "SpaceCraftDW";
|
||||||
|
public static final byte PKT_DIMENSION_LIST = 0;
|
||||||
|
|
||||||
|
private static Map<Integer, WorldProps> registeredDimensions = new HashMap<Integer, WorldProps>();
|
||||||
|
|
||||||
|
private static SaveSpecificData getSaveData() {
|
||||||
|
MapStorage ms = DimensionManager.getWorld(0).mapStorage;
|
||||||
|
SaveSpecificData ssd = (SaveSpecificData)ms.loadData(SaveSpecificData.class, "subworlds-dw-save-data");
|
||||||
|
if(ssd == null)
|
||||||
|
ms.setData("subworlds-dw-save-data", ssd = new SaveSpecificData("subworlds-dw-save-data"));
|
||||||
|
return ssd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new empty dimension for Detached World use,
|
||||||
|
* returns the dimension ID.
|
||||||
|
* only called on the server
|
||||||
|
*/
|
||||||
|
public static int createWorld(WorldProps props) {
|
||||||
|
int dim = DimensionManager.getNextFreeDimId();
|
||||||
|
|
||||||
|
System.out.println("DWManager: creating dimension #"+dim);
|
||||||
|
|
||||||
|
registerDimensions(Collections.singletonMap(dim, props), false);
|
||||||
|
|
||||||
|
MinecraftServer.getServer().worldServerForDimension(dim);
|
||||||
|
System.out.println("DWManager: created dimension #"+dim);
|
||||||
|
return dim;
|
||||||
|
}
|
||||||
|
public static int createWorld() {
|
||||||
|
return createWorld(new WorldProps());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
DimensionManager.registerProviderType(PROVIDER_TYPE_ID, DWWorldProvider.class, false);
|
||||||
|
MinecraftForge.EVENT_BUS.register(new EventHandler());
|
||||||
|
FMLCommonHandler.instance().bus().register(new ConnectionHandler());
|
||||||
|
APILocator.getNetManager().listen(new PacketMap());
|
||||||
|
new ChunkLoadingCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class PacketMap implements IPacketMap {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return CHANNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPacket createS2CPacket(byte id) {
|
||||||
|
if(id == PKT_DIMENSION_LIST)
|
||||||
|
return new PacketDWDimensionList();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPacket createC2SPacket(byte id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ConnectionHandler {
|
||||||
|
@SubscribeEvent
|
||||||
|
public String connectionReceived(FMLNetworkEvent.ServerConnectionFromClientEvent evt) {
|
||||||
|
PacketDWDimensionList packet = new PacketDWDimensionList();
|
||||||
|
packet.clearExisting = true;
|
||||||
|
packet.data = registeredDimensions;
|
||||||
|
APILocator.getNetManager().send(packet, evt.manager, true);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// only called on the server, unless there is no server
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
static void registerDimensions(Map<Integer, WorldProps> dimIDs, boolean clearExisting) {
|
||||||
|
if(clearExisting) {
|
||||||
|
for(int i : registeredDimensions.keySet())
|
||||||
|
DimensionManager.unregisterDimension(i);
|
||||||
|
registeredDimensions.clear();
|
||||||
|
}
|
||||||
|
SaveSpecificData sd = MinecraftServer.getServer() == null ? null : getSaveData();
|
||||||
|
for(int i : dimIDs.keySet()) {
|
||||||
|
DimensionManager.registerDimension(i, PROVIDER_TYPE_ID);
|
||||||
|
registeredDimensions.put(i, dimIDs.get(i));
|
||||||
|
|
||||||
|
if(sd != null && !sd.dw_worlds.containsKey(i)) {
|
||||||
|
sd.dw_worlds.put(i, dimIDs.get(i));
|
||||||
|
sd.setDirty(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sd != null)
|
||||||
|
{
|
||||||
|
PacketDWDimensionList packet = new PacketDWDimensionList();
|
||||||
|
packet.clearExisting = clearExisting;
|
||||||
|
packet.data = dimIDs;
|
||||||
|
for(EntityPlayer pl : (List<EntityPlayer>)MinecraftServer.getServer().getConfigurationManager().playerEntityList) {
|
||||||
|
APILocator.getNetManager().sendToClient(packet, pl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// must be public or Forge crashes
|
||||||
|
public static class EventHandler {
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onWorldLoad(WorldEvent.Load evt) {
|
||||||
|
if(!evt.world.isRemote && evt.world.provider.dimensionId == 0) {
|
||||||
|
registerDimensions(getSaveData().dw_worlds, true);
|
||||||
|
}
|
||||||
|
if(!evt.world.isRemote)
|
||||||
|
evt.world.addWorldAccess(new WorldListener(evt.world));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onWorldUnload(WorldEvent.Unload evt) {
|
||||||
|
if(!evt.world.isRemote && evt.world.provider.dimensionId == 0) {
|
||||||
|
registerDimensions(Collections.<Integer, WorldProps>emptyMap(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// must be public as instances are created by reflection
|
||||||
|
public static class SaveSpecificData extends WorldSavedData {
|
||||||
|
public SaveSpecificData(String par1Str) {
|
||||||
|
super(par1Str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Integer, WorldProps> dw_worlds = new HashMap<Integer, WorldProps>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readFromNBT(NBTTagCompound var1) {
|
||||||
|
if(var1.hasKey("dw_worlds")) {
|
||||||
|
NBTTagList t = var1.getTagList("dw_worlds", NBTType.COMPOUND);
|
||||||
|
for(int k = 0; k < t.tagCount(); k++)
|
||||||
|
{
|
||||||
|
WorldProps props = new WorldProps();
|
||||||
|
NBTTagCompound tag = t.getCompoundTagAt(k);
|
||||||
|
int dim = tag.getInteger("dim");
|
||||||
|
props.read(tag);
|
||||||
|
dw_worlds.put(dim, props);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToNBT(NBTTagCompound var1) {
|
||||||
|
NBTTagList t = new NBTTagList();
|
||||||
|
for(Map.Entry<Integer, WorldProps> i : dw_worlds.entrySet()) {
|
||||||
|
NBTTagCompound c = new NBTTagCompound();
|
||||||
|
c.setInteger("dim", i.getKey());
|
||||||
|
i.getValue().write(c);
|
||||||
|
t.appendTag(c);
|
||||||
|
}
|
||||||
|
var1.setTag("dw_worlds", t);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class WorldListener implements IWorldAccess {
|
||||||
|
//public final World worldObj;
|
||||||
|
public WorldListener(World world) {
|
||||||
|
//this.worldObj = world;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEntityDestroy(Entity var1) {
|
||||||
|
if(var1 instanceof DWEntity)
|
||||||
|
((DWEntity)var1).onUnloadOrDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void markBlockForUpdate(int var1, int var2, int var3) {}
|
||||||
|
@Override public void markBlockForRenderUpdate(int var1, int var2, int var3) {}
|
||||||
|
@Override public void markBlockRangeForRenderUpdate(int var1, int var2, int var3, int var4, int var5, int var6) {}
|
||||||
|
@Override public void playSound(String var1, double var2, double var4, double var6, float var8, float var9) {}
|
||||||
|
@Override public void playSoundToNearExcept(EntityPlayer var1, String var2, double var3, double var5, double var7, float var9, float var10) {}
|
||||||
|
@Override public void spawnParticle(String var1, double var2, double var4, double var6, double var8, double var10, double var12) {}
|
||||||
|
@Override public void onEntityCreate(Entity var1) {}
|
||||||
|
@Override public void playRecord(String var1, int var2, int var3, int var4) {}
|
||||||
|
@Override public void broadcastSound(int var1, int var2, int var3, int var4, int var5) {}
|
||||||
|
@Override public void playAuxSFX(EntityPlayer var1, int var2, int var3, int var4, int var5, int var6) {}
|
||||||
|
@Override public void destroyBlockPartially(int var1, int var2, int var3, int var4, int var5) {}
|
||||||
|
@Override public void onStaticEntitiesChanged() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WorldProps getProps(int dim) {
|
||||||
|
WorldProps p = registeredDimensions.get(dim);
|
||||||
|
if(p == null)
|
||||||
|
return new WorldProps(); // probably on client. TODO verify correct
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
31
src/main/java/mods/immibis/subworlds/dw/DWTeleporter.java
Normal file
31
src/main/java/mods/immibis/subworlds/dw/DWTeleporter.java
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package mods.immibis.subworlds.dw;
|
||||||
|
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
|
import net.minecraft.world.Teleporter;
|
||||||
|
import net.minecraft.world.WorldServer;
|
||||||
|
|
||||||
|
public class DWTeleporter extends Teleporter {
|
||||||
|
|
||||||
|
public WorldServer world;
|
||||||
|
|
||||||
|
public DWTeleporter(WorldServer par1WorldServer) {
|
||||||
|
super(par1WorldServer);
|
||||||
|
world = par1WorldServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void placeInPortal(Entity par1Entity, double par2, double par4, double par6, float par8) {
|
||||||
|
DWWorldProvider provider = (DWWorldProvider)world.provider;
|
||||||
|
|
||||||
|
double x = provider.props.xsize/2;
|
||||||
|
double y = 5;
|
||||||
|
double z = provider.props.zsize/2;
|
||||||
|
|
||||||
|
if(par1Entity instanceof EntityLivingBase)
|
||||||
|
((EntityLivingBase)par1Entity).setPositionAndUpdate(x, y, z);
|
||||||
|
else
|
||||||
|
par1Entity.setPosition(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
22
src/main/java/mods/immibis/subworlds/dw/DWUtils.java
Normal file
22
src/main/java/mods/immibis/subworlds/dw/DWUtils.java
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
package mods.immibis.subworlds.dw;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityTracker;
|
||||||
|
import net.minecraft.entity.EntityTrackerEntry;
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
|
import net.minecraft.util.IntHashMap;
|
||||||
|
import net.minecraft.world.WorldServer;
|
||||||
|
import cpw.mods.fml.relauncher.ReflectionHelper;
|
||||||
|
|
||||||
|
public class DWUtils {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Set<EntityPlayerMP> getTrackingPlayers(Entity ent) {
|
||||||
|
EntityTracker t = ((WorldServer)ent.worldObj).getEntityTracker();
|
||||||
|
|
||||||
|
IntHashMap trackedEntityIDs = ReflectionHelper.getPrivateValue(EntityTracker.class, t, 3);
|
||||||
|
EntityTrackerEntry entry = (EntityTrackerEntry)trackedEntityIDs.lookup(ent.getEntityId());
|
||||||
|
return entry.trackingPlayers;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
package mods.immibis.subworlds.dw;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import net.minecraft.world.ChunkPosition;
|
||||||
|
import net.minecraft.world.WorldType;
|
||||||
|
import net.minecraft.world.biome.BiomeGenBase;
|
||||||
|
import net.minecraft.world.biome.WorldChunkManager;
|
||||||
|
import net.minecraft.world.gen.layer.GenLayer;
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
public class DWWorldChunkManager extends WorldChunkManager {
|
||||||
|
public final DWWorldProvider provider;
|
||||||
|
|
||||||
|
public DWWorldChunkManager(DWWorldProvider provider) {
|
||||||
|
this.provider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areBiomesViable(int par1, int par2, int par3, List par4List) {
|
||||||
|
return par4List.contains(DWChunkGenerator.BIOME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkPosition findBiomePosition(int par1, int par2, int par3, List par4List, Random par5Random) {
|
||||||
|
if(par4List.contains(DWChunkGenerator.BIOME))
|
||||||
|
return new ChunkPosition(provider.props.xsize/2, provider.props.ysize/2, provider.props.zsize/2);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BiomeGenBase[] getBiomeGenAt(BiomeGenBase[] ar, int par2, int par3, int par4, int par5, boolean par6) {
|
||||||
|
if (ar == null || ar.length < par4 * par5)
|
||||||
|
ar = new BiomeGenBase[par4 * par5];
|
||||||
|
|
||||||
|
Arrays.fill(ar, DWChunkGenerator.BIOME);
|
||||||
|
|
||||||
|
return ar;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BiomeGenBase getBiomeGenAt(int par1, int par2) {
|
||||||
|
return DWChunkGenerator.BIOME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BiomeGenBase[] getBiomesForGeneration(BiomeGenBase[] ar, int par2, int par3, int par4, int par5) {
|
||||||
|
if (ar == null || ar.length < par4 * par5)
|
||||||
|
ar = new BiomeGenBase[par4 * par5];
|
||||||
|
|
||||||
|
Arrays.fill(ar, DWChunkGenerator.BIOME);
|
||||||
|
|
||||||
|
return ar;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List getBiomesToSpawnIn() {
|
||||||
|
return Collections.singletonList(DWChunkGenerator.BIOME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GenLayer[] getModdedBiomeGenerators(WorldType worldType, long seed, GenLayer[] original) {
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float[] getRainfall(float[] ar, int par2, int par3, int par4, int par5) {
|
||||||
|
if(ar == null || ar.length < par4 * par5)
|
||||||
|
ar = new float[par4 * par5];
|
||||||
|
|
||||||
|
Arrays.fill(ar, DWChunkGenerator.BIOME.rainfall);
|
||||||
|
|
||||||
|
return ar;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getTemperatureAtHeight(float par1, int par2) {
|
||||||
|
return par1;
|
||||||
|
}
|
||||||
|
}
|
226
src/main/java/mods/immibis/subworlds/dw/DWWorldProvider.java
Normal file
226
src/main/java/mods/immibis/subworlds/dw/DWWorldProvider.java
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
package mods.immibis.subworlds.dw;
|
||||||
|
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
|
import net.minecraft.util.ChunkCoordinates;
|
||||||
|
import net.minecraft.util.Vec3;
|
||||||
|
import net.minecraft.world.WorldProvider;
|
||||||
|
import net.minecraft.world.WorldServer;
|
||||||
|
import net.minecraft.world.biome.BiomeGenBase;
|
||||||
|
import net.minecraft.world.chunk.Chunk;
|
||||||
|
import net.minecraft.world.chunk.IChunkProvider;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
public class DWWorldProvider extends WorldProvider {
|
||||||
|
|
||||||
|
public WorldProps props;
|
||||||
|
|
||||||
|
public static final boolean
|
||||||
|
LIGHTNING = false,
|
||||||
|
RAIN = false,
|
||||||
|
RESPAWN_HERE = false,
|
||||||
|
FOG = false,
|
||||||
|
FULLBRIGHT = true;
|
||||||
|
|
||||||
|
public DWTeleporter teleporter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDimension(int dim) {
|
||||||
|
props = DWManager.getProps(dim);
|
||||||
|
super.setDimension(dim);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public Vec3 getSkyColor(Entity cameraEntity, float partialTicks) {
|
||||||
|
return super.getSkyColor(cameraEntity, partialTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDimensionName() {
|
||||||
|
return "Detached World";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public float[] calcSunriseSunsetColors(float par1, float par2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canCoordinateBeSpawn(int par1, int par2) {
|
||||||
|
return par1 >= 0 && par1 < props.xsize && par2 >= 0 && par2 < props.zsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canDoLightning(Chunk chunk) {
|
||||||
|
return LIGHTNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canDoRainSnowIce(Chunk chunk) {
|
||||||
|
return RAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*@Override
|
||||||
|
public boolean canMineBlock(EntityPlayer player, int x, int y, int z) {
|
||||||
|
return x >= 0 && y >= 0 && z >= 0 && x < HSIZE && y < VSIZE && z < HSIZE && super.canMineBlock(player, x, y, z);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRespawnHere() {
|
||||||
|
return RESPAWN_HERE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IChunkProvider createChunkGenerator() {
|
||||||
|
try {
|
||||||
|
return props.generatorClass.getConstructor(WorldServer.class, DWWorldProvider.class).newInstance((WorldServer)worldObj, this);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
//new DWChunkGenerator((WorldServer)worldObj, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public boolean doesXZShowFog(int par1, int par2) {
|
||||||
|
return FOG;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void generateLightBrightnessTable() {
|
||||||
|
if(FULLBRIGHT) {
|
||||||
|
for(int k = 0; k < 16; k++)
|
||||||
|
lightBrightnessTable[k] = 1;
|
||||||
|
} else
|
||||||
|
super.generateLightBrightnessTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getActualHeight() {
|
||||||
|
return props.ysize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAverageGroundLevel() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BiomeGenBase getBiomeGenForCoords(int x, int z) {
|
||||||
|
return DWChunkGenerator.BIOME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public Vec3 getFogColor(float par1, float par2) {
|
||||||
|
//return worldObj.getWorldVec3Pool().getVecFromPool((int)(par1*255), 255, (int)(par2*255));
|
||||||
|
return super.getFogColor(par1, par2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight() {
|
||||||
|
return props.ysize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkCoordinates getRandomizedSpawnPoint() {
|
||||||
|
return new ChunkCoordinates(props.xsize/2, props.ysize/2, props.zsize/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRespawnDimension(EntityPlayerMP player) {
|
||||||
|
return RESPAWN_HERE ? dimensionId : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSaveFolder() {
|
||||||
|
return "CRAFT" + dimensionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getSeed() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkCoordinates getSpawnPoint() {
|
||||||
|
return getRandomizedSpawnPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public double getVoidFogYFactor() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getWelcomeMessage() {
|
||||||
|
return "Entering sub-world...";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDepartMessage() {
|
||||||
|
return "Leaving sub-world...";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public boolean getWorldHasVoidParticles() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDaytime() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSurfaceWorld() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void registerWorldChunkManager() {
|
||||||
|
worldChunkMgr = new DWWorldChunkManager(this);
|
||||||
|
if(!worldObj.isRemote)
|
||||||
|
teleporter = new DWTeleporter((WorldServer)worldObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAllowedSpawnTypes(boolean allowHostile, boolean allowPeaceful) {
|
||||||
|
super.setAllowedSpawnTypes(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateWeather() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canSnowAt(int x, int y, int z, boolean checkLight) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBlockFreeze(int x, int y, int z, boolean byWater) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canMineBlock(EntityPlayer player, int x, int y, int z) {
|
||||||
|
return super.canMineBlock(player, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float calculateCelestialAngle(long par1, float par3) {
|
||||||
|
return super.calculateCelestialAngle(par1, par3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void calculateInitialWeather() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package mods.immibis.subworlds.dw;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import mods.immibis.core.api.net.IPacket;
|
||||||
|
import mods.immibis.core.api.net.PacketUtils;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
|
||||||
|
public class PacketDWDimensionList implements IPacket {
|
||||||
|
|
||||||
|
public boolean clearExisting = false;
|
||||||
|
public Map<Integer, WorldProps> data = new HashMap<Integer, WorldProps>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getID() {
|
||||||
|
return DWManager.PKT_DIMENSION_LIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return DWManager.CHANNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(DataInputStream in) throws IOException {
|
||||||
|
clearExisting = in.readBoolean();
|
||||||
|
int len = in.readInt();
|
||||||
|
for(int k = 0; k < len; k++) {
|
||||||
|
int id = in.readInt();
|
||||||
|
WorldProps wp = new WorldProps();
|
||||||
|
wp.read(PacketUtils.readNBT(in));
|
||||||
|
data.put(id, wp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(DataOutputStream out) throws IOException {
|
||||||
|
out.writeBoolean(clearExisting);
|
||||||
|
out.writeInt(data.size());
|
||||||
|
for(Map.Entry<Integer, WorldProps> e : data.entrySet()) {
|
||||||
|
out.writeInt(e.getKey());
|
||||||
|
NBTTagCompound tag = new NBTTagCompound();
|
||||||
|
e.getValue().write(tag);
|
||||||
|
PacketUtils.writeNBT(tag, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceived(EntityPlayer source) {
|
||||||
|
if(source == null && MinecraftServer.getServer() == null) {
|
||||||
|
DWManager.registerDimensions(data, clearExisting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
32
src/main/java/mods/immibis/subworlds/dw/WorldProps.java
Normal file
32
src/main/java/mods/immibis/subworlds/dw/WorldProps.java
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package mods.immibis.subworlds.dw;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.world.chunk.IChunkProvider;
|
||||||
|
|
||||||
|
// POD structure with extra info about a DW world
|
||||||
|
public final class WorldProps {
|
||||||
|
public int xsize = 48;
|
||||||
|
public int ysize = 48;
|
||||||
|
public int zsize = 48;
|
||||||
|
|
||||||
|
// class must have constructor taking (WorldServer, DWWorldProvider)
|
||||||
|
public Class<? extends IChunkProvider> generatorClass = DWChunkGenerator.class;
|
||||||
|
|
||||||
|
public void read(NBTTagCompound tag) {
|
||||||
|
xsize = tag.getInteger("xsize");
|
||||||
|
ysize = tag.getInteger("ysize");
|
||||||
|
zsize = tag.getInteger("zsize");
|
||||||
|
try {
|
||||||
|
generatorClass = Class.forName(tag.getString("genclass")).asSubclass(IChunkProvider.class);
|
||||||
|
} catch(ClassNotFoundException e) {
|
||||||
|
generatorClass = DWChunkGenerator.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(NBTTagCompound tag) {
|
||||||
|
tag.setInteger("xsize", xsize);
|
||||||
|
tag.setInteger("ysize", ysize);
|
||||||
|
tag.setInteger("zsize", zsize);
|
||||||
|
tag.setString("genclass", generatorClass.getName());
|
||||||
|
}
|
||||||
|
}
|
79
src/main/java/mods/immibis/subworlds/mws/MWSClientWorld.java
Normal file
79
src/main/java/mods/immibis/subworlds/mws/MWSClientWorld.java
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
package mods.immibis.subworlds.mws;
|
||||||
|
|
||||||
|
|
||||||
|
import mods.immibis.subworlds.dw.DWWorldProvider;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.WorldClient;
|
||||||
|
import net.minecraft.client.network.NetHandlerPlayClient;
|
||||||
|
import net.minecraft.client.renderer.EntityRenderer;
|
||||||
|
import net.minecraft.client.renderer.RenderGlobal;
|
||||||
|
import net.minecraft.world.EnumDifficulty;
|
||||||
|
import net.minecraft.world.WorldSettings;
|
||||||
|
import cpw.mods.fml.relauncher.ReflectionHelper;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class MWSClientWorld extends WorldClient {
|
||||||
|
public int dimension;
|
||||||
|
|
||||||
|
//private Chunk blankChunk;
|
||||||
|
|
||||||
|
public boolean isDead = false;
|
||||||
|
|
||||||
|
public MWSClientWorld(int dimID) {
|
||||||
|
// need a valid NetClientHandler for construction so grab one from the real world
|
||||||
|
super((NetHandlerPlayClient)ReflectionHelper.getPrivateValue(WorldClient.class, Minecraft.getMinecraft().theWorld, 0),
|
||||||
|
new WorldSettings(Minecraft.getMinecraft().theWorld.getWorldInfo()),
|
||||||
|
dimID,
|
||||||
|
EnumDifficulty.PEACEFUL, // difficulty
|
||||||
|
Minecraft.getMinecraft().theWorld.theProfiler);
|
||||||
|
|
||||||
|
// but now we don't need it any more
|
||||||
|
ReflectionHelper.setPrivateValue(WorldClient.class, this, null, 0);
|
||||||
|
|
||||||
|
dimension = dimID;
|
||||||
|
|
||||||
|
isRemote = true;
|
||||||
|
|
||||||
|
Minecraft mc = Minecraft.getMinecraft();
|
||||||
|
|
||||||
|
render = new RenderGlobal(mc); /*{
|
||||||
|
@Override
|
||||||
|
public void renderAllRenderLists(int par1, double par2) {
|
||||||
|
super.renderAllRenderLists(par1, par2);
|
||||||
|
System.out.println(par1+" "+par2+" "+((java.util.List)ReflectionHelper.getPrivateValue(RenderGlobal.class, this, "glRenderLists")).size());
|
||||||
|
}
|
||||||
|
};*/
|
||||||
|
final EntityRenderer normalER = mc.entityRenderer;
|
||||||
|
erender = new EntityRenderer(mc, mc.getResourceManager()) {
|
||||||
|
|
||||||
|
// use the normal lightmap, not our separate one
|
||||||
|
@Override public void disableLightmap(double par1) {normalER.disableLightmap(par1);}
|
||||||
|
@Override public void enableLightmap(double par1) {normalER.enableLightmap(par1);}
|
||||||
|
};
|
||||||
|
|
||||||
|
render.setWorldAndLoadRenderers(this);
|
||||||
|
|
||||||
|
//blankChunk = getChunkFromChunkCoords(0, 0);
|
||||||
|
|
||||||
|
if(provider instanceof DWWorldProvider) {
|
||||||
|
DWWorldProvider pv = (DWWorldProvider)provider;
|
||||||
|
|
||||||
|
for(int x = -1; x <= pv.props.xsize; x++)
|
||||||
|
for(int z = -1; z <= pv.props.zsize; z++)
|
||||||
|
doPreChunk(x, z, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderGlobal render;
|
||||||
|
public EntityRenderer erender;
|
||||||
|
|
||||||
|
public void zeppelinTick() {
|
||||||
|
updateEntities();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unloadChunk(int x, int z) {
|
||||||
|
doPreChunk(x, z, false);
|
||||||
|
}
|
||||||
|
}
|
34
src/main/java/mods/immibis/subworlds/mws/MWSListener.java
Normal file
34
src/main/java/mods/immibis/subworlds/mws/MWSListener.java
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package mods.immibis.subworlds.mws;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.minecraft.network.NetworkManager;
|
||||||
|
import net.minecraft.world.ChunkCoordIntPair;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains a reference to a client, as well as a
|
||||||
|
* mechanism for determining which part of the world to send to this client.
|
||||||
|
*/
|
||||||
|
public abstract class MWSListener {
|
||||||
|
public final NetworkManager client;
|
||||||
|
|
||||||
|
public MWSListener(NetworkManager client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See update()
|
||||||
|
public int x, y, z;
|
||||||
|
public boolean isDead;
|
||||||
|
|
||||||
|
public int ticksToNextRangeCheck = 0;
|
||||||
|
public int RANGE_CHECK_INTERVAL = 20;
|
||||||
|
Set<ChunkCoordIntPair> loadedChunks = new HashSet<ChunkCoordIntPair>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this to update x, y and z with the centre of the area that will be sent to the client.
|
||||||
|
* Set isDead to true to remove the listener.
|
||||||
|
*/
|
||||||
|
public abstract void update();
|
||||||
|
}
|
204
src/main/java/mods/immibis/subworlds/mws/MWSManager.java
Normal file
204
src/main/java/mods/immibis/subworlds/mws/MWSManager.java
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
package mods.immibis.subworlds.mws;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
import mods.immibis.core.api.APILocator;
|
||||||
|
import mods.immibis.core.api.net.IPacket;
|
||||||
|
import mods.immibis.core.api.net.IPacketMap;
|
||||||
|
import mods.immibis.core.api.net.IPacketWrapper;
|
||||||
|
import mods.immibis.subworlds.mws.packets.*;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
import net.minecraftforge.event.world.WorldEvent;
|
||||||
|
import cpw.mods.fml.common.FMLCommonHandler;
|
||||||
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import cpw.mods.fml.common.gameevent.TickEvent;
|
||||||
|
import cpw.mods.fml.common.network.FMLNetworkEvent;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MWS is Multi-World Sync. It handles sending worlds to clients that the player isn't in.
|
||||||
|
*
|
||||||
|
* Each server world is associated with an MWSWorldManager, even if no clients are watching it.
|
||||||
|
*/
|
||||||
|
public class MWSManager {
|
||||||
|
|
||||||
|
public static void debug(String s) {
|
||||||
|
System.out.println("[SubWorlds MWS Debug] "+s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String CHANNEL = "ImmMWS";
|
||||||
|
|
||||||
|
private static WeakHashMap<World, MWSWorldManager> managers = new WeakHashMap<World, MWSWorldManager>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the MWSWorldManager that controls MWS for a given server world.
|
||||||
|
*/
|
||||||
|
public static MWSWorldManager getWorldManager(World world) {
|
||||||
|
if(world.isRemote)
|
||||||
|
throw new IllegalArgumentException("Argument must be a server world.");
|
||||||
|
|
||||||
|
MWSWorldManager m = managers.get(world);
|
||||||
|
if(m == null)
|
||||||
|
managers.put(world, m = new MWSWorldManager(world));
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
private static Map<Integer, MWSClientWorld> clientWorlds;
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
clientWorlds = new HashMap<Integer, MWSClientWorld>();
|
||||||
|
} catch(NoSuchFieldError e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the MWSClientWorld for a given dimension ID, or null if none exists.
|
||||||
|
*/
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public static MWSClientWorld getClientWorld(int dimID) {
|
||||||
|
return clientWorlds.get(dimID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public static void clientBegin(int dimID) {
|
||||||
|
debug("MWS client start: "+dimID);
|
||||||
|
clientWorlds.put(dimID, new MWSClientWorld(dimID));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public static void clientEnd(int dimID) {
|
||||||
|
debug("MWS client end: "+dimID);
|
||||||
|
MWSClientWorld w = clientWorlds.remove(dimID);
|
||||||
|
if(w != null) {
|
||||||
|
// is any cleanup necessary?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public static Entity findClientEntity(int entID) {
|
||||||
|
for(MWSClientWorld w : clientWorlds.values()) {
|
||||||
|
Entity e = w.getEntityByID(entID);
|
||||||
|
if(e != null)
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
MinecraftForge.EVENT_BUS.register(new ForgeEventListener());
|
||||||
|
APILocator.getNetManager().listen(new PacketMap());
|
||||||
|
FMLCommonHandler.instance().bus().register(new FMLEventListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
// must be public or Forge throws an exception
|
||||||
|
public static class ForgeEventListener {
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onWorldUnload(WorldEvent.Unload evt) {
|
||||||
|
if(!evt.world.isRemote) {
|
||||||
|
MWSWorldManager m = managers.get(evt.world);
|
||||||
|
if(m != null)
|
||||||
|
m.onWorldUnload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final byte PKT_BEGIN = 0;
|
||||||
|
public static final byte PKT_BLOCK = 1;
|
||||||
|
public static final byte PKT_CHUNK = 2;
|
||||||
|
public static final byte PKT_MULTIBLOCK = 3;
|
||||||
|
public static final byte PKT_TILE = 4;
|
||||||
|
public static final byte PKT_UNLOAD = 5;
|
||||||
|
public static final byte PKT_END = 6;
|
||||||
|
public static final byte PKT_SET_WORLD = 7;
|
||||||
|
|
||||||
|
private static class PacketMap implements IPacketMap {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return CHANNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPacket createS2CPacket(byte id) {
|
||||||
|
switch(id) {
|
||||||
|
case PKT_BEGIN: return new PacketMWSBegin();
|
||||||
|
case PKT_BLOCK: return new PacketMWSBlock();
|
||||||
|
case PKT_CHUNK: return new PacketMWSChunk();
|
||||||
|
case PKT_MULTIBLOCK: return new PacketMWSMultiBlock();
|
||||||
|
case PKT_TILE: return new PacketMWSTile();
|
||||||
|
case PKT_UNLOAD: return new PacketMWSUnload();
|
||||||
|
case PKT_END: return new PacketMWSEnd();
|
||||||
|
case PKT_SET_WORLD: return new PacketMWSSetWorld();
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPacket createC2SPacket(byte id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// must be public or forge crashes
|
||||||
|
public static class FMLEventListener {
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onServerTickEnd(TickEvent.ServerTickEvent evt) {
|
||||||
|
if(evt.phase != TickEvent.Phase.END) return;
|
||||||
|
for(MWSWorldManager m : managers.values())
|
||||||
|
m.tick();
|
||||||
|
}
|
||||||
|
@SubscribeEvent
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void onClientSideConnect(FMLNetworkEvent.ClientConnectedToServerEvent evt) {
|
||||||
|
evt.manager.channel().pipeline().addBefore("packet_handler", "immibis subworlds mws subworld packet delayer congratulations if you are reading this far", new ChannelInboundHandlerAdapter() {
|
||||||
|
boolean delayingMessages = false;
|
||||||
|
int delayingMessagesForWorld;
|
||||||
|
List<Object> delayedMessages = new ArrayList<>();
|
||||||
|
@Override
|
||||||
|
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||||
|
if(msg instanceof IPacketWrapper) {
|
||||||
|
IPacket wp = ((IPacketWrapper)msg).packet;
|
||||||
|
if(wp instanceof PacketMWSSetWorld) {
|
||||||
|
int dim = ((PacketMWSSetWorld)wp).dim;
|
||||||
|
if(delayingMessages && dim != delayingMessagesForWorld) {
|
||||||
|
delayingMessages = false;
|
||||||
|
delayedMessages.add(new IPacketWrapper(new PacketMWSSetWorld(PacketMWSSetWorld.NORMAL_DIM)));
|
||||||
|
for(Object obj : delayedMessages)
|
||||||
|
ctx.fireChannelRead(obj);
|
||||||
|
delayedMessages.clear();
|
||||||
|
}
|
||||||
|
if(dim != PacketMWSSetWorld.NORMAL_DIM) {
|
||||||
|
delayingMessages = true;
|
||||||
|
delayingMessagesForWorld = dim;
|
||||||
|
delayedMessages.add(msg);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(delayingMessages)
|
||||||
|
delayedMessages.add(msg);
|
||||||
|
else
|
||||||
|
ctx.fireChannelRead(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
457
src/main/java/mods/immibis/subworlds/mws/MWSWorldManager.java
Normal file
457
src/main/java/mods/immibis/subworlds/mws/MWSWorldManager.java
Normal file
|
@ -0,0 +1,457 @@
|
||||||
|
package mods.immibis.subworlds.mws;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import mods.immibis.core.api.APILocator;
|
||||||
|
import mods.immibis.subworlds.dw.DWWorldProvider;
|
||||||
|
import mods.immibis.subworlds.mws.packets.*;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.network.NetworkManager;
|
||||||
|
import net.minecraft.network.Packet;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.util.LongHashMap;
|
||||||
|
import net.minecraft.world.ChunkCoordIntPair;
|
||||||
|
import net.minecraft.world.IWorldAccess;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.chunk.Chunk;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds MWS state for one world.
|
||||||
|
*/
|
||||||
|
public class MWSWorldManager {
|
||||||
|
private final WeakReference<World> worldObj;
|
||||||
|
private final int dimensionID; // if world is unloaded, we need to know the dimension number to inform clients
|
||||||
|
|
||||||
|
private final int VIEW_DISTANCE = MinecraftServer.getServer().getConfigurationManager().getViewDistance();
|
||||||
|
|
||||||
|
MWSWorldManager(World world) {
|
||||||
|
this.worldObj = new WeakReference<World>(world);
|
||||||
|
this.dimensionID = world.provider.dimensionId;
|
||||||
|
world.addWorldAccess(new WorldListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Range {
|
||||||
|
// inclusive min, exclusive max
|
||||||
|
public final int minx, miny, minz, maxx, maxy, maxz;
|
||||||
|
public Range(int minx, int miny, int minz, int maxx, int maxy, int maxz) {
|
||||||
|
this.minx = minx;
|
||||||
|
this.miny = miny;
|
||||||
|
this.minz = minz;
|
||||||
|
this.maxx = maxx;
|
||||||
|
this.maxy = maxy;
|
||||||
|
this.maxz = maxz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBlockCount() {
|
||||||
|
return (maxx - minx) * (maxy - miny) * (maxz - minz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<MWSListener> listeners = new HashSet<MWSListener>();
|
||||||
|
|
||||||
|
private class SyncedChunk {
|
||||||
|
public final int x, z;
|
||||||
|
|
||||||
|
public SyncedChunk(int x, int z) {
|
||||||
|
this.x = x;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Range[] updateRanges = new Range[8];
|
||||||
|
private int nUpdateRanges;
|
||||||
|
private int nUpdatedBlocks;
|
||||||
|
|
||||||
|
//public Set<MWSListener> listeners = new HashSet<MWSListener>();
|
||||||
|
|
||||||
|
public void addRange(Range r) {
|
||||||
|
if(nUpdateRanges < updateRanges.length) {
|
||||||
|
updateRanges[nUpdateRanges] = r;
|
||||||
|
nUpdatedBlocks += r.getBlockCount();
|
||||||
|
}
|
||||||
|
nUpdateRanges++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Collection<Packet> nextUpdatePackets() {
|
||||||
|
if(nUpdateRanges == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
World world = worldObj.get();
|
||||||
|
if(world == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Collection<Packet> rv = null;
|
||||||
|
|
||||||
|
if(nUpdatedBlocks == 1) {
|
||||||
|
int x = updateRanges[0].minx + (this.x << 4);
|
||||||
|
int y = updateRanges[0].miny;
|
||||||
|
int z = updateRanges[0].minz + (this.z << 4);
|
||||||
|
|
||||||
|
updateRanges[0] = null;
|
||||||
|
|
||||||
|
Packet blockPacket = APILocator.getNetManager().wrap(new PacketMWSBlock(x, y, z, world), true);
|
||||||
|
|
||||||
|
TileEntity te = world.getTileEntity(x, y, z);
|
||||||
|
Packet tedesc = te == null ? null : te.getDescriptionPacket();
|
||||||
|
if(tedesc != null)
|
||||||
|
rv = Arrays.asList(APILocator.getNetManager().wrap(new PacketMWSTile(world, tedesc), true), blockPacket);
|
||||||
|
else
|
||||||
|
rv = Arrays.asList(blockPacket);
|
||||||
|
|
||||||
|
} else if(nUpdatedBlocks < 64 && nUpdateRanges <= updateRanges.length) {
|
||||||
|
PacketMWSMultiBlock mbp = new PacketMWSMultiBlock(this.x, this.z, nUpdatedBlocks, world);
|
||||||
|
rv = new ArrayList<Packet>(8);
|
||||||
|
rv.add(APILocator.getNetManager().wrap(mbp, true));
|
||||||
|
|
||||||
|
//Chunk c = world.getChunkFromChunkCoords(this.x, this.z);
|
||||||
|
|
||||||
|
for(int k = 0; k < nUpdateRanges; k++) {
|
||||||
|
Range r = updateRanges[k];
|
||||||
|
updateRanges[k] = null;
|
||||||
|
|
||||||
|
for(int x_ = r.minx; x_ < r.maxx; x_++)
|
||||||
|
for(int y = r.miny; y < r.maxy; y++)
|
||||||
|
for(int z_ = r.minz; z_ < r.maxz; z_++) {
|
||||||
|
int x = x_ + (this.x << 4);
|
||||||
|
int z = z_ + (this.z << 4);
|
||||||
|
|
||||||
|
mbp.addBlock(x, y, z, world);
|
||||||
|
|
||||||
|
TileEntity te = world.getTileEntity(x, y, z);
|
||||||
|
if(te != null) {
|
||||||
|
Packet teDesc = te.getDescriptionPacket();
|
||||||
|
if(teDesc != null)
|
||||||
|
rv.add(APILocator.getNetManager().wrap(new PacketMWSTile(world, teDesc), true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Chunk c = world.getChunkFromChunkCoords(this.x, this.z);
|
||||||
|
rv = new ArrayList<Packet>(16);
|
||||||
|
rv.add(APILocator.getNetManager().wrap(new PacketMWSChunk(this.x, this.z, world, c), true));
|
||||||
|
for(TileEntity te : (Collection<TileEntity>)c.chunkTileEntityMap.values()) {
|
||||||
|
Packet teDesc = te.getDescriptionPacket();
|
||||||
|
if(teDesc != null)
|
||||||
|
rv.add(APILocator.getNetManager().wrap(new PacketMWSTile(world, teDesc), true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nUpdateRanges = 0;
|
||||||
|
nUpdatedBlocks = 0;
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<SyncedChunk> changedChunks = new HashSet<SyncedChunk>();
|
||||||
|
private Set<SyncedChunk> allChunks = new HashSet<SyncedChunk>();
|
||||||
|
private LongHashMap chunks = new LongHashMap();
|
||||||
|
|
||||||
|
private SyncedChunk getSyncedChunk(int x, int z, boolean markForUpdate) {
|
||||||
|
long index = ChunkCoordIntPair.chunkXZ2Int(x, z);
|
||||||
|
SyncedChunk s = (SyncedChunk)chunks.getValueByKey(index);
|
||||||
|
if(s == null) {
|
||||||
|
s = new SyncedChunk(x, z);
|
||||||
|
chunks.add(index, s);
|
||||||
|
allChunks.add(s);
|
||||||
|
}
|
||||||
|
if(markForUpdate)
|
||||||
|
synchronized(changedChunks) {
|
||||||
|
changedChunks.add(s);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class WorldListener implements IWorldAccess {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void markBlockForUpdate(int var1, int var2, int var3) {
|
||||||
|
getSyncedChunk(var1 >> 4, var3 >> 4, true).addRange(new Range(var1&15, var2, var3&15, var1&15, var2, var3&15));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void markBlockForRenderUpdate(int var1, int var2, int var3) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void markBlockRangeForRenderUpdate(int var1, int var2, int var3,int var4, int var5, int var6) {
|
||||||
|
int mincx = var1 >> 4;
|
||||||
|
int mincz = var3 >> 4;
|
||||||
|
int maxcx = var4 >> 4;
|
||||||
|
int maxcz = var6 >> 4;
|
||||||
|
for(int cx = mincx; cx <= maxcx; cx++) {
|
||||||
|
int minx = (cx == mincx ? var1 & 15 : 0);
|
||||||
|
int maxx = (cx == maxcx ? (var4 & 15) + 1 : 16);
|
||||||
|
for(int cz = mincz; cz <= maxcz; cz++) {
|
||||||
|
int minz = (cz == mincz ? var3 & 15 : 0);
|
||||||
|
int maxz = (cz == maxcz ? (var6 & 15) + 1 : 16);
|
||||||
|
|
||||||
|
getSyncedChunk(cx, cz, true).addRange(new Range(minx, var2, minz, maxx, var5, maxz));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playSound(String var1, double var2, double var4, double var6, float var8, float var9) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void spawnParticle(String var1, double var2, double var4, double var6, double var8, double var10, double var12) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEntityCreate(Entity var1) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEntityDestroy(Entity var1) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playRecord(String var1, int var2, int var3, int var4) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playAuxSFX(EntityPlayer var1, int var2, int var3, int var4, int var5, int var6) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroyBlockPartially(int var1, int var2, int var3, int var4, int var5) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playSoundToNearExcept(EntityPlayer var1, String var2, double var3, double var5, double var7, float var9, float var10) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void broadcastSound(int var1, int var2, int var3, int var4, int var5) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStaticEntitiesChanged() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*private boolean isInViewingRange(SyncedChunk sc, MWSListener w) {
|
||||||
|
int minx = (sc.x - VIEW_DISTANCE) * 16;
|
||||||
|
int maxx = (sc.x + VIEW_DISTANCE + 1) * 16;
|
||||||
|
int minz = (sc.z - VIEW_DISTANCE) * 16;
|
||||||
|
int maxz = (sc.z + VIEW_DISTANCE + 1) * 16;
|
||||||
|
return w.x >= minx && w.z >= minz && w.x <= maxx && w.z <= maxz;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
private void sendUpdate(SyncedChunk sc) {
|
||||||
|
Collection<Packet> packets = sc.nextUpdatePackets();
|
||||||
|
if(packets == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int minx = (sc.x - VIEW_DISTANCE) * 16;
|
||||||
|
int maxx = (sc.x + VIEW_DISTANCE + 1) * 16;
|
||||||
|
int minz = (sc.z - VIEW_DISTANCE) * 16;
|
||||||
|
int maxz = (sc.z + VIEW_DISTANCE + 1) * 16;
|
||||||
|
|
||||||
|
for(MWSListener w : listeners) {
|
||||||
|
if(w.x >= minx && w.x <= maxx && w.z >= minz && w.z <= maxz) {
|
||||||
|
for(Packet p : packets) {
|
||||||
|
w.client.scheduleOutboundPacket(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick() {
|
||||||
|
for(MWSListener l : new ArrayList<MWSListener>(listeners)) {
|
||||||
|
l.update();
|
||||||
|
if(l.isDead)
|
||||||
|
listeners.remove(l);
|
||||||
|
|
||||||
|
if(l.ticksToNextRangeCheck <= 0) {
|
||||||
|
l.ticksToNextRangeCheck = l.RANGE_CHECK_INTERVAL;
|
||||||
|
updateLoadedChunks(l);
|
||||||
|
} else
|
||||||
|
l.ticksToNextRangeCheck--;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized(changedChunks) {
|
||||||
|
if(!changedChunks.isEmpty()) {
|
||||||
|
Collection<SyncedChunk> copy = new ArrayList<SyncedChunk>(changedChunks);
|
||||||
|
changedChunks.clear();
|
||||||
|
for(SyncedChunk sc : copy)
|
||||||
|
sendUpdate(sc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final int MAX_CHUNKS_PER_TICK = 5;
|
||||||
|
|
||||||
|
int nSent = 0;
|
||||||
|
|
||||||
|
while(sendQueue.size() > 0) {
|
||||||
|
SendQueueEntry e = sendQueue.poll();
|
||||||
|
if(!listeners.contains(e.l))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//if(SubWorldsMod.sendQueueThrottle(e.l.client))
|
||||||
|
// break;
|
||||||
|
|
||||||
|
//System.out.println("sending "+e.hashCode()+": "+e.cx+","+e.cz+" to "+e.l);
|
||||||
|
|
||||||
|
e.send();
|
||||||
|
nSent++;
|
||||||
|
if(nSent >= MAX_CHUNKS_PER_TICK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SendQueueEntry {
|
||||||
|
public MWSListener l;
|
||||||
|
public int cx, cz;
|
||||||
|
public World world;
|
||||||
|
public Chunk c;
|
||||||
|
|
||||||
|
public SendQueueEntry(MWSListener l, int cx, int cz, World world, Chunk c) {
|
||||||
|
this.c = c;
|
||||||
|
this.cx = cx;
|
||||||
|
this.cz = cz;
|
||||||
|
this.world = world;
|
||||||
|
this.l = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void send() {
|
||||||
|
APILocator.getNetManager().send(new PacketMWSChunk(cx, cz, world, c), l.client, true);
|
||||||
|
|
||||||
|
//APILocator.getNetManager().send(new PacketMWSSetWorld(world.provider.dimensionId), l.client, true);
|
||||||
|
for(TileEntity te : (Collection<TileEntity>)c.chunkTileEntityMap.values()) {
|
||||||
|
Packet teDesc = te.getDescriptionPacket();
|
||||||
|
if(teDesc != null)
|
||||||
|
l.client.scheduleOutboundPacket(APILocator.getNetManager().wrap(new PacketMWSTile(world, teDesc), true));
|
||||||
|
//l.client.scheduleOutboundPacket(teDesc);
|
||||||
|
}
|
||||||
|
//APILocator.getNetManager().send(new PacketMWSSetWorld(PacketMWSSetWorld.NORMAL_DIM), l.client, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Queue<SendQueueEntry> sendQueue = new LinkedList<SendQueueEntry>();
|
||||||
|
|
||||||
|
public void addListener(MWSListener l) {
|
||||||
|
World world = worldObj.get();
|
||||||
|
if(world == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
l.update();
|
||||||
|
|
||||||
|
if(l.isDead)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!listeners.add(l))
|
||||||
|
return;
|
||||||
|
|
||||||
|
int minx, minz, maxx, maxz;
|
||||||
|
|
||||||
|
if(world.provider instanceof DWWorldProvider) {
|
||||||
|
minx = minz = 0;
|
||||||
|
maxx = ((DWWorldProvider)world.provider).props.xsize >> 4;
|
||||||
|
maxz = ((DWWorldProvider)world.provider).props.zsize >> 4;
|
||||||
|
} else {
|
||||||
|
minx = (l.x>>4) - VIEW_DISTANCE;
|
||||||
|
maxx = (l.x>>4) + VIEW_DISTANCE + 1;
|
||||||
|
minz = (l.z>>4) - VIEW_DISTANCE;
|
||||||
|
maxz = (l.z>>4) + VIEW_DISTANCE + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
l.client.scheduleOutboundPacket(APILocator.getNetManager().wrap(new PacketMWSBegin(world.provider.dimensionId), true));
|
||||||
|
|
||||||
|
for(int x = minx; x <= maxx; x++)
|
||||||
|
for(int z = minz; z <= maxz; z++) {
|
||||||
|
sendQueue.add(new SendQueueEntry(l, x, z, world, world.getChunkFromChunkCoords(x, z)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateLoadedChunks(MWSListener l) {
|
||||||
|
int minx, minz, maxx, maxz;
|
||||||
|
|
||||||
|
World world = worldObj.get();
|
||||||
|
if(world == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(world.provider instanceof DWWorldProvider) {
|
||||||
|
minx = minz = 0;
|
||||||
|
maxx = ((DWWorldProvider)world.provider).props.xsize >> 4;
|
||||||
|
maxz = ((DWWorldProvider)world.provider).props.zsize >> 4;
|
||||||
|
} else {
|
||||||
|
minx = (l.x>>4) - VIEW_DISTANCE;
|
||||||
|
maxx = (l.x>>4) + VIEW_DISTANCE + 1;
|
||||||
|
minz = (l.z>>4) - VIEW_DISTANCE;
|
||||||
|
maxz = (l.z>>4) + VIEW_DISTANCE + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<ChunkCoordIntPair> targetChunks = new HashSet<ChunkCoordIntPair>();
|
||||||
|
|
||||||
|
for(int x = minx; x <= maxx; x++)
|
||||||
|
for(int z = minz; z <= maxz; z++) {
|
||||||
|
//System.out.println(l.x+" "+l.z+" "+x+" "+z);
|
||||||
|
targetChunks.add(new ChunkCoordIntPair(x, z));
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<ChunkCoordIntPair> toLoad = new HashSet<ChunkCoordIntPair>(targetChunks);
|
||||||
|
Set<ChunkCoordIntPair> toUnload = new HashSet<ChunkCoordIntPair>(l.loadedChunks);
|
||||||
|
toLoad.removeAll(l.loadedChunks);
|
||||||
|
toUnload.removeAll(targetChunks);
|
||||||
|
|
||||||
|
/*System.out.println("target: "+targetChunks);
|
||||||
|
System.out.println("loaded: "+l.loadedChunks);
|
||||||
|
System.out.println(" load: "+toLoad);
|
||||||
|
System.out.println("unload: "+toUnload);*/
|
||||||
|
|
||||||
|
for(ChunkCoordIntPair ccip : toLoad) {
|
||||||
|
l.loadedChunks.add(ccip);
|
||||||
|
//System.out.println("load "+ccip);
|
||||||
|
sendQueue.add(new SendQueueEntry(l, ccip.chunkXPos, ccip.chunkZPos, world, world.getChunkFromChunkCoords(ccip.chunkXPos, ccip.chunkZPos)));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(ChunkCoordIntPair ccip : toUnload) {
|
||||||
|
l.client.scheduleOutboundPacket(APILocator.getNetManager().wrap(new PacketMWSUnload(world, ccip.chunkXPos, ccip.chunkZPos), true));
|
||||||
|
//System.out.println("unload "+ccip);
|
||||||
|
l.loadedChunks.remove(ccip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeListener(NetworkManager client) {
|
||||||
|
for(MWSListener l : listeners) {
|
||||||
|
if(l.client == client) {
|
||||||
|
removeListener(l);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeListener(MWSListener l) {
|
||||||
|
l.isDead = true;
|
||||||
|
listeners.remove(l);
|
||||||
|
l.client.scheduleOutboundPacket(APILocator.getNetManager().wrap(new PacketMWSEnd(dimensionID), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
void onWorldUnload() {
|
||||||
|
Packet p = APILocator.getNetManager().wrap(new PacketMWSEnd(dimensionID), true);
|
||||||
|
for(MWSListener l : listeners) {
|
||||||
|
l.isDead = true;
|
||||||
|
l.client.scheduleOutboundPacket(p);
|
||||||
|
}
|
||||||
|
listeners.clear();
|
||||||
|
worldObj.clear();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package mods.immibis.subworlds.mws.packets;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import mods.immibis.core.api.net.IPacket;
|
||||||
|
import mods.immibis.subworlds.mws.MWSManager;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
public class PacketMWSBegin implements /*Runnable,*/ IPacket {
|
||||||
|
|
||||||
|
public int dim;
|
||||||
|
|
||||||
|
public PacketMWSBegin() {}
|
||||||
|
public PacketMWSBegin(int dim) {this.dim = dim;}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getID() {
|
||||||
|
return MWSManager.PKT_BEGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(DataOutputStream out) throws IOException {
|
||||||
|
out.writeInt(dim);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(DataInputStream in) throws IOException {
|
||||||
|
dim = in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void onReceived(EntityPlayer source) {
|
||||||
|
/*MainThreadTaskQueue.enqueue(this, Side.CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void run() {*/
|
||||||
|
MWSManager.clientBegin(dim);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return MWSManager.CHANNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package mods.immibis.subworlds.mws.packets;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import mods.immibis.core.MainThreadTaskQueue;
|
||||||
|
import mods.immibis.core.api.net.IPacket;
|
||||||
|
import mods.immibis.subworlds.mws.MWSManager;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
public class PacketMWSBlock implements IPacket, Runnable {
|
||||||
|
|
||||||
|
int x, y, z, type, meta, dim;
|
||||||
|
|
||||||
|
public PacketMWSBlock(int x, int y, int z, World w) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
this.dim = w.provider.dimensionId;
|
||||||
|
this.type = Block.getIdFromBlock(w.getBlock(x, y, z));
|
||||||
|
this.meta = w.getBlockMetadata(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketMWSBlock() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getID() {
|
||||||
|
return MWSManager.PKT_BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(DataOutputStream out) throws IOException {
|
||||||
|
out.writeInt(x);
|
||||||
|
out.writeInt(y);
|
||||||
|
out.writeInt(z);
|
||||||
|
out.writeShort((short)type);
|
||||||
|
out.writeByte((byte)meta);
|
||||||
|
out.writeInt(dim);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(DataInputStream in) throws IOException {
|
||||||
|
x = in.readInt();
|
||||||
|
y = in.readInt();
|
||||||
|
z = in.readInt();
|
||||||
|
type = in.readShort();
|
||||||
|
meta = in.readByte();
|
||||||
|
dim = in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return MWSManager.CHANNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void onReceived(EntityPlayer source) {
|
||||||
|
MainThreadTaskQueue.enqueue(this, Side.CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void run() {
|
||||||
|
World w = MWSManager.getClientWorld(dim);
|
||||||
|
if(w != null) {
|
||||||
|
w.setBlock(x, y, z, Block.getBlockById(type), meta, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,186 @@
|
||||||
|
package mods.immibis.subworlds.mws.packets;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.zip.Deflater;
|
||||||
|
import java.util.zip.DeflaterOutputStream;
|
||||||
|
import java.util.zip.InflaterInputStream;
|
||||||
|
|
||||||
|
import mods.immibis.core.api.net.IPacket;
|
||||||
|
import mods.immibis.subworlds.mws.MWSManager;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.client.multiplayer.WorldClient;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.world.EnumSkyBlock;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.chunk.Chunk;
|
||||||
|
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
public class PacketMWSChunk implements IPacket {
|
||||||
|
|
||||||
|
public int cx, cz, dim;
|
||||||
|
public short[] type;
|
||||||
|
public byte[] meta;
|
||||||
|
public byte[] light;
|
||||||
|
public short mask;
|
||||||
|
|
||||||
|
public PacketMWSChunk(int x, int z, World w, Chunk c) {
|
||||||
|
cx = x;
|
||||||
|
cz = z;
|
||||||
|
dim = w.provider.dimensionId;
|
||||||
|
|
||||||
|
fromChunk(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketMWSChunk() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getID() {
|
||||||
|
return MWSManager.PKT_CHUNK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fromChunk(Chunk c) {
|
||||||
|
type = new short[16*16*256];
|
||||||
|
meta = new byte[16*16*256];
|
||||||
|
light = new byte[16*16*256];
|
||||||
|
|
||||||
|
mask = 0;
|
||||||
|
for(int k = 0; k < 16; k++)
|
||||||
|
if(c.getBlockStorageArray()[k] != null)
|
||||||
|
mask |= (1 << k);
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
for(int y = 0; y < 256; y++)
|
||||||
|
for(int x = 0; x < 16; x++)
|
||||||
|
for(int z = 0; z < 16; z++, pos++) {
|
||||||
|
type[pos] = (short)Block.getIdFromBlock(c.getBlock(x, y, z));
|
||||||
|
meta[pos] = (byte)c.getBlockMetadata(x, y, z);
|
||||||
|
byte L = (byte)(c.getSavedLightValue(EnumSkyBlock.Block, x, y, z) & 15);
|
||||||
|
byte SL = (byte)(c.getSavedLightValue(EnumSkyBlock.Sky, x, y, z) & 15);
|
||||||
|
light[pos] = (byte)((SL << 4) | L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void toChunk(Chunk c) {
|
||||||
|
ExtendedBlockStorage[] ebs = c.getBlockStorageArray();
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
for(int y = 0; y < 256; y++) {
|
||||||
|
ExtendedBlockStorage segment = ebs[y >> 4];
|
||||||
|
if((mask & (1 << (y >> 4))) == 0) {
|
||||||
|
pos += 256;
|
||||||
|
ebs[y >> 4] = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(segment == null)
|
||||||
|
segment = ebs[y >> 4] = new ExtendedBlockStorage(y >> 4, true);
|
||||||
|
for(int x = 0; x < 16; x++)
|
||||||
|
for(int z = 0; z < 16; z++, pos++) {
|
||||||
|
int SL = (light[pos] >> 4) & 15;
|
||||||
|
int L = light[pos] & 15;
|
||||||
|
segment.setExtBlocklightValue(x, y&15, z, L);
|
||||||
|
segment.setExtSkylightValue(x, y&15, z, SL);
|
||||||
|
segment.func_150818_a(x, y&15, z, Block.getBlockById(type[pos]));
|
||||||
|
segment.setExtBlockMetadata(x, y&15, z, meta[pos]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int x = c.xPosition << 4;
|
||||||
|
int z = c.zPosition << 4;
|
||||||
|
|
||||||
|
for(int k = 0; k < 16; k++)
|
||||||
|
if((mask & (1 << k)) != 0)
|
||||||
|
c.worldObj.markBlockRangeForRenderUpdate(x, k << 4, z, x+15, (k<<4)+15, z+15);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ThreadLocal<byte[]> buffer128kb = new ThreadLocal<byte[]>() {
|
||||||
|
@Override
|
||||||
|
protected byte[] initialValue() {return new byte[131072];}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(DataOutputStream out) throws IOException {
|
||||||
|
out.writeInt(cx);
|
||||||
|
out.writeInt(cz);
|
||||||
|
out.writeInt(dim);
|
||||||
|
out.writeShort(mask);
|
||||||
|
DeflaterOutputStream o = new DeflaterOutputStream(out, new Deflater());
|
||||||
|
//OutputStream o = out;
|
||||||
|
byte[] buffer = buffer128kb.get();
|
||||||
|
int pos = 0;
|
||||||
|
for(short s : type) {
|
||||||
|
buffer[pos++] = (byte)(s >> 8);
|
||||||
|
buffer[pos++] = (byte)s;
|
||||||
|
}
|
||||||
|
o.write(buffer);
|
||||||
|
o.write(meta);
|
||||||
|
o.write(light);
|
||||||
|
o.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(DataInputStream in) throws IOException {
|
||||||
|
cx = in.readInt();
|
||||||
|
cz = in.readInt();
|
||||||
|
dim = in.readInt();
|
||||||
|
mask = in.readShort();
|
||||||
|
|
||||||
|
InflaterInputStream i = new InflaterInputStream(in);
|
||||||
|
//InputStream i = in;
|
||||||
|
type = new short[65536];
|
||||||
|
meta = new byte[65536];
|
||||||
|
light = new byte[65536];
|
||||||
|
byte[] buffer = buffer128kb.get();
|
||||||
|
int pos = 0;
|
||||||
|
readFully(i, buffer);
|
||||||
|
for(int k = 0; k < 65536; k++, pos += 2) {
|
||||||
|
int b1 = buffer[pos] & 255;
|
||||||
|
int b2 = buffer[pos+1] & 255;
|
||||||
|
//if(b1 == -1 || b2 == -1)
|
||||||
|
// throw new IOException("unexpected EOF");
|
||||||
|
type[k] = (short)((b1 << 8) | b2);
|
||||||
|
}
|
||||||
|
readFully(i, meta);
|
||||||
|
readFully(i, light);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readFully(InputStream i, byte[] b) throws IOException {
|
||||||
|
int pos = 0;
|
||||||
|
while(pos < b.length) {
|
||||||
|
int read = i.read(b, pos, b.length - pos);
|
||||||
|
if(read < 0)
|
||||||
|
throw new IOException("Unexpected end of stream (after "+pos+" bytes, need "+b.length+")");
|
||||||
|
pos += read;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return MWSManager.CHANNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void onReceived(EntityPlayer source) {
|
||||||
|
/*MainThreadTaskQueue.enqueue(this, Side.CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void run() {*/
|
||||||
|
WorldClient w = MWSManager.getClientWorld(dim);
|
||||||
|
if(w != null) {
|
||||||
|
w.doPreChunk(cx, cz, true);
|
||||||
|
Chunk c = w.getChunkFromChunkCoords(cx, cz);
|
||||||
|
toChunk(c);
|
||||||
|
System.out.println("Received chunk "+dim+"/"+cx+"/"+cz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package mods.immibis.subworlds.mws.packets;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import mods.immibis.core.MainThreadTaskQueue;
|
||||||
|
import mods.immibis.core.api.net.IPacket;
|
||||||
|
import mods.immibis.subworlds.mws.MWSManager;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
public class PacketMWSEnd implements IPacket, Runnable {
|
||||||
|
|
||||||
|
public int dim;
|
||||||
|
|
||||||
|
public PacketMWSEnd() {}
|
||||||
|
public PacketMWSEnd(int dim) {this.dim = dim;}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getID() {
|
||||||
|
return MWSManager.PKT_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(DataOutputStream out) throws IOException {
|
||||||
|
out.writeInt(dim);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(DataInputStream in) throws IOException {
|
||||||
|
dim = in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return MWSManager.CHANNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void onReceived(EntityPlayer source) {
|
||||||
|
MainThreadTaskQueue.enqueue(this, Side.CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void run() {
|
||||||
|
MWSManager.clientEnd(dim);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
package mods.immibis.subworlds.mws.packets;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import mods.immibis.core.MainThreadTaskQueue;
|
||||||
|
import mods.immibis.core.api.net.IPacket;
|
||||||
|
import mods.immibis.subworlds.mws.MWSManager;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
public class PacketMWSMultiBlock implements IPacket.Asynchronous, Runnable {
|
||||||
|
|
||||||
|
public PacketMWSMultiBlock() {}
|
||||||
|
|
||||||
|
public int size, pos, dim, cx, cz;
|
||||||
|
public byte[] meta;
|
||||||
|
public short[] type;
|
||||||
|
public byte[] x;
|
||||||
|
public int[] y;
|
||||||
|
public byte[] z;
|
||||||
|
|
||||||
|
public PacketMWSMultiBlock(int cx, int cz, int size, World w) {
|
||||||
|
this.size = size;
|
||||||
|
this.cx = cx;
|
||||||
|
this.cz = cz;
|
||||||
|
dim = w.provider.dimensionId;
|
||||||
|
pos = 0;
|
||||||
|
meta = new byte[size];
|
||||||
|
type = new short[size];
|
||||||
|
x = new byte[size];
|
||||||
|
y = new int[size];
|
||||||
|
z = new byte[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getID() {
|
||||||
|
return MWSManager.PKT_MULTIBLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(DataOutputStream out) throws IOException {
|
||||||
|
out.writeInt(pos);
|
||||||
|
out.writeInt(cx);
|
||||||
|
out.writeInt(cz);
|
||||||
|
out.writeInt(dim);
|
||||||
|
for(int k = 0; k < pos; k++) {
|
||||||
|
out.writeByte(x[k]);
|
||||||
|
out.writeInt(y[k]);
|
||||||
|
out.writeByte(z[k]);
|
||||||
|
out.writeByte(meta[k]);
|
||||||
|
out.writeShort(type[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(DataInputStream in) throws IOException {
|
||||||
|
size = pos = in.readInt();
|
||||||
|
cx = in.readInt();
|
||||||
|
cz = in.readInt();
|
||||||
|
dim = in.readInt();
|
||||||
|
for(int k = 0; k < size; k++) {
|
||||||
|
x[k] = in.readByte();
|
||||||
|
y[k] = in.readInt();
|
||||||
|
z[k] = in.readByte();
|
||||||
|
meta[k] = in.readByte();
|
||||||
|
type[k] = in.readShort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addBlock(int x2, int y2, int z2, World w) {
|
||||||
|
x[pos] = (byte)x2;
|
||||||
|
y[pos] = y2;
|
||||||
|
z[pos] = (byte)z2;
|
||||||
|
type[pos] = (short)Block.getIdFromBlock(w.getBlock(x2 + (cx << 4), y2, z2 + (cz << 4)));
|
||||||
|
meta[pos] = (byte)w.getBlockMetadata(x2 + (cx << 4), y2, z2 + (cz << 4));
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return MWSManager.CHANNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void onReceived(EntityPlayer source) {
|
||||||
|
MainThreadTaskQueue.enqueue(this, Side.CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void run() {
|
||||||
|
World w = MWSManager.getClientWorld(dim);
|
||||||
|
if(w != null) {
|
||||||
|
for(int k = 0; k < pos; k++) {
|
||||||
|
w.setBlock((cx<<4) + x[k], y[k], (cz<<4) + z[k], Block.getBlockById(type[k]), meta[k], 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package mods.immibis.subworlds.mws.packets;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.WorldClient;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
import mods.immibis.core.api.net.IPacket;
|
||||||
|
import mods.immibis.subworlds.mws.MWSManager;
|
||||||
|
|
||||||
|
public class PacketMWSSetWorld implements IPacket {
|
||||||
|
|
||||||
|
public static final int NORMAL_DIM = Integer.MIN_VALUE;
|
||||||
|
|
||||||
|
public int dim;
|
||||||
|
|
||||||
|
public PacketMWSSetWorld() {}
|
||||||
|
public PacketMWSSetWorld(int dim) {this.dim = dim;}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getID() {
|
||||||
|
return MWSManager.PKT_SET_WORLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(DataOutputStream out) throws IOException {
|
||||||
|
out.writeInt(dim);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(DataInputStream in) throws IOException {
|
||||||
|
dim = in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
private static WorldClient oldWorld;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void onReceived(EntityPlayer source) {
|
||||||
|
if(dim == NORMAL_DIM) {
|
||||||
|
if(oldWorld == null)
|
||||||
|
throw new AssertionError();
|
||||||
|
Minecraft.getMinecraft().theWorld = oldWorld;
|
||||||
|
oldWorld = null;
|
||||||
|
} else {
|
||||||
|
oldWorld = Minecraft.getMinecraft().theWorld;
|
||||||
|
WorldClient newWorld = MWSManager.getClientWorld(dim);
|
||||||
|
if(newWorld != null)
|
||||||
|
Minecraft.getMinecraft().theWorld = newWorld;
|
||||||
|
else
|
||||||
|
System.out.println("[WARNING] [SubWorlds MWS] Got set-world packet for unknown client world "+dim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return MWSManager.CHANNEL;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
package mods.immibis.subworlds.mws.packets;
|
||||||
|
|
||||||
|
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import mods.immibis.core.api.net.IPacket;
|
||||||
|
import mods.immibis.subworlds.mws.MWSManager;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.WorldClient;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.network.EnumConnectionState;
|
||||||
|
import net.minecraft.network.INetHandler;
|
||||||
|
import net.minecraft.network.Packet;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
public class PacketMWSTile implements IPacket {
|
||||||
|
|
||||||
|
public Packet teDesc;
|
||||||
|
public int dim;
|
||||||
|
public IOException exception;
|
||||||
|
|
||||||
|
public PacketMWSTile() {}
|
||||||
|
|
||||||
|
public PacketMWSTile(World w, Packet teDesc) {
|
||||||
|
this.teDesc = teDesc;
|
||||||
|
dim = w.provider.dimensionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getID() {
|
||||||
|
return MWSManager.PKT_TILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(DataOutputStream out) throws IOException {
|
||||||
|
if(exception != null)
|
||||||
|
throw new IOException("delayed wrapped encoding exception", exception);
|
||||||
|
|
||||||
|
Integer packetID = (Integer)EnumConnectionState.PLAY.func_150755_b().inverse().get(teDesc.getClass());
|
||||||
|
if(packetID == null) {
|
||||||
|
//System.out.println("can't send "+teDesc);
|
||||||
|
out.writeByte(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out.writeByte(packetID.intValue());
|
||||||
|
|
||||||
|
out.writeInt(dim);
|
||||||
|
|
||||||
|
if(packetID != null) {
|
||||||
|
PacketBuffer packetbuffer = new PacketBuffer(Unpooled.buffer());
|
||||||
|
teDesc.writePacketData(packetbuffer);
|
||||||
|
|
||||||
|
// TODO waste of memory/garbage
|
||||||
|
byte[] data = new byte[packetbuffer.readableBytes()];
|
||||||
|
packetbuffer.readBytes(data);
|
||||||
|
out.writeInt(data.length);
|
||||||
|
out.write(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(DataInputStream in) throws IOException {
|
||||||
|
int packetID = in.readByte() & 255;
|
||||||
|
dim = in.readInt();
|
||||||
|
|
||||||
|
if(packetID == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int len = in.readInt();
|
||||||
|
if(len > 2097152)
|
||||||
|
throw new IOException("input packet size > 2MB");
|
||||||
|
|
||||||
|
// TODO waste of memory/garbage (considering this is coming from a ByteArrayInputStream)
|
||||||
|
byte[] data = new byte[len];
|
||||||
|
in.readFully(data);
|
||||||
|
|
||||||
|
Packet packet;
|
||||||
|
try {
|
||||||
|
packet = ((Class<? extends Packet>)EnumConnectionState.PLAY.func_150755_b().get(packetID)).getConstructor().newInstance();
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
throw new IOException("failed to instantiate packet", e);
|
||||||
|
}
|
||||||
|
packet.readPacketData(new PacketBuffer(Unpooled.wrappedBuffer(data)));
|
||||||
|
this.teDesc = packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return MWSManager.CHANNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void onReceived(EntityPlayer source) {
|
||||||
|
if(teDesc == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
WorldClient w = MWSManager.getClientWorld(dim);
|
||||||
|
if(w != null) {
|
||||||
|
Minecraft mc = Minecraft.getMinecraft();
|
||||||
|
WorldClient oldWorld = mc.theWorld;
|
||||||
|
|
||||||
|
mc.theWorld = w;
|
||||||
|
|
||||||
|
try {
|
||||||
|
INetHandler handler = Minecraft.getMinecraft().getNetHandler();
|
||||||
|
System.out.println("Received tile packet "+teDesc);
|
||||||
|
teDesc.processPacket(handler);
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
mc.theWorld = oldWorld;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package mods.immibis.subworlds.mws.packets;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import mods.immibis.core.MainThreadTaskQueue;
|
||||||
|
import mods.immibis.core.api.net.IPacket;
|
||||||
|
import mods.immibis.subworlds.mws.MWSManager;
|
||||||
|
import net.minecraft.client.multiplayer.WorldClient;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
public class PacketMWSUnload implements IPacket, Runnable {
|
||||||
|
|
||||||
|
public int dim, x, z;
|
||||||
|
|
||||||
|
public PacketMWSUnload() {}
|
||||||
|
public PacketMWSUnload(World world, int x, int z) {this.dim = world.provider.dimensionId; this.x = x; this.z = z;}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getID() {
|
||||||
|
return MWSManager.PKT_UNLOAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(DataOutputStream out) throws IOException {
|
||||||
|
out.writeInt(dim);
|
||||||
|
out.writeInt(x);
|
||||||
|
out.writeInt(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(DataInputStream in) throws IOException {
|
||||||
|
dim = in.readInt();
|
||||||
|
x = in.readInt();
|
||||||
|
z = in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return MWSManager.CHANNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void onReceived(EntityPlayer source) {
|
||||||
|
MainThreadTaskQueue.enqueue(this, Side.CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void run() {
|
||||||
|
WorldClient w = MWSManager.getClientWorld(dim);
|
||||||
|
if(w != null)
|
||||||
|
w.doPreChunk(x, z, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
package mods.immibis.tinycarts;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.material.Material;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
|
import net.minecraft.util.AxisAlignedBB;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class BlockTransparentBedrock extends Block {
|
||||||
|
public BlockTransparentBedrock() {
|
||||||
|
super(Material.rock);
|
||||||
|
|
||||||
|
setBlockUnbreakable();
|
||||||
|
setResistance(6000000.0F);
|
||||||
|
setStepSound(soundTypeStone);
|
||||||
|
setBlockName("tinycarts.transparent_bedrock");
|
||||||
|
disableStats();
|
||||||
|
setBlockTextureName("bedrock");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getUseNeighborBrightness() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
|
||||||
|
final float border = 1/16f;
|
||||||
|
return AxisAlignedBB.getBoundingBox((double)par2 + border, (double)par3 + this.minY, (double)par4 + border, (double)par2 + 1-border, (double)par3 + 1-border, (double)par4 + 1-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) {
|
||||||
|
if(par5Entity instanceof EntityPlayerMP)
|
||||||
|
TinyCartsMod.removeFromCart(par5Entity, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// render in no passes = invisible
|
||||||
|
@Override
|
||||||
|
public boolean canRenderInPass(int pass) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean renderAsNormalBlock() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOpaqueCube() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void breakBlock(World par1World, int par2, int par3, int par4, Block par5, int par6) {
|
||||||
|
if(allowRemoval.get() > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
allowPlacement.incrementAndGet();
|
||||||
|
try {
|
||||||
|
par1World.setBlock(par2, par3, par4, par5);
|
||||||
|
} finally {
|
||||||
|
allowPlacement.decrementAndGet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBlockAdded(World par1World, int par2, int par3, int par4) {
|
||||||
|
if(allowPlacement.get() > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
allowRemoval.incrementAndGet();
|
||||||
|
try {
|
||||||
|
par1World.setBlockToAir(par2, par3, par4);
|
||||||
|
} finally {
|
||||||
|
allowRemoval.decrementAndGet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static AtomicInteger allowPlacement = new AtomicInteger();
|
||||||
|
static AtomicInteger allowRemoval = new AtomicInteger();
|
||||||
|
}
|
271
src/main/java/mods/immibis/tinycarts/CartExternalFakeEntity.java
Normal file
271
src/main/java/mods/immibis/tinycarts/CartExternalFakeEntity.java
Normal file
|
@ -0,0 +1,271 @@
|
||||||
|
package mods.immibis.tinycarts;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import mods.immibis.core.api.APILocator;
|
||||||
|
import mods.immibis.core.api.net.IPacket;
|
||||||
|
import mods.immibis.subworlds.ClientFakeEntities;
|
||||||
|
import mods.immibis.subworlds.FakeEntity;
|
||||||
|
import mods.immibis.subworlds.dw.DWEntityRenderer;
|
||||||
|
import mods.immibis.subworlds.dw.DWWorldProvider;
|
||||||
|
import mods.immibis.subworlds.mws.MWSClientWorld;
|
||||||
|
import mods.immibis.subworlds.mws.MWSManager;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.OpenGlHelper;
|
||||||
|
import net.minecraft.client.renderer.RenderHelper;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.network.Packet;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
public class CartExternalFakeEntity extends FakeEntity {
|
||||||
|
public final int dimID;
|
||||||
|
|
||||||
|
// rotation is applied first when rendering, then translation.
|
||||||
|
// x/y/z is the coordinates of the centre of the player's world in the FE world (not vice versa)
|
||||||
|
public double x, y, z, yaw;
|
||||||
|
//public Quaternion rotation = new Quaternion();
|
||||||
|
|
||||||
|
private double prevX, prevY, prevZ, prevYaw;
|
||||||
|
//private Quaternion prevRotation = rotation.clone();
|
||||||
|
|
||||||
|
public CartExternalFakeEntity(boolean isClient, int dimID) {
|
||||||
|
super(isClient);
|
||||||
|
this.dimID = dimID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CartExternalFakeEntity(boolean isClient, int entID, int dimID) {
|
||||||
|
super(isClient, entID);
|
||||||
|
this.dimID = dimID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Packet getUpdatePacket() {
|
||||||
|
final double MOVE_THRESHOLD = 0.2;
|
||||||
|
if(prevYaw == yaw && Math.abs(x - prevX) < MOVE_THRESHOLD && Math.abs(y - prevY) < MOVE_THRESHOLD && Math.abs(z - prevZ) < MOVE_THRESHOLD) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
prevYaw = yaw;
|
||||||
|
prevX = x;
|
||||||
|
prevY = y;
|
||||||
|
prevZ = z;
|
||||||
|
|
||||||
|
return APILocator.getNetManager().wrap(new UpdatePacket(this), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Packet getDescriptionPacket() {
|
||||||
|
return APILocator.getNetManager().wrap(new CreatePacket(this), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Packet getDestructionPacket() {
|
||||||
|
return APILocator.getNetManager().wrap(new DeletePacket(entityID), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean updated = false;
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
|
||||||
|
if(isClient) {
|
||||||
|
if(updated)
|
||||||
|
updated = false;
|
||||||
|
else {
|
||||||
|
prevX = x;
|
||||||
|
prevY = y;
|
||||||
|
prevZ = z;
|
||||||
|
prevYaw = yaw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public void render(double pl_x, double pl_y, double pl_z, float partialTick) {
|
||||||
|
MWSClientWorld subWorld = MWSManager.getClientWorld(dimID);
|
||||||
|
World plWorld = Minecraft.getMinecraft().theWorld;
|
||||||
|
if(subWorld == null || !(plWorld.provider instanceof DWWorldProvider)) {
|
||||||
|
super.render(pl_x, pl_y, pl_z, partialTick);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GL11.glPushMatrix();
|
||||||
|
GL11.glTranslated(-pl_x, -pl_y, -pl_z);
|
||||||
|
// now 0,0,0 = origin of the world the player is in
|
||||||
|
|
||||||
|
DWWorldProvider pv = (DWWorldProvider)plWorld.provider;
|
||||||
|
GL11.glTranslated(pv.props.xsize/2, 0, pv.props.zsize/2);
|
||||||
|
// now 0,0,0 = centre-bottom of world the player is in
|
||||||
|
|
||||||
|
double cx = prevX + (x - prevX) * partialTick;
|
||||||
|
double cy = prevY + (y - prevY) * partialTick;
|
||||||
|
double cz = prevZ + (z - prevZ) * partialTick;
|
||||||
|
|
||||||
|
// why not just cx,cy,cz?
|
||||||
|
GL11.glTranslated(cx-x, cy-y, cz-z);
|
||||||
|
|
||||||
|
GL11.glScalef(EntityMinecartAwesome.SCALE, EntityMinecartAwesome.SCALE, EntityMinecartAwesome.SCALE);
|
||||||
|
GL11.glRotatef((float)yaw, 0, 1, 0);
|
||||||
|
|
||||||
|
DWEntityRenderer.renderClientWorld(subWorld, partialTick, 0, 0, 0, x, y, z);
|
||||||
|
GL11.glPopMatrix();
|
||||||
|
|
||||||
|
OpenGlHelper.setActiveTexture(OpenGlHelper.lightmapTexUnit);
|
||||||
|
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||||
|
OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
|
||||||
|
RenderHelper.disableStandardItemLighting();
|
||||||
|
GL11.glColor3f(1, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DeletePacket implements IPacket {
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return NetworkHandler.CHANNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getID() {
|
||||||
|
return NetworkHandler.PKT_CEFE_DELETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int entID;
|
||||||
|
|
||||||
|
public DeletePacket() {}
|
||||||
|
public DeletePacket(int id) {entID = id;}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceived(EntityPlayer source) {
|
||||||
|
ClientFakeEntities.remove(entID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(DataInputStream in) throws IOException {
|
||||||
|
entID = in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(DataOutputStream out) throws IOException {
|
||||||
|
out.writeInt(entID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CreatePacket implements IPacket {
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return NetworkHandler.CHANNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getID() {
|
||||||
|
return NetworkHandler.PKT_CEFE_CREATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int entID, dimID;
|
||||||
|
public double x, y, z, r;
|
||||||
|
|
||||||
|
public CreatePacket() {}
|
||||||
|
public CreatePacket(CartExternalFakeEntity ent) {
|
||||||
|
entID = ent.entityID;
|
||||||
|
dimID = ent.dimID;
|
||||||
|
x = ent.x;
|
||||||
|
y = ent.y;
|
||||||
|
z = ent.z;
|
||||||
|
r = ent.yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceived(EntityPlayer source) {
|
||||||
|
CartExternalFakeEntity e = new CartExternalFakeEntity(true, entID, dimID);
|
||||||
|
e.x = x;
|
||||||
|
e.y = y;
|
||||||
|
e.z = z;
|
||||||
|
e.yaw = r;
|
||||||
|
ClientFakeEntities.add(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(DataInputStream in) throws IOException {
|
||||||
|
entID = in.readInt();
|
||||||
|
x = in.readDouble();
|
||||||
|
y = in.readDouble();
|
||||||
|
z = in.readDouble();
|
||||||
|
r = in.readDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(DataOutputStream out) throws IOException {
|
||||||
|
out.writeInt(entID);
|
||||||
|
out.writeDouble(x);
|
||||||
|
out.writeDouble(y);
|
||||||
|
out.writeDouble(z);
|
||||||
|
out.writeDouble(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class UpdatePacket implements IPacket {
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return NetworkHandler.CHANNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getID() {
|
||||||
|
return NetworkHandler.PKT_CEFE_UPDATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int entID;
|
||||||
|
public double x, y, z;
|
||||||
|
public float rot;
|
||||||
|
|
||||||
|
public UpdatePacket() {}
|
||||||
|
public UpdatePacket(CartExternalFakeEntity ent) {
|
||||||
|
entID = ent.entityID;
|
||||||
|
x = ent.x;
|
||||||
|
y = ent.y;
|
||||||
|
z = ent.z;
|
||||||
|
rot = (float)ent.yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceived(EntityPlayer source) {
|
||||||
|
CartExternalFakeEntity ent = (CartExternalFakeEntity)ClientFakeEntities.get(entID);
|
||||||
|
|
||||||
|
ent.prevX = x;
|
||||||
|
ent.prevY = y;
|
||||||
|
ent.prevZ = z;
|
||||||
|
|
||||||
|
ent.updated = true;
|
||||||
|
|
||||||
|
ent.x = x;
|
||||||
|
ent.y = y;
|
||||||
|
ent.z = z;
|
||||||
|
ent.yaw = rot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(DataInputStream in) throws IOException {
|
||||||
|
entID = in.readInt();
|
||||||
|
x = in.readDouble();
|
||||||
|
y = in.readDouble();
|
||||||
|
z = in.readDouble();
|
||||||
|
rot = in.readFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(DataOutputStream out) throws IOException {
|
||||||
|
out.writeInt(entID);
|
||||||
|
out.writeDouble(x);
|
||||||
|
out.writeDouble(y);
|
||||||
|
out.writeDouble(z);
|
||||||
|
out.writeFloat(rot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
src/main/java/mods/immibis/tinycarts/CommandExitCart.java
Normal file
31
src/main/java/mods/immibis/tinycarts/CommandExitCart.java
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package mods.immibis.tinycarts;
|
||||||
|
|
||||||
|
import net.minecraft.command.CommandBase;
|
||||||
|
import net.minecraft.command.ICommandSender;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.util.ChatComponentText;
|
||||||
|
|
||||||
|
public class CommandExitCart extends CommandBase {
|
||||||
|
@Override
|
||||||
|
public boolean canCommandSenderUseCommand(ICommandSender par1iCommandSender) {
|
||||||
|
return par1iCommandSender instanceof EntityPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCommandName() {
|
||||||
|
return "exitcart";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCommandUsage(ICommandSender icommandsender) {
|
||||||
|
return "/exitcart";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processCommand(ICommandSender icommandsender, String[] astring) {
|
||||||
|
if(icommandsender instanceof EntityPlayer)
|
||||||
|
TinyCartsMod.removeFromCart((EntityPlayer)icommandsender, true);
|
||||||
|
else
|
||||||
|
icommandsender.addChatMessage(new ChatComponentText("That command is only applicable to players."));
|
||||||
|
}
|
||||||
|
}
|
340
src/main/java/mods/immibis/tinycarts/EntityMinecartAwesome.java
Normal file
340
src/main/java/mods/immibis/tinycarts/EntityMinecartAwesome.java
Normal file
|
@ -0,0 +1,340 @@
|
||||||
|
package mods.immibis.tinycarts;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import mods.immibis.subworlds.FakeEntity;
|
||||||
|
import mods.immibis.subworlds.SubWorldsMod;
|
||||||
|
import mods.immibis.subworlds.dw.DWEntity;
|
||||||
|
import mods.immibis.subworlds.dw.DWManager;
|
||||||
|
import mods.immibis.subworlds.dw.DWWorldProvider;
|
||||||
|
import mods.immibis.subworlds.dw.WorldProps;
|
||||||
|
import net.minecraft.entity.item.EntityMinecart;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.management.ServerConfigurationManager;
|
||||||
|
import net.minecraft.util.Vec3;
|
||||||
|
import net.minecraft.world.ChunkCoordIntPair;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.WorldServer;
|
||||||
|
import net.minecraftforge.common.ForgeChunkManager;
|
||||||
|
import net.minecraftforge.common.ForgeChunkManager.Ticket;
|
||||||
|
import net.minecraftforge.common.ForgeChunkManager.Type;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
import net.minecraftforge.event.entity.minecart.MinecartInteractEvent;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
public class EntityMinecartAwesome extends EntityMinecart {
|
||||||
|
|
||||||
|
public static final int XSIZE = 16;
|
||||||
|
public static final int ZSIZE = 10;
|
||||||
|
public static final int YSIZE = 10;
|
||||||
|
|
||||||
|
public static final int SCALE = 10; // render scale; internal blocks per external block
|
||||||
|
|
||||||
|
public EntityMinecartAwesome(World par1World) {
|
||||||
|
super(par1World);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityMinecartAwesome(World w, double x, double y, double z) {
|
||||||
|
super(w, x, y, z);
|
||||||
|
if(w.isRemote)
|
||||||
|
throw new IllegalStateException();
|
||||||
|
|
||||||
|
WorldProps props = new WorldProps();
|
||||||
|
props.xsize = XSIZE;
|
||||||
|
props.ysize = YSIZE;
|
||||||
|
props.zsize = ZSIZE;
|
||||||
|
props.generatorClass = InteriorChunkGen.class;
|
||||||
|
internalWorldID = DWManager.createWorld(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getMountedYOffset() {
|
||||||
|
return 0.3f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int internalWorldID;
|
||||||
|
@Override
|
||||||
|
protected void readEntityFromNBT(NBTTagCompound par1nbtTagCompound) {
|
||||||
|
super.readEntityFromNBT(par1nbtTagCompound);
|
||||||
|
internalWorldID = par1nbtTagCompound.getInteger("intwid");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void writeEntityToNBT(NBTTagCompound par1nbtTagCompound) {
|
||||||
|
super.writeEntityToNBT(par1nbtTagCompound);
|
||||||
|
par1nbtTagCompound.setInteger("intwid", internalWorldID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DWSubEntity getDW() {
|
||||||
|
if(riddenByEntity instanceof DWSubEntity)
|
||||||
|
return (DWSubEntity)riddenByEntity;
|
||||||
|
else if(worldObj.isRemote)
|
||||||
|
return null;
|
||||||
|
else {
|
||||||
|
DWSubEntity dwsub = new DWSubEntity(worldObj);
|
||||||
|
dwsub.posX = posX;
|
||||||
|
dwsub.posY = posY;
|
||||||
|
dwsub.posZ = posZ;
|
||||||
|
worldObj.spawnEntityInWorld(dwsub);
|
||||||
|
dwsub.mountEntity(this);
|
||||||
|
return dwsub;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpdate() {
|
||||||
|
super.onUpdate();
|
||||||
|
|
||||||
|
getDW();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean interactFirst(EntityPlayer par1EntityPlayer)
|
||||||
|
{
|
||||||
|
if(MinecraftForge.EVENT_BUS.post(new MinecartInteractEvent(this, par1EntityPlayer)))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(!(par1EntityPlayer instanceof EntityPlayerMP))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(worldObj.isRemote)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ServerConfigurationManager scm = MinecraftServer.getServer().getConfigurationManager();
|
||||||
|
scm.transferPlayerToDimension((EntityPlayerMP)par1EntityPlayer, internalWorldID, ((DWWorldProvider)getDW().getInternalWorld().provider).teleporter);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinecartType() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX the whole purpose of this field is hacky. subworlds should keep track of this for us.
|
||||||
|
static Map<Integer, WeakReference<DWSubEntity>> entitiesByInternalID = new HashMap<Integer, WeakReference<DWSubEntity>>();
|
||||||
|
|
||||||
|
public static class DWSubEntity extends DWEntity {
|
||||||
|
public DWSubEntity(World w) {
|
||||||
|
super(w);
|
||||||
|
setSize(Math.min(XSIZE, ZSIZE)/(float)SCALE, YSIZE/(float)SCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityMinecartAwesome getCart() {
|
||||||
|
if(ridingEntity instanceof EntityMinecartAwesome)
|
||||||
|
return (EntityMinecartAwesome)ridingEntity;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int internalWorldID = Integer.MIN_VALUE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUnloadOrDestroy() {
|
||||||
|
if(!worldObj.isRemote) {
|
||||||
|
synchronized(entitiesByInternalID) {
|
||||||
|
int intWID = internalWorldID;
|
||||||
|
if(intWID != Integer.MIN_VALUE) {
|
||||||
|
WeakReference<DWSubEntity> ent = entitiesByInternalID.get(intWID);
|
||||||
|
if(ent != null && ent.get() == this) {
|
||||||
|
entitiesByInternalID.remove(intWID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mountEntity(null);
|
||||||
|
super.onUnloadOrDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Ticket externalTicket, internalTicket;
|
||||||
|
|
||||||
|
private static final int EXTERNAL_VIEW_DISTANCE = 7;
|
||||||
|
|
||||||
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
|
private void updateChunkLoading() {
|
||||||
|
boolean load = requiresInteriorLoaded();
|
||||||
|
if(load != (externalTicket != null)) {
|
||||||
|
if(DEBUG) System.out.println("[TinyCarts DEBUG] External loading: now "+load);
|
||||||
|
if(load) {
|
||||||
|
WorldServer world = (WorldServer)worldObj;
|
||||||
|
|
||||||
|
externalTicket = ForgeChunkManager.requestTicket(SubWorldsMod.INSTANCE, world, Type.NORMAL);
|
||||||
|
|
||||||
|
int baseX = (int)(posX) >> 4;
|
||||||
|
int baseZ = (int)(posZ) >> 4;
|
||||||
|
|
||||||
|
for(int dx = -EXTERNAL_VIEW_DISTANCE; dx <= EXTERNAL_VIEW_DISTANCE; dx++)
|
||||||
|
for(int dz = -EXTERNAL_VIEW_DISTANCE; dz <= EXTERNAL_VIEW_DISTANCE; dz++) {
|
||||||
|
int x = dx + baseX, z = dz + baseZ;
|
||||||
|
ForgeChunkManager.forceChunk(externalTicket, new ChunkCoordIntPair(x, z));
|
||||||
|
world.theChunkProviderServer.loadChunk(x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ForgeChunkManager.releaseTicket(externalTicket);
|
||||||
|
externalTicket = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(load != (internalTicket != null)) {
|
||||||
|
if(load) {
|
||||||
|
WorldServer world = getInternalWorld();
|
||||||
|
if(world == null)
|
||||||
|
throw new IllegalStateException("Failed to load internal world.");
|
||||||
|
|
||||||
|
internalTicket = ForgeChunkManager.requestTicket(SubWorldsMod.INSTANCE, world, Type.NORMAL);
|
||||||
|
|
||||||
|
int size = (Math.max(XSIZE, YSIZE)+15)/16;
|
||||||
|
|
||||||
|
if(DEBUG) System.out.println("[TinyCarts DEBUG] Internal loading: now true ("+size+"x"+size+")");
|
||||||
|
for(int x = 0; x < size; x++)
|
||||||
|
for(int z = 0; z < size; z++) {
|
||||||
|
ForgeChunkManager.forceChunk(internalTicket, new ChunkCoordIntPair(x, z));
|
||||||
|
world.theChunkProviderServer.loadChunk(x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if(DEBUG) System.out.println("[TinyCarts DEBUG] Internal loading: now false");
|
||||||
|
ForgeChunkManager.releaseTicket(internalTicket);
|
||||||
|
internalTicket = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isDead) { // should always be true
|
||||||
|
int intWID = internalWorldID = getCart().internalWorldID;
|
||||||
|
synchronized(entitiesByInternalID) {
|
||||||
|
WeakReference<DWSubEntity> ref = entitiesByInternalID.get(intWID);
|
||||||
|
DWSubEntity reffed = (ref == null ? null : ref.get());
|
||||||
|
if(reffed == null || (reffed.isDead && reffed != this)) {
|
||||||
|
entitiesByInternalID.put(intWID, new WeakReference<DWSubEntity>(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else assert false : "updateChunkLoading on dead entity?";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float getActualClientMinecartYaw(EntityMinecart cart, double old) {
|
||||||
|
double x = cart.posX, y = cart.posY, z = cart.posZ;
|
||||||
|
Vec3 vec3 = cart.func_70489_a(x, y, z);
|
||||||
|
//float f5 = cart.rotationPitch;
|
||||||
|
double d6 = 0.30000001192092896D;
|
||||||
|
float yaw = cart.rotationYaw;
|
||||||
|
|
||||||
|
if (vec3 != null)
|
||||||
|
{
|
||||||
|
Vec3 vec31 = cart.func_70495_a(x, y, z, d6);
|
||||||
|
Vec3 vec32 = cart.func_70495_a(x, y, z, -d6);
|
||||||
|
|
||||||
|
if (vec31 == null)
|
||||||
|
{
|
||||||
|
vec31 = vec3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec32 == null)
|
||||||
|
{
|
||||||
|
vec32 = vec3;
|
||||||
|
}
|
||||||
|
|
||||||
|
//renderX += vec3.xCoord - x;
|
||||||
|
//renderY += (vec31.yCoord + vec32.yCoord) / 2.0D - y;
|
||||||
|
//renderZ += vec3.zCoord - z;
|
||||||
|
Vec3 vec33 = vec32.addVector(-vec31.xCoord, -vec31.yCoord, -vec31.zCoord);
|
||||||
|
|
||||||
|
if (vec33.lengthVector() != 0.0D)
|
||||||
|
{
|
||||||
|
vec33 = vec33.normalize();
|
||||||
|
yaw = (float)(Math.atan2(vec33.zCoord, vec33.xCoord) * 180.0D / Math.PI);
|
||||||
|
//f5 = (float)(Math.atan(vec33.yCoord) * 73.0D);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if(Math.abs(angleDiff(old, yaw)) > Math.abs(angleDiff(old, yaw+180)))
|
||||||
|
if(yaw > 0)
|
||||||
|
yaw -= 180;
|
||||||
|
else
|
||||||
|
yaw += 180;*/
|
||||||
|
|
||||||
|
return yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*private static double angleDiff(double a, double b) {
|
||||||
|
b -= a;
|
||||||
|
if(b < 0)
|
||||||
|
b = (b % 360) + 360;
|
||||||
|
b = (b + 180) % 360 - 180;
|
||||||
|
assert !(b < -180 || b > 180) : "angleDiff is broken";
|
||||||
|
return b;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpdate() {
|
||||||
|
if(!worldObj.isRemote && (getCart() == null || getCart().getDW() != this)) {
|
||||||
|
setDead();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if(ridingEntity != null && worldObj.isRemote)
|
||||||
|
// System.out.println(worldObj.isRemote+" "+(int)posX+" "+(int)posY+" "+(int)posZ+" "+(int)ridingEntity.posX+" "+(int)ridingEntity.posY+" "+(int)ridingEntity.posZ);
|
||||||
|
|
||||||
|
if(getCart() != null)
|
||||||
|
rotationYaw = !worldObj.isRemote ? ridingEntity.rotationYaw : getActualClientMinecartYaw(getCart(), rotationYaw);
|
||||||
|
//if(worldObj.isRemote) {
|
||||||
|
//System.out.println("yaw "+rotationYaw);
|
||||||
|
//}
|
||||||
|
|
||||||
|
super.onUpdate();
|
||||||
|
|
||||||
|
if(!worldObj.isRemote) {
|
||||||
|
updateChunkLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void applyGLRotation(float partialTick) {
|
||||||
|
GL11.glScalef(1.0f/SCALE, 1.0f/SCALE, 1.0f/SCALE);
|
||||||
|
if(ridingEntity != null)
|
||||||
|
GL11.glRotatef(-rotationYaw, 0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FakeEntity createExternalWorldFE() {
|
||||||
|
return new CartExternalFakeEntity(false, getCart().internalWorldID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected WorldServer getInternalWorld() {
|
||||||
|
return MinecraftServer.getServer().worldServerForDimension(getCart().internalWorldID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateExternalWorldFE(FakeEntity e_) {
|
||||||
|
CartExternalFakeEntity e = (CartExternalFakeEntity)e_;
|
||||||
|
e.x = posX;
|
||||||
|
e.y = posY;
|
||||||
|
e.z = posZ;
|
||||||
|
e.yaw = ridingEntity == null ? 0 : ridingEntity.rotationYaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is called when a position update is received from the server.
|
||||||
|
// by overriding it we make sure the client doesn't try to be smart and push this entity out of bounding boxes.
|
||||||
|
// also, ignore the position from the update packet. because it's incorrect for entities that are riding other entities.
|
||||||
|
// also, ignore the rotation. because we copy that from the cart entity.
|
||||||
|
// in fact, just do nothing when a position/rotation update is received.
|
||||||
|
@Override
|
||||||
|
public void setPositionAndRotation2(double par1, double par3, double par5, float par7, float par8, int par9) {
|
||||||
|
//this.setPosition(par1, par3, par5);
|
||||||
|
//this.setRotation(par7, par8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
120
src/main/java/mods/immibis/tinycarts/InteriorChunkGen.java
Normal file
120
src/main/java/mods/immibis/tinycarts/InteriorChunkGen.java
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
package mods.immibis.tinycarts;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import mods.immibis.subworlds.dw.DWWorldProvider;
|
||||||
|
import mods.immibis.subworlds.dw.WorldProps;
|
||||||
|
import net.minecraft.entity.EnumCreatureType;
|
||||||
|
import net.minecraft.init.Blocks;
|
||||||
|
import net.minecraft.util.IProgressUpdate;
|
||||||
|
import net.minecraft.world.ChunkPosition;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.WorldServer;
|
||||||
|
import net.minecraft.world.biome.BiomeGenBase;
|
||||||
|
import net.minecraft.world.chunk.Chunk;
|
||||||
|
import net.minecraft.world.chunk.IChunkProvider;
|
||||||
|
|
||||||
|
public class InteriorChunkGen implements IChunkProvider {
|
||||||
|
|
||||||
|
private WorldProps props;
|
||||||
|
private WorldServer w;
|
||||||
|
|
||||||
|
public InteriorChunkGen(WorldServer w, DWWorldProvider wp) {
|
||||||
|
this.props = wp.props;
|
||||||
|
this.w = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Chunk provideChunk(int i, int j) {
|
||||||
|
Chunk c = new Chunk(w, i, j);
|
||||||
|
|
||||||
|
BlockTransparentBedrock.allowPlacement.incrementAndGet();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(i == 0 && j == 0) {
|
||||||
|
for(int x = 0; x < props.xsize; x++)
|
||||||
|
for(int z = 0; z < props.zsize; z++) {
|
||||||
|
c.func_150807_a(x, 0, z, TinyCartsMod.transparentBedrock, 0);
|
||||||
|
c.func_150807_a(x, props.ysize-1, z, TinyCartsMod.transparentBedrock, 0);
|
||||||
|
c.func_150807_a(x, 1, z, Blocks.planks, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int x = 0; x < props.xsize; x++)
|
||||||
|
for(int y = 0; y < props.ysize; y++) {
|
||||||
|
c.func_150807_a(x, y, 0, TinyCartsMod.transparentBedrock, 0);
|
||||||
|
c.func_150807_a(x, y, props.zsize-1, TinyCartsMod.transparentBedrock, 0);
|
||||||
|
c.func_150807_a(0, y, x, TinyCartsMod.transparentBedrock, 0);
|
||||||
|
c.func_150807_a(props.xsize-1, y, x, TinyCartsMod.transparentBedrock, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
BlockTransparentBedrock.allowPlacement.decrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
c.generateSkylightMap();
|
||||||
|
Arrays.fill(c.getBiomeArray(), (byte)BiomeGenBase.plains.biomeID);
|
||||||
|
c.isTerrainPopulated = true;
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean chunkExists(int i, int j) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Chunk loadChunk(int i, int j) {
|
||||||
|
return provideChunk(i, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void populate(IChunkProvider ichunkprovider, int i, int j) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean saveChunks(boolean flag, IProgressUpdate iprogressupdate) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean unloadQueuedChunks() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canSave() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String makeString() {
|
||||||
|
return getClass().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<?> getPossibleCreatures(EnumCreatureType enumcreaturetype, int i, int j, int k) {
|
||||||
|
return Collections.EMPTY_LIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkPosition func_147416_a(World var1, String var2, int var3, int var4, int var5) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLoadedChunkCount() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recreateStructures(int i, int j) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveExtraData() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package mods.immibis.tinycarts;
|
||||||
|
|
||||||
|
import mods.immibis.subworlds.dw.DWWorldProvider;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockRailBase;
|
||||||
|
import net.minecraft.creativetab.CreativeTabs;
|
||||||
|
import net.minecraft.entity.item.EntityMinecart;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.ChatComponentText;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class ItemMinecartAwesome extends Item {
|
||||||
|
public ItemMinecartAwesome()
|
||||||
|
{
|
||||||
|
this.maxStackSize = 1;
|
||||||
|
|
||||||
|
this.setCreativeTab(CreativeTabs.tabTransport);
|
||||||
|
this.setTextureName("tinycarts:minecart");
|
||||||
|
this.setUnlocalizedName("tinycarts.cart");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10)
|
||||||
|
{
|
||||||
|
if(par3World.provider instanceof DWWorldProvider) {
|
||||||
|
if(par3World.isRemote)
|
||||||
|
par2EntityPlayer.addChatMessage(new ChatComponentText("Don't even think about it."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block i1 = par3World.getBlock(par4, par5, par6);
|
||||||
|
|
||||||
|
if (BlockRailBase.func_150051_a(i1))
|
||||||
|
{
|
||||||
|
if (!par3World.isRemote)
|
||||||
|
{
|
||||||
|
EntityMinecart entityminecart = new EntityMinecartAwesome(par3World, (double)((float)par4 + 0.5F), (double)((float)par5 + 0.5F), (double)((float)par6 + 0.5F));
|
||||||
|
|
||||||
|
if (par1ItemStack.hasDisplayName())
|
||||||
|
{
|
||||||
|
entityminecart.setMinecartName(par1ItemStack.getDisplayName());
|
||||||
|
}
|
||||||
|
|
||||||
|
par3World.spawnEntityInWorld(entityminecart);
|
||||||
|
}
|
||||||
|
|
||||||
|
--par1ItemStack.stackSize;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
src/main/java/mods/immibis/tinycarts/NetworkHandler.java
Normal file
34
src/main/java/mods/immibis/tinycarts/NetworkHandler.java
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package mods.immibis.tinycarts;
|
||||||
|
|
||||||
|
import mods.immibis.core.api.net.IPacket;
|
||||||
|
import mods.immibis.core.api.net.IPacketMap;
|
||||||
|
|
||||||
|
public class NetworkHandler implements IPacketMap {
|
||||||
|
|
||||||
|
public static final String CHANNEL = "TinyCarts";
|
||||||
|
|
||||||
|
public static final byte PKT_CEFE_CREATE = 0;
|
||||||
|
public static final byte PKT_CEFE_DELETE = 1;
|
||||||
|
public static final byte PKT_CEFE_UPDATE = 2;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return CHANNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPacket createS2CPacket(byte id) {
|
||||||
|
switch(id) {
|
||||||
|
case PKT_CEFE_CREATE: return new CartExternalFakeEntity.CreatePacket();
|
||||||
|
case PKT_CEFE_DELETE: return new CartExternalFakeEntity.DeletePacket();
|
||||||
|
case PKT_CEFE_UPDATE: return new CartExternalFakeEntity.UpdatePacket();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPacket createC2SPacket(byte id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package mods.immibis.tinycarts;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.entity.RenderMinecart;
|
||||||
|
import net.minecraft.entity.item.EntityMinecart;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
public class RenderMinecartAwesome extends RenderMinecart {
|
||||||
|
private static final ResourceLocation texture = new ResourceLocation("tinycarts", "textures/entity/minecart.png");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ResourceLocation getEntityTexture(EntityMinecart par1EntityMinecart) {
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
}
|
122
src/main/java/mods/immibis/tinycarts/TinyCartsMod.java
Normal file
122
src/main/java/mods/immibis/tinycarts/TinyCartsMod.java
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
package mods.immibis.tinycarts;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
import mods.immibis.cobaltite.AssignedBlock;
|
||||||
|
import mods.immibis.cobaltite.AssignedItem;
|
||||||
|
import mods.immibis.cobaltite.CobaltiteMod;
|
||||||
|
import mods.immibis.cobaltite.ModBase;
|
||||||
|
import mods.immibis.core.api.APILocator;
|
||||||
|
import mods.immibis.core.api.FMLModInfo;
|
||||||
|
import mods.immibis.subworlds.ExitTeleporter;
|
||||||
|
import mods.immibis.subworlds.dw.DWWorldProvider;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
|
import net.minecraft.init.Items;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.management.ServerConfigurationManager;
|
||||||
|
import net.minecraft.util.ChatComponentText;
|
||||||
|
import net.minecraft.world.WorldServer;
|
||||||
|
import cpw.mods.fml.client.registry.RenderingRegistry;
|
||||||
|
import cpw.mods.fml.common.Mod;
|
||||||
|
import cpw.mods.fml.common.Mod.EventHandler;
|
||||||
|
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||||
|
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||||
|
import cpw.mods.fml.common.event.FMLServerStartingEvent;
|
||||||
|
import cpw.mods.fml.common.registry.EntityRegistry;
|
||||||
|
import cpw.mods.fml.common.registry.GameRegistry;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IMPORTANT SMALL DETAIL: -X EITHER FORWARD OR BACKWARD, -Z IS SIDEWAYS.
|
||||||
|
*/
|
||||||
|
@Mod(modid="TinyCarts", name="TinyCarts", version="0.2", dependencies="required-after:SubWorlds")
|
||||||
|
@CobaltiteMod()
|
||||||
|
@FMLModInfo(authors="immibis", description="", url="")
|
||||||
|
public class TinyCartsMod extends ModBase {
|
||||||
|
@AssignedItem(id="awesomecart")
|
||||||
|
public static ItemMinecartAwesome itemCart;
|
||||||
|
|
||||||
|
@AssignedBlock(id="transparentbedrock")
|
||||||
|
public static BlockTransparentBedrock transparentBedrock;
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void init(FMLInitializationEvent evt) {
|
||||||
|
EntityRegistry.registerModEntity(EntityMinecartAwesome.class, "tinycarts.cart", 0, this, 50, 1, true);
|
||||||
|
EntityRegistry.registerModEntity(EntityMinecartAwesome.DWSubEntity.class, "tinycarts.cart.dwsub", 1, this, 50, 1, true);
|
||||||
|
|
||||||
|
APILocator.getNetManager().listen(new NetworkHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addRecipes() throws Exception {
|
||||||
|
GameRegistry.addRecipe(new ItemStack(itemCart), "D D", "DDD", 'D', Items.diamond);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onServerStart(FMLServerStartingEvent evt) {
|
||||||
|
evt.registerServerCommand(new CommandExitCart());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
protected void clientInit() throws Exception {
|
||||||
|
RenderingRegistry.registerEntityRenderingHandler(EntityMinecartAwesome.class, new RenderMinecartAwesome());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void __init(FMLInitializationEvent evt) {super._init(evt);}
|
||||||
|
@EventHandler
|
||||||
|
public void __preinit(FMLPreInitializationEvent evt) {super._preinit(evt);}
|
||||||
|
|
||||||
|
private static long lastRFCWarnTime = 0;
|
||||||
|
public static void removeFromCart(Entity ent, boolean ignoreIfNotInCart) {
|
||||||
|
if(ent.worldObj.isRemote) {
|
||||||
|
assert false : "removeFromCart - on client world!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(ent.worldObj.provider instanceof DWWorldProvider)) {
|
||||||
|
assert ignoreIfNotInCart : "removeFromCart - not in DW world!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWWorldProvider wp = (DWWorldProvider)ent.worldObj.provider;
|
||||||
|
if(wp.props.generatorClass != InteriorChunkGen.class) {
|
||||||
|
assert ignoreIfNotInCart : "removeFromCart - not in TinyCart world!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX this way of getting the entity is hacky
|
||||||
|
WeakReference<EntityMinecartAwesome.DWSubEntity> dwsub_ref = EntityMinecartAwesome.entitiesByInternalID.get(wp.dimensionId);
|
||||||
|
|
||||||
|
EntityMinecartAwesome.DWSubEntity dwsub = dwsub_ref == null ? null : dwsub_ref.get();
|
||||||
|
if(dwsub == null) {
|
||||||
|
if(lastRFCWarnTime - System.nanoTime() > 5000) {
|
||||||
|
System.out.println("[TinyCarts] Potential problem - entity is leaving a cart, but we can't find the outside of the cart! Entity is "+ent+", internal world ID is "+ent.worldObj.provider.dimensionId+". This message will only be printed once every 5 seconds, maximum.");
|
||||||
|
lastRFCWarnTime = System.nanoTime();
|
||||||
|
}
|
||||||
|
if(ent instanceof EntityPlayer)
|
||||||
|
((EntityPlayer)ent).addChatMessage(new ChatComponentText("Uh oh! Outside of the cart could not be found! Cannot teleport you, sorry."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldServer outsideWorld = (WorldServer)dwsub.worldObj;
|
||||||
|
double x = dwsub.posX;
|
||||||
|
double y = dwsub.posY;
|
||||||
|
double z = dwsub.posZ;
|
||||||
|
|
||||||
|
x += (outsideWorld.rand.nextDouble() + 1) * (outsideWorld.rand.nextBoolean() ? -1 : 1);
|
||||||
|
z += (outsideWorld.rand.nextDouble() + 1) * (outsideWorld.rand.nextBoolean() ? -1 : 1);
|
||||||
|
|
||||||
|
ServerConfigurationManager scm = MinecraftServer.getServer().getConfigurationManager();
|
||||||
|
if(ent instanceof EntityPlayerMP)
|
||||||
|
scm.transferPlayerToDimension((EntityPlayerMP)ent, outsideWorld.provider.dimensionId, new ExitTeleporter(outsideWorld, x, y, z));
|
||||||
|
//else
|
||||||
|
// scm.transferEntityToWorld(ent, par2, par3WorldServer, par4WorldServer)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
2
src/main/resources/assets/tinycarts/lang/en_US.lang
Normal file
2
src/main/resources/assets/tinycarts/lang/en_US.lang
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
tile.tinycarts.transparent_bedrock.name=You're not supposed to have this block!
|
||||||
|
item.tinycarts.cart.name=Expandable Minecart
|
BIN
src/main/resources/assets/tinycarts/textures/entity/minecart.png
Normal file
BIN
src/main/resources/assets/tinycarts/textures/entity/minecart.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
BIN
src/main/resources/assets/tinycarts/textures/items/minecart.png
Normal file
BIN
src/main/resources/assets/tinycarts/textures/items/minecart.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 354 B |
Loading…
Reference in a new issue