使用的MC版本是1.8.9,反编译、反混淆用Forge

本篇内容从玩家点击“创建世界”开始,到具体的生成区块前为止

世界生成过程

世界设置

首先从创建世界的GUI开始看,类名net.minecraft.client.gui.GuiCreateWorld,以下是点击按钮的代码

 /*** Called by the controls from the buttonList when activated. (Mouse pressed for buttons)*/protected void actionPerformed(GuiButton button) throws IOException{// ...else if (button.id == 0) // 判断点击的是不是“创建新的世界”按钮{this.mc.displayGuiScreen((GuiScreen)null);if (this.field_146345_x) // 已经点击了这个按钮,不再重复以下代码{return;}this.field_146345_x = true;// 这个i就是随机数种子,初始化为随机数long i = (new Random()).nextLong();// s是玩家输入的种子String s = this.field_146335_h.getText();// 如果玩家输入了种子,使用玩家输入的种子if (!StringUtils.isEmpty(s)){try{long j = Long.parseLong(s);if (j != 0L){i = j;}}catch (NumberFormatException var7){// 如果输入的不是数字,使用字符串的哈希值i = (long)s.hashCode();}}WorldType.worldTypes[this.selectedIndex].onGUICreateWorldPress(); // 目前版本这个函数为空// 游戏模式(生存、创造等),这个决定玩家的能力(飞行、无敌等)WorldSettings.GameType worldsettings$gametype = WorldSettings.GameType.getByName(this.gameMode);// 这里传入了各种游戏设置,就是你在GUI上看到的那些设置(生成建筑、超平坦等)WorldSettings worldsettings = new WorldSettings(i, worldsettings$gametype, this.field_146341_s, this.field_146337_w, WorldType.worldTypes[this.selectedIndex]);worldsettings.setWorldName(this.chunkProviderSettingsJson); // 世界名称if (this.field_146338_v && !this.field_146337_w){worldsettings.enableBonusChest(); // 奖励箱}if (this.allowCheats && !this.field_146337_w){worldsettings.enableCommands(); // 允许作弊}// 启动游戏服务器,参数为存档文件夹路径、世界(文件夹)名、游戏设置this.mc.launchIntegratedServer(this.field_146336_i, this.field_146333_g.getText().trim(), worldsettings);}// ...

启动游戏服务器

这里补充一些小知识,MC的单人游戏其实是在本进程内建了服务器,服务器才是负责生成世界的,客户端只负责操作输入、渲染等

类名net.minecraft.client.Minecraft

 /*** Arguments: World foldername,  World ingame name, WorldSettings*/public void launchIntegratedServer(String folderName, String worldName, WorldSettings worldSettingsIn){net.minecraftforge.fml.client.FMLClientHandler.instance().startIntegratedServer(folderName, worldName, worldSettingsIn);// 首先卸载已经加载的世界this.loadWorld((WorldClient)null);System.gc();ISaveHandler isavehandler = this.saveLoader.getSaveLoader(folderName, false);// 世界信息,包含世界名、难度、时间、出生点等东西WorldInfo worldinfo = isavehandler.loadWorldInfo();// 因为是创造新的世界,这里worldinfo == nullif (worldinfo == null && worldSettingsIn != null){worldinfo = new WorldInfo(worldSettingsIn, folderName);isavehandler.saveWorldInfo(worldinfo);}if (worldSettingsIn == null){worldSettingsIn = new WorldSettings(worldinfo);}try{// 启动游戏服务器线程this.theIntegratedServer = new IntegratedServer(this, folderName, worldName, worldSettingsIn);this.theIntegratedServer.startServerThread();this.integratedServerIsRunning = true;}catch (Throwable throwable){CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Starting integrated server");CrashReportCategory crashreportcategory = crashreport.makeCategory("Starting integrated server");crashreportcategory.addCrashSection("Level ID", folderName);crashreportcategory.addCrashSection("Level Name", worldName);throw new ReportedException(crashreport);}this.loadingScreen.displaySavingString(I18n.format("menu.loadingLevel", new Object[0]));// 轮询获取加载世界的进度并显示while (!this.theIntegratedServer.serverIsInRunLoop()){if (!net.minecraftforge.fml.common.StartupQuery.check()){loadWorld(null);displayGuiScreen(null);return;}String s = this.theIntegratedServer.getUserMessage();if (s != null){this.loadingScreen.displayLoadingString(I18n.format(s, new Object[0]));}else{this.loadingScreen.displayLoadingString("");}try{Thread.sleep(200L);}catch (InterruptedException var9){;}}// 以下是客户端与服务器连接,这里不讨论this.displayGuiScreen((GuiScreen)null);SocketAddress socketaddress = this.theIntegratedServer.getNetworkSystem().addLocalEndpoint();NetworkManager networkmanager = NetworkManager.provideLocalClient(socketaddress);networkmanager.setNetHandler(new NetHandlerLoginClient(networkmanager, this, (GuiScreen)null));networkmanager.sendPacket(new C00Handshake(47, socketaddress.toString(), 0, EnumConnectionState.LOGIN, true));com.mojang.authlib.GameProfile gameProfile = this.getSession().getProfile();if (!this.getSession().hasCachedProperties()){gameProfile = sessionService.fillProfileProperties(gameProfile, true); //Forge: Fill profile properties upon game load. Fixes MC-52974.this.getSession().setProperties(gameProfile.getProperties());}networkmanager.sendPacket(new C00PacketLoginStart(gameProfile));this.myNetworkManager = networkmanager;}

加载世界

类名net.minecraft.server.integrated.IntegratedServer

服务器线程启动后调用这个函数

 /*** Initialises the server and starts it.*/protected boolean startServer() throws IOException{logger.info("Starting integrated minecraft server version 1.8.9");this.setOnlineMode(true);this.setCanSpawnAnimals(true);this.setCanSpawnNPCs(true);this.setAllowPvp(true);this.setAllowFlight(true);logger.info("Generating keypair");this.setKeyPair(CryptManager.generateKeyPair());if (!net.minecraftforge.fml.common.FMLCommonHandler.instance().handleServerAboutToStart(this)) return false;// 加载所有世界(主世界、地狱、末地等)this.loadAllWorlds(this.getFolderName(), this.getWorldName(), this.theWorldSettings.getSeed(), this.theWorldSettings.getTerrainType(), this.theWorldSettings.getWorldName());this.setMOTD(this.getServerOwner() + " - " + this.worldServers[0].getWorldInfo().getWorldName());return net.minecraftforge.fml.common.FMLCommonHandler.instance().handleServerStarting(this);}
protected void loadAllWorlds(String folderName, String worldName, long seed, WorldType type, String p_71247_6_){this.convertMapIfNeeded(folderName);ISaveHandler isavehandler = this.getActiveAnvilConverter().getSaveLoader(folderName, true);this.setResourcePackFromWorld(this.getFolderName(), isavehandler);WorldInfo worldinfo = isavehandler.loadWorldInfo();if (worldinfo == null){worldinfo = new WorldInfo(this.theWorldSettings, worldName);}else{worldinfo.setWorldName(worldName);}WorldServer overWorld = (isDemo() ? (WorldServer)(new DemoWorldServer(this, isavehandler, worldinfo, 0, this.theProfiler)).init() :(WorldServer)(new WorldServer(this, isavehandler, worldinfo, 0, this.theProfiler)).init());overWorld.initialize(this.theWorldSettings);// 初始化各世界for (int dim : net.minecraftforge.common.DimensionManager.getStaticDimensionIDs()){WorldServer world = (dim == 0 ? overWorld : (WorldServer)(new WorldServerMulti(this, isavehandler, dim, overWorld, this.theProfiler)).init());world.addWorldAccess(new WorldManager(this, world));if (!this.isSinglePlayer()){world.getWorldInfo().setGameType(getGameType());}net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.WorldEvent.Load(world));}this.getConfigurationManager().setPlayerManager(new WorldServer[]{ overWorld });if (overWorld.getWorldInfo().getDifficulty() == null){this.setDifficultyForAllWorlds(this.mc.gameSettings.difficulty);}// 加载玩家附近的区块this.initialWorldChunkLoad();}

类名net.minecraft.server.MinecraftServer

 protected void initialWorldChunkLoad(){int i = 16;int j = 4;int k = 192;int l = 625;int i1 = 0;this.setUserMessage("menu.generatingTerrain");int j1 = 0;logger.info("Preparing start region for level " + j1);WorldServer worldserver = net.minecraftforge.common.DimensionManager.getWorld(j1);BlockPos blockpos = worldserver.getSpawnPoint();long k1 = getCurrentTimeMillis();// MC中区块大小是16*16,所以这里是加载玩家附近25*25个区块for (int l1 = -192; l1 <= 192 && this.isServerRunning(); l1 += 16){for (int i2 = -192; i2 <= 192 && this.isServerRunning(); i2 += 16){long j2 = getCurrentTimeMillis();if (j2 - k1 > 1000L){this.outputPercentRemaining("Preparing spawn area", i1 * 100 / 625);k1 = j2;}++i1;// 加载一个区块,参数是区块坐标(方块坐标/16)worldserver.theChunkProviderServer.loadChunk(blockpos.getX() + l1 >> 4, blockpos.getZ() + i2 >> 4);}}this.clearCurrentTask();}

类名net.minecraft.world.gen.ChunkProviderServer

   /*** loads or generates the chunk at the chunk location specified*/public Chunk loadChunk(int p_73158_1_, int p_73158_2_){return loadChunk(p_73158_1_, p_73158_2_, null);}public Chunk loadChunk(int par1, int par2, Runnable runnable){long k = ChunkCoordIntPair.chunkXZ2Int(par1, par2);this.droppedChunksSet.remove(Long.valueOf(k));Chunk chunk = (Chunk)this.id2ChunkMap.getValueByKey(k);net.minecraft.world.chunk.storage.AnvilChunkLoader loader = null;if (this.chunkLoader instanceof net.minecraft.world.chunk.storage.AnvilChunkLoader){loader = (net.minecraft.world.chunk.storage.AnvilChunkLoader) this.chunkLoader;}// We can only use the queue for already generated chunksif (chunk == null && loader != null && loader.chunkExists(this.worldObj, par1, par2)){if (runnable != null){net.minecraftforge.common.chunkio.ChunkIOExecutor.queueChunkLoad(this.worldObj, loader, this, par1, par2, runnable);return null;}else{chunk = net.minecraftforge.common.chunkio.ChunkIOExecutor.syncChunkLoad(this.worldObj, loader, this, par1, par2);}}else if (chunk == null){// 此时区块还未生成所以会运行到这里chunk = this.originalLoadChunk(par1, par2);}// If we didn't load the chunk async and have a callback run it nowif (runnable != null){runnable.run();}return chunk;}public Chunk originalLoadChunk(int p_73158_1_, int p_73158_2_){long i = ChunkCoordIntPair.chunkXZ2Int(p_73158_1_, p_73158_2_);this.droppedChunksSet.remove(Long.valueOf(i));Chunk chunk = (Chunk)this.id2ChunkMap.getValueByKey(i);if (chunk == null){boolean added = loadingChunks.add(i);if (!added){net.minecraftforge.fml.common.FMLLog.bigWarning("There is an attempt to load a chunk (%d,%d) in di    >mension %d that is already being loaded. This will cause weird chunk breakages.", p_73158_1_, p_73158_2_, worldObj.provider.getDimensionId());}chunk = net.minecraftforge.common.ForgeChunkManager.fetchDormantChunk(i, this.worldObj);if (chunk == null)chunk = this.loadChunkFromFile(p_73158_1_, p_73158_2_);if (chunk == null){if (this.serverChunkGenerator == null){chunk = this.dummyChunk;}else{try{// 如果区块不存在,这个函数会生成区块chunk = this.serverChunkGenerator.provideChunk(p_73158_1_, p_73158_2_);}catch (Throwable throwable){CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Exception generating new chunk");CrashReportCategory crashreportcategory = crashreport.makeCategory("Chunk to be generated");crashreportcategory.addCrashSection("Location", String.format("%d,%d", new Object[] {Integer.valueOf(p_73158_1_), Integer.valueOf(p_73158_2_)}));crashreportcategory.addCrashSection("Position hash", Long.valueOf(i));crashreportcategory.addCrashSection("Generator", this.serverChunkGenerator.makeString());throw new ReportedException(crashreport);}}}this.id2ChunkMap.add(i, chunk);this.loadedChunks.add(chunk);loadingChunks.remove(i);chunk.onChunkLoad();chunk.populateChunk(this, this, p_73158_1_, p_73158_2_);}return chunk;}

我的世界-世界生成过程-01-生成地形之前相关推荐

  1. Minecraft的世界生成过程(一)生成地形之前

    首先剧透一下,Minecraft生成地形的主要算法就是噪声函数,Notch本人也早就回答过了.但是我一直没有仔细研究MC生成世界的整个过程,最近有时间就好好研究一下 使用的MC版本是1.8.9,反编译 ...

  2. 【Unity3D】Unity3D开发《我的世界》之六、创建地形(视频 + 源码)

    转载请注明出处:http://www.cnblogs.com/shamoyuu/p/unity_minecraft_06.html 一.引入LibNoise 虽然Unity3D里也有一个Mathf.P ...

  3. 小啊呜产品读书笔记001:《邱岳的产品手记-02》 开篇词 产品经理的世界没有对错 01讲 验证码是个好设计吗 02讲 产品经理工具指南 03讲 产品案例分析·Trigraphy的设计哲学

    小啊呜产品读书笔记001:<邱岳的产品手记-02> 开篇词 产品经理的世界没有对错 & 01讲 验证码是个好设计吗 & 02讲 产品经理工具指南 & 03讲 产品案 ...

  4. 我的世界服务器修改怪物生成,我的世界阻止服务器怪物生成指令大全

    在我的世界游戏中,如果你是在玩服务器的话,你不想见到某种怪物,你就需要使用指令,下面小编就为大家整理出了我的世界阻止服务器怪物生成指令大全,希望大家喜欢! #+(true为是,false为否) spa ...

  5. 我的世界服务器修改生成怪物速度的文件,我的世界服务器禁止怪物生成指令大全...

    我的世界服务器禁止怪物生成指令大全 我的世界服务器禁止怪物生成指令大全.有没有小伙伴和小编一样对于我的世界中各式各样的怪物头疼不已呢?是的话,今天大家有福了,因为小编今天教大家如何在自建服务器中使用禁 ...

  6. 修改我的世界服务器怪物爆率,我的世界阻止服务器怪物生成指令汇总

    我的世界阻止服务器怪物生成指令汇总,如果你是在玩服务器的话,那么下面的这些指令或许会对你有所帮助,下面的指令可以帮助你在服务器中来控制一些怪物的生成,一起来看下. #+(true为是,false为否) ...

  7. java版溺尸掉三叉戟吗_我的世界溺尸怎么生成_我的世界溺尸掉落什么-街机中国...

    我的世界溺尸在哪,我的世界溺尸怎么生成,我的世界溺尸掉落什么,我的世界溺尸三叉戟怎么得,下面小编就给大家带来我的世界溺尸详细攻略,感兴趣的朋友一起来看看吧! 溺尸溺尸(Drowned)是在所有海洋生物 ...

  8. 【毕业设计】基于程序化生成和音频检测的生态仿真与3D内容生成系统----程序化生成地形算法设计

    2 程序化生成地形算法设计 Input: Output: 2.1 地形的生成 程序化生成地形算法是一种在计算机中生成地形的方法,通常用于游戏开发和虚拟现实应用.下面是几种常见的程序化生成地形算法: D ...

  9. unity3d 随机生成地形之随机山脉

    利用Fractal Noise生成地形,再加上山体shader,外加雪shader Noise生成结果 noise 生成主要参考这篇文章,就不再赘述 Value3D: Perlin2D: Fracta ...

  10. 应用Revit结合CAD图纸生成地形实体和地质模型

    由于本人是岩土工程,研究方向主要偏向于支挡防护工程,不可避免要在BIM软件中进行地形实体的构建.经过资料的搜集和整理,发现利用Revit的Dynamo可以进行操作.但是利用Dynamo 节点搭建的脚本 ...

最新文章

  1. Linux配置协同工作目录,Linux学习二:文件权限与目录配置
  2. 图灵奖得主、AAAI候任主席展望“AI未来10年”
  3. 常见的数据库端口及查询方法
  4. socket与文件描述符
  5. 【DP】K星人的语言(2020特长生 T3)
  6. 基于TextRank算法的文本摘要(附Python代码)
  7. initrd的启动过程
  8. ubuntu10.10升级到11.4出错之问题解决
  9. vmware workstation不可恢复错误:(vthread-7)
  10. Corel VideoStudio X7 (64bit)安装
  11. YY直播产品体验报告
  12. 中国近代史-蒋廷黻-笔记-第一章-剿夷与抚夷-第一节-英国请中国订立邦交
  13. 一文讲透商业智能BI 到底是什么[转]
  14. 教你文件批量重命名技巧,彻底告别手工改名的繁琐
  15. 一个排列是某些对象的有序组合,例如,3124 就是数字 1,2,3,4 的一种可能排列。 如果所有的排列按照数值或者字母序排序,我们称其为一个字典序。 0, 1, 2 的字典排列有:012 021 1
  16. 原来发朋友圈还有这讲究,难怪我的朋友圈没人看
  17. java 递归算法N的乘阶
  18. Unity Shader-真实下雨路面
  19. shutter截图编辑功能
  20. go项目部署服务器保姆级教程(带图)

热门文章

  1. 创维 IPTV E900刷机DIY最详指南
  2. Win7 旗舰版 SP1环境下安装Microsoft .NET Framework 4.8
  3. DM556步进驱动器适配驱动步进电机
  4. ssm+jsp计算机毕业设计大学生工作室管理系统5465a(程序+LW+源码+远程部署)
  5. 智慧养老整体化解决方案-养老院解决方案-智能养老系统-新导智能
  6. 全球及中国包装机械行业应用规模与发展动态研究报告2022版
  7. Cadence 绘制PCB添加泪滴与差分布线与铺铜简单介绍
  8. Excel转PDF最简单的方法
  9. 关于最近DNF刷图频繁出现验证码的解决方案
  10. 基于Tensorflow2.1的Mask RCNN兼容性问题(Variables were created within a Lambda layer (anchors))