用户:
Fox_Awa查看:1 回复:8 评论:1 创建时间:2020-11-01T20:29:25
这是一个公众项目,欢迎参与我们,大家一起挖掘岛三,享受代码乐趣。
岛三一部分源代码已泄露。至于为什么只有一部分,这个待会会说。
已经发现的隐藏类(暂时无法访问,但可以推测出内容):
Box3LogLevel 在console对象中 隐藏成员 用于表示console消息的重要程度 枚举类 状态:INFO/DEBUG/WARN/ERROR
api_[n] 这些都是岛三的内部API。
selectors_[n] 这些都是选择器的内部实现。
注:selectors_1有一个ParsedSelector,就是QueryString。只接受字符串,所以依照源代码,这里需要隐式转换(即arg+'')。然后还有一个testEntity函数,用于测试wrapper,这玩意返回布尔值,如果为真代表实体匹配,至于wrapper是什么,就是那个黑箱子_this里面的entities了。entities就相当于world.querySelectorAll('*')这样的,不过是wrapper而已。wrapper的类型我们暂时不知,放到一边。在阅读源代码之后我们还发现,[querySelector是不能用player来匹配的,也不能用*匹配。]
已经发现的隐藏函数(知道其作用,但是不能访问内容):
world._this._say(0,0,消息) 用于发送消息。0应该是指id,id 0为世界,但不知道是哪个0。
world._this._createEntity(id号) 用于创建指定id号的[空]实体。(不受entityQuota限制)
注:计算id的方法是:((++ _this.entityCounter) << 1) + 1 即实体计数器+1后左移一位,然后再+1。
例:设_this.entityCounter=1,则id为5。
注意,实体计数器并非当前创建的实体数,当前创建的实体数为_this.scriptEntityCount而不是_this.entityCounter。
我们这里假设不进行任何操作时为0。
_this._createEntity会返回一个类似于{entity:new Box3Entity()}这样的数据。
[world的私有变量].coerceEntityConfig(实体设定(即为world.createEntity传进去的东西),实体(就是Box3Entity,源代码是wrapper.entity,而wrapper是由_this._createEntity得到的,所以我们知道这里是给实体赋值))
相关变量:
_this.pendingCreate Array 用于存放正在创建的实体.为什么会这样说呢?因为后面还有一个内部函数,叫
notifyEntityCreate(用到我们之前那个wrapper) 确认实体已经创建
确认之后会返回wrapper.entity,且没有if,并且完成后pendingCreate没有被pop出来,我想应该是在notifyEntityCreate阶段做好的
_this.getEntities和_this.getPlayers 前者用于获取实体,后者用于获取玩家。用于querySelectorAll匹配。这些关键字不会用ParsedSelector解析。
注意!我们发现world.testSelector也是有的,但是其中的entity必定会被转成wrapper。我们还发现了个调用方式:
var wrapper = _this.wrapperIndex.get(entity);
是什么意思呢?wrapperIndex这个的字面意思让我们知道这是“包装索引”,实际上entity就是个index而已。真正的幕后主人是wrapper。
world.raycast这个函数本来不怎么起眼,但是它十分有趣,告诉我们射线是怎么算的,所以我这里摘抄下来。
"raycast":[fun](origin, direction, options) {
var _a = coerce_1.coerceVec3(origin, new math_1.Box3Vector3(0, 0, 0)), ox = _a.x, oy = _a.y, oz = _a.z;
var _b = coerce_1.coerceVec3(direction, new math_1.Box3Vector3(0, 0, 0)), dx = _b.x, dy = _b.y, dz = _b.z;
var _c = coerceRaycastOptions(options || {}, {
maxDistance: Infinity,
ignoreFluid: false,
ignoreEntities: false,
ignoreVoxel: false,
}), maxDistance = _c.maxDistance, ignoreEntities = _c.ignoreEntities, ignoreFluid = _c.ignoreFluid, ignoreVoxel = _c.ignoreVoxel;
var l = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (l > 1e-8) {
dx /= l;
dy /= l;
dz /= l;
}
var result = new api_1.Box3RaycastResult(false, null, 0, new math_1.Box3Vector3(ox, oy, oz), new math_1.Box3Vector3(dx, dy, dz), maxDistance, new math_1.Box3Vector3(0, 0, 0), new math_1.Box3Vector3(0, 0, 0), new math_1.Box3Vector3(0, 0, 0));
if (!ignoreEntities) {
var bodyRaycast = raycast_bodies_1.BodyRaycastSchema.alloc();
if (raycast_bodies_1.raycastBodies(bodyRaycast喵bodies, ox, oy, oz, dx, dy, dz, 0)) {
var e = _this.entity.entityIndex.get(bodyRaycast.hitId);
if (e && bodyRaycast.hitTime < maxDistance) {
result.hit = true;
result.hitEntity = e.entity;
result.distance = bodyRaycast.hitTime;
result.normal.x = bodyRaycast.hitNormal[0];
result.normal.y = bodyRaycast.hitNormal[1];
result.normal.z = bodyRaycast.hitNormal[2];
result.hitPosition.x = bodyRaycast.hitPosition[0];
result.hitPosition.y = bodyRaycast.hitPosition[1];
result.hitPosition.z = bodyRaycast.hitPosition[2];
}
}
raycast_bodies_1.BodyRaycastSchema.free(bodyRaycast);
}
if (!ignoreVoxel) {
var rayHit = new voxel_raycast_1.VoxelRaycastHitResult();
if (voxel_raycast_1.raycast(rayHit, _this._blockIndex, _this._voxel.voxels, gl_matrix_1.vec3.fromValues(ox, oy, oz), gl_matrix_1.vec3.fromValues(dx, dy, dz), result.distance, ignoreFluid)) {
result.hit = true;
result.hitEntity = null;
result.hitVoxel = rayHit.hitBlock;
result.distance = rayHit.hitDistance;
result.hitPosition.x = rayHit.hitPosition[0];
result.hitPosition.y = rayHit.hitPosition[0];
result.hitPosition.z = rayHit.hitPosition[0];
result.voxelIndex.x = rayHit.hitVoxel[0];
result.voxelIndex.y = rayHit.hitVoxel[1];
result.voxelIndex.z = rayHit.hitVoxel[2];
result.normal.x = rayHit.hitNormal[0];
result.normal.y = rayHit.hitNormal[1];
result.normal.z = rayHit.hitNormal[2];
}
}
return result;
}
看了这些函数你可能吃惊不已。没错,岛三的外部函数只是冰山一角(甚至连一个点都不到),而内部函数却是一个超级奇妙的世界!!!
接下来是一些无法查看内容仅能推测作用的变量/函数:
_this.protocol 推测:这是一个类,且不是enum类,是跟服务器通信的最关键的位置。这部分较难爬取,但是成功以后对我们的岛三代码挖掘有非常大的用处。
已知函数:
_this.protocol.server(服务器).message(负责控制台).clearLog();
这一部分主要是为了多人同步控制台而生的。
_this.config 推测:这是一个类,且不是enum类,里面存放了很多跟岛三配置有关的东西,也是关键位置。根据源代码看,entityQuota依赖这个类,大多数函数也依赖这个类。
由于时间关系,我只介绍了一部分内部代码,其余代码我会分期出(前提是我不被封号,有时间且没有被编程猫工作人员上门拜访)。我只是略微讲了一点岛三主要的函数,还有更深层的东西等待着我们去探索。目前只有我一个人在发掘相关内容,可能心有余而力不足,欢迎加入我们(投递邮件喵和我们一起发掘更深层的世界。
岛三GitBook不正确的条目举例:
第一章是介绍Box3World的。岛三API告诉我们,world就是Box3World,但是实际上并不是这样的。
Box3World的构造代码:
[fun] Box3World(entityQuota, onRespawn, nextRespawn, createEntity, querySelector, querySelectorAll, testSelector, addCollisionFilter, removeCollisionFilter, clearCollisionFilters, collisionFilters, raycast, searchBox, onTick, nextTick, onTakeDamage, nextTakeDamage, onDie, nextDie, onPlayerJoin, nextPlayerJoin, onPlayerLeave, nextPlayerLeave, onEntityCreate, nextEntityCreate, onEntityDestroy, nextEntityDestroy, say, onChat, nextChat, onClick, nextClick, onPress, nextPress, onRelease, nextRelease, onEntityContact, nextEntityContact, onEntitySeparate, nextEntitySeparate, onVoxelContact, nextVoxelContact, onVoxelSeparate, nextVoxelSeparate, onFluidEnter, nextFluidEnter, onFluidLeave, nextFluidLeave, triggers, addTrigger, removeTrigger, onInteract, nextInteract, sound) {
this.entityQuota = entityQuota;
this.onRespawn = onRespawn;
this.nextRespawn = nextRespawn;
this.createEntity = createEntity;
this.querySelector = querySelector;
this.querySelectorAll = querySelectorAll;
this.testSelector = testSelector;
this.addCollisionFilter = addCollisionFilter;
this.removeCollisionFilter = removeCollisionFilter;
this.clearCollisionFilters = clearCollisionFilters;
this.collisionFilters = collisionFilters;
this.raycast = raycast;
this.searchBox = searchBox;
this.onTick = onTick;
this.nextTick = nextTick;
this.onTakeDamage = onTakeDamage;
this.nextTakeDamage = nextTakeDamage;
this.onDie = onDie;
this.nextDie = nextDie;
this.onPlayerJoin = onPlayerJoin;
this.nextPlayerJoin = nextPlayerJoin;
this.onPlayerLeave = onPlayerLeave;
this.nextPlayerLeave = nextPlayerLeave;
this.onEntityCreate = onEntityCreate;
this.nextEntityCreate = nextEntityCreate;
this.onEntityDestroy = onEntityDestroy;
this.nextEntityDestroy = nextEntityDestroy;
this.say = say;
this.onChat = onChat;
this.nextChat = nextChat;
this.onClick = onClick;
this.nextClick = nextClick;
this.onPress = onPress;
this.nextPress = nextPress;
this.onRelease = onRelease;
this.nextRelease = nextRelease;
this.onEntityContact = onEntityContact;
this.nextEntityContact = nextEntityContact;
this.onEntitySeparate = onEntitySeparate;
this.nextEntitySeparate = nextEntitySeparate;
this.onVoxelContact = onVoxelContact;
this.nextVoxelContact = nextVoxelContact;
this.onVoxelSeparate = onVoxelSeparate;
this.nextVoxelSeparate = nextVoxelSeparate;
this.onFluidEnter = onFluidEnter;
this.nextFluidEnter = nextFluidEnter;
this.onFluidLeave = onFluidLeave;
this.nextFluidLeave = nextFluidLeave;
this.triggers = triggers;
this.addTrigger = addTrigger;
this.removeTrigger = removeTrigger;
this.onInteract = onInteract;
this.nextInteract = nextInteract;
this.sound = sound;
this.projectName = 'Project';
this.currentTick = 0;
this.lightMode = 'natural';
this.sunPhase = 0;
this.sunFrequency = 0;
this.lunarPhase = 0;
this.sunDirection = new math_1.Box3Vector3(0, -1, 0);
this.sunLight = new math_1.Box3RGBColor(1000, 1000, 1000);
this.skyLeftLight = new math_1.Box3RGBColor(0, 0, 0);
this.skyRightLight = new math_1.Box3RGBColor(0, 0, 0);
this.skyBottomLight = new math_1.Box3RGBColor(0, 0, 0);
this.skyTopLight = new math_1.Box3RGBColor(0, 0, 0);
this.skyFrontLight = new math_1.Box3RGBColor(0, 0, 0);
this.skyBackLight = new math_1.Box3RGBColor(0, 0, 0);
this.fogColor = new math_1.Box3RGBColor(1, 1, 1);
this.fogStartDistance = 0;
this.fogHeightOffset = 0;
this.fogHeightFalloff = 0.8;
this.fogUnifor喵ensity = 0;
this.maxFog = 1;
this.snowDensity = 0;
this.snowSizeLo = 0;
this.snowSizeHi = 1;
this.snowFallSpeed = 1;
this.snowSpinSpeed = 0;
this.snowColor = new math_1.Box3RGBAColor(1, 1, 1, 1);
this.snowTexture = '';
this.rainDensity = 0;
this.rainDirection = new math_1.Box3Vector3(0, 1, 0);
this.rainSpeed = 1;
this.rainSizeLo = 0;
this.rainSizeHi = 1;
this.rainInterference = 0;
this.rainColor = new math_1.Box3RGBAColor(1, 1, 1, 1);
this.gravity = -0.1;
this.airFriction = 0.001;
this.breakVoxelSound = new Box3SoundEffect();
this.placeVoxelSound = new Box3SoundEffect();
this.playerJoinSound = new Box3SoundEffect();
this.playerLeaveSound = new Box3SoundEffect();
this.ambientSound = new Box3SoundEffect();
}
没错,看起来就是这么“简单”。但结合我们之前讲的内容,各种_开头的隐藏API,让我们觉得这个“world”已经不再那么简单了。没错,world不可能是由Box3World构造的(除非说给类添加成员),world是由一个隐藏类构造的,而这个隐藏类我们现在还无法知道,它在隐藏代码的最深处,而以我的能力还无法挖掘这个的代码。但是,我们还是有命名权的。我们这里可以给它起个名字——
Box3RealWorld。
总有一天,Box3的代码会被全部挖掘出来,而到了那个时候,我们人人都可以拥有一个去除掉了所有限制的,自定义化的Box3。
Q:为什么有些类/函数的内容我们不知道?
因为Box3使用了特权方法来隔离代码。并且,一部分函数是在内部var的,我们也不能读取到这部分的函数,只能读取到公共属性,不过我们能知道的已经非常多了。剩下的代码,只能等官方披露或者我们探索了。我们现在已经无法继续探索下去了,继续探索下去的话,只能使用恶意参数构造(XSS)来进行进一步挖掘。
本篇文章写了很久,且是完全善意的。虽然继续挖掘可能会使作弊程序和Bot代玩滋生,但是这也是一次——
追求自由的喵。
希望编程猫官方别删。