We just released a prototype of the cancelled SNES port of Puggsy! Take a look!
As always, thank you for supporting The Cutting Room Floor on Patreon!
This article is marked as NSFW!

Neopia Studio

From The Cutting Room Floor
Jump to navigation Jump to search

Title Screen

Neopia Studio

Developer: NetDragon
Publishers: NetDragon, Jumpstart
Platforms: iOS, Android
Released in US: January 22, 2022


GraphicsIcon.png This game has unused graphics.
ModelsIcon.png This game has unused models.
TextIcon.png This game has unused text.


<Sanky> please suggest an unused sprite with a clock or something
This game is still under active development.
Be aware that any unused content you find may become used or removed in the future. Please only add things to the article that are unlikely to ever be used, or went unused for some time. If they do get used, please remove them from the page and specify in the edit summary!
And you were just a scroll away from being fired too...
Oh dear, I do believe I have the vapors.
This page contains content that is not safe for work or other locations with the potential for personal embarrassment.
Such as: Textures for a nude female body.

What would happen if Homescapes got the Neopets brand slapped onto it? Well, this is exactly that. You're welcome...?

Unused Models

There's a few unused models in the game.

Unused Graphics

Early Candies

NS Early Candy 1.pngNS Early Candy 2.pngNS Early Candy 3.pngNS Early Candy 4.pngNS Early Candy 5.pngNS Early Candy 6.png

Early designs for the Petpet candies that are used in the Match 3 segments of the game.

Profile Pictures

NS ProfilePictureA.pngNS ProfilePictureB.pngNS ProfilePictureC.pngNS ProfilePictureD.pngNS ProfilePictureE.pngNS ProfilePictureF.png

Placeholder options for a profile picture in-game. In the final version, you are only allowed to choose icons of the Neopets that you have unlocked.

Floating Bridge

NS FloatingBridge.pngNS FloatPath.png

Placeholder graphics for an unimplemented floating bridge and a path on it.

Terminal Point

NS TerminalPoint.png

TerminalPoint.png appears to be a red map marker with a Chinese character on it.

Unused Textures

For some reason, low resolution, partially transparent textures of a naked woman are present in the game's files. There is no model to accompany them, so all we have are these textures.

Neopia Studio Woman Eye.png NS Woman Eyelash.png NS Woman Head.png NS Woman Body.png

Unused Text

decoder.lua

--
--------------------------------------------------------------------------------
--  FILE:  decoder.lua
--  DESCRIPTION:  protoc-gen-lua
--      Google's Protocol Buffers project, ported to lua.
--      https://code.google.com/p/protoc-gen-lua/
--
--      Copyright (c) 2010 , 林卓毅 (Zhuoyi Lin) netsnail@gmail.com
--      All rights reserved.
--
--      Use, modification and distribution are subject to the "New BSD License"
--      as listed at <url: http://www.opensource.org/licenses/bsd-license.php >.
--
--  COMPANY:  NetEase
--  CREATED:  2010年07月29日 19时30分51秒 CST
--------------------------------------------------------------------------------
--
local string = string
local table = table
local assert = assert
local ipairs = ipairs
local error = error
local print = print

local pb = require "pb"
local encoder = require "protobuf.encoder"
local wire_format = require "protobuf.wire_format"
module "protobuf.decoder"

local _DecodeVarint = pb.varint_decoder
local _DecodeSignedVarint = pb.signed_varint_decoder

local _DecodeVarint32 = pb.varint_decoder
local _DecodeSignedVarint32 = pb.signed_varint_decoder

local _DecodeVarint64 = pb.varint_decoder64
local _DecodeSignedVarint64 = pb.signed_varint_decoder64

ReadTag = pb.read_tag

local function _SimpleDecoder(wire_type, decode_value)
    return function(field_number, is_repeated, is_packed, key, new_default)
        if is_packed then
            local DecodeVarint = _DecodeVarint
            return function (buffer, pos, pend, message, field_dict)
                local value = field_dict[key]
                if value == nil then
                    value = new_default(message)
                    field_dict[key] = value
                end
                local endpoint
                endpoint, pos = DecodeVarint(buffer, pos)
                endpoint = endpoint + pos
                if endpoint > pend then
                    error('Truncated message.')
                end
                local element
                while pos < endpoint do
                    element, pos = decode_value(buffer, pos)
                    value[#value + 1] = element
                end
                if pos > endpoint then
                    value:remove(#value)
                    error('Packed element was truncated.')
                end
                return pos
            end
        elseif is_repeated then
            local tag_bytes = encoder.TagBytes(field_number, wire_type)
            local tag_len = #tag_bytes
            local sub = string.sub
            return function(buffer, pos, pend, message, field_dict)
                local value = field_dict[key]
                if value == nil then
                    value = new_default(message)
                    field_dict[key] = value
                end
                while 1 do
                    local element, new_pos = decode_value(buffer, pos)
                    value:append(element)
                    pos = new_pos + tag_len
                    if sub(buffer, new_pos+1, pos) ~= tag_bytes or new_pos >= pend then
                        if new_pos > pend then
                            error('Truncated message.')
                        end
                        return new_pos
                    end
                end
            end
        else
            return function (buffer, pos, pend, message, field_dict)
                field_dict[key], pos = decode_value(buffer, pos)
                if pos > pend then
                    field_dict[key] = nil
                    error('Truncated message.')
                end
                return pos
            end
        end
    end
end

local function _ModifiedDecoder(wire_type, decode_value, modify_value)
    local InnerDecode = function (buffer, pos)
        local result, new_pos = decode_value(buffer, pos)
        return modify_value(result), new_pos
    end
    return _SimpleDecoder(wire_type, InnerDecode)
end

local function _StructPackDecoder(wire_type, value_size, format)
    local struct_unpack = pb.struct_unpack

    function InnerDecode(buffer, pos)
        local new_pos = pos + value_size
        local result = struct_unpack(format, buffer, pos)
        return result, new_pos
    end
    return _SimpleDecoder(wire_type, InnerDecode)
end

local function _Boolean(value)
    return value ~= 0
end

Int32Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeSignedVarint32)
EnumDecoder = Int32Decoder

Int64Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeSignedVarint64)

UInt32Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint32)
UInt64Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint64)

SInt32Decoder = _ModifiedDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint32, wire_format.ZigZagDecode32)
SInt64Decoder = _ModifiedDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint64, wire_format.ZigZagDecode64)

Fixed32Decoder  = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, 4, string.byte('I'))
Fixed64Decoder  = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, 8, string.byte('Q'))
SFixed32Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, 4, string.byte('i'))
SFixed64Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, 8, string.byte('q'))
FloatDecoder    = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, 4, string.byte('f'))
DoubleDecoder   = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, 8, string.byte('d'))


BoolDecoder = _ModifiedDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint, _Boolean)


function StringDecoder(field_number, is_repeated, is_packed, key, new_default)
    local DecodeVarint = _DecodeVarint
    local sub = string.sub
    --    local unicode = unicode
    assert(not is_packed)
    if is_repeated then
        local tag_bytes = encoder.TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
        local tag_len = #tag_bytes
        return function (buffer, pos, pend, message, field_dict)
            local value = field_dict[key]
            if value == nil then
                value = new_default(message)
                field_dict[key] = value
            end
            while 1 do
                local size, new_pos
                size, pos = DecodeVarint(buffer, pos)
                new_pos = pos + size
                if new_pos > pend then
                    error('Truncated string.')
                end
                value:append(sub(buffer, pos+1, new_pos))
                pos = new_pos + tag_len
                if sub(buffer, new_pos + 1, pos) ~= tag_bytes or new_pos == pend then
                    return new_pos
                end
            end
        end
    else
        return function (buffer, pos, pend, message, field_dict)
            local size, new_pos
            size, pos = DecodeVarint(buffer, pos)
            new_pos = pos + size
            if new_pos > pend then
                error('Truncated string.')
            end
            field_dict[key] = sub(buffer, pos + 1, new_pos)
            return new_pos
        end
    end
end

function BytesDecoder(field_number, is_repeated, is_packed, key, new_default)
    local DecodeVarint = _DecodeVarint
    local sub = string.sub
    assert(not is_packed)
    if is_repeated then
        local tag_bytes = encoder.TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
        local tag_len = #tag_bytes
        return function (buffer, pos, pend, message, field_dict)
            local value = field_dict[key]
            if value == nil then
                value = new_default(message)
                field_dict[key] = value
            end
            while 1 do
                local size, new_pos
                size, pos = DecodeVarint(buffer, pos)
                new_pos = pos + size
                if new_pos > pend then
                    error('Truncated string.')
                end
                value:append(sub(buffer, pos + 1, new_pos))
                pos = new_pos + tag_len
                if sub(buffer, new_pos + 1, pos) ~= tag_bytes or new_pos == pend then
                    return new_pos
                end
            end
        end
    else
        return function(buffer, pos, pend, message, field_dict)
            local size, new_pos
            size, pos = DecodeVarint(buffer, pos)
            new_pos = pos + size
            if new_pos > pend then
                error('Truncated string.')
            end
            field_dict[key] = sub(buffer, pos + 1, new_pos)
            return new_pos
        end
    end
end

function MessageDecoder(field_number, is_repeated, is_packed, key, new_default)
    local DecodeVarint = _DecodeVarint
    local sub = string.sub

    assert(not is_packed)
    if is_repeated then
        local tag_bytes = encoder.TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
        local tag_len = #tag_bytes
        return function (buffer, pos, pend, message, field_dict)
            local value = field_dict[key]
            if value == nil then
                value = new_default(message)
                field_dict[key] = value
            end
            while 1 do
                local size, new_pos
                size, pos = DecodeVarint(buffer, pos)
                new_pos = pos + size
                if new_pos > pend then
                    error('Truncated message.')
                end
                if value:add():_InternalParse(buffer, pos, new_pos) ~= new_pos then
                    error('Unexpected end-group tag.')
                end
                pos = new_pos + tag_len
                if sub(buffer, new_pos + 1, pos) ~= tag_bytes or new_pos == pend then
                    return new_pos
                end
            end
        end
    else
        return function (buffer, pos, pend, message, field_dict)
            local value = field_dict[key]
            if value == nil then
                value = new_default(message)
                field_dict[key] = value
            end
            local size, new_pos
            size, pos = DecodeVarint(buffer, pos)
            new_pos = pos + size
            if new_pos > pend then
                error('Truncated message.')
            end
            if value:_InternalParse(buffer, pos, new_pos) ~= new_pos then
                error('Unexpected end-group tag.')
            end
            return new_pos
        end
    end
end

function _SkipVarint(buffer, pos, pend)
    local value
    value, pos = _DecodeVarint(buffer, pos)
    return pos
end

function _SkipFixed64(buffer, pos, pend)
    pos = pos + 8
    if pos > pend then 
        error('Truncated message.')
    end
    return pos
end

function _SkipLengthDelimited(buffer, pos, pend)
    local size
    size, pos = _DecodeVarint(buffer, pos)
    pos = pos + size
    if pos > pend then
        error('Truncated message.')
    end
    return pos
end

function _SkipFixed32(buffer, pos, pend)
    pos = pos + 4
    if pos > pend then
        error('Truncated message.')
    end
    return pos
end

function _RaiseInvalidWireType(buffer, pos, pend)
    error('Tag had invalid wire type.')
end

function _FieldSkipper()
    WIRETYPE_TO_SKIPPER = {
        _SkipVarint,
        _SkipFixed64,
        _SkipLengthDelimited,
        _SkipGroup,
        _EndGroup,
        _SkipFixed32,
        _RaiseInvalidWireType,
        _RaiseInvalidWireType,
    }

--    wiretype_mask = wire_format.TAG_TYPE_MASK
    local ord = string.byte
    local sub = string.sub

    return function (buffer, pos, pend, tag_bytes)
        local wire_type = ord(sub(tag_bytes, 1, 1)) % 8 + 1
        return WIRETYPE_TO_SKIPPER[wire_type](buffer, pos, pend)
    end
end

SkipField = _FieldSkipper()

TODO.txt

1、场景管理 done
2、特效管理
3、TCP Connector
4、PB Processer
5、AB
6、Touch
7、Tween -- DoTween
8、Unity Object Pool -- done
9、图集管理

代码规范.txt


一:命名规范:
	1、类命名:驼峰式命名:单词首字母大写,如:GetInstance
	2、函数命名:同类名
	3、公有变量命名:同类名
	4、私有变量命名:小写,单词之间用“_”分隔,如:self.action_list
	5、局部变量命名:同私有变量
	6、参数名命名:同私有变量
	7、任何情况下不应该由外部访问的成员,使用双下划线打头,其它同私有变量命名,如:析构函数__init,内部成员self.__callback
	8、由于脚本语言没有跳转功能,最好在UI组件实例的名字末尾标识组件类型,提高可读性:
		a)基础组件(自定义的 Component):xxx_cmp
		b)按钮(UIButton):xxx_btn
		c)文本(UIText):xxx_txet
		d)图片(UIImage):xxx_img
		e)输入框(UIInput):xxx_input
		f)标签组(UITabGroup):xxx_tabgroup
		g)按钮组(UIButtonGroup):xxx_btngroup
		h)可选中按钮(UIToggelButton):xxx_togglebtn
		i)可复用组件(UIWrapGroup):xxx_wrapgroup
		j)滑动条组件(UISlider):xxx_slider
		k)后续...
	9、所有UI脚本以UI打头,即UIxxxx,  界面层 UIxxxxView
	10、系统功能扩展函数:全部使用小写,不用下划线,如对table的扩展:table.walksort
	11、所有协程函数体以"Co"打头,如:CoAsyncLoad,表示该函数必须运行在协程中,并且可以使用任意协程相关函数
	12、所有Unity Object均使用全局函数IsNull判空===>***很重要

二:类定义和使用
	1、所有函数定义为local,在脚本最底部导出,导出的函数一定是公有的
	2、所有公有函数第一个参数是self,函数使用调用:instance:function(...)
	3、所有私有函数第一个参数是self,不导出,只能在脚本内访问,函数调用:function(self, ...)
	4、所有私有函数一定要先定义,后调用
	5、override的使用有点特殊:先用base = baseClassType,然后override时使用:base.function(self)调用父类方法
	6、继承类时,如果不是等同于cs侧sealed的概念,那么必须把基类的参数列表填写完整,后面接上自己需要的参数
	7、函数需要重载时,一般通过判断参数个数和类型来实现,此时必须把最长参数列表填齐,除了回调绑定等不定参数的特俗情况,一般情况下不要使用可变参数(...)
	9、所有定义回调的地方,都需要预先声明回调和注释说明回调原型,让使用者一目了然
	10、__init不需要调用base.__init,底层会自动调用基类构造函数,__delete也一样

三:单例类定义和使用
	1、单例类从Singleton继承,不要重写GetInstance、Delete方法
	2、单例类定义时内部函数书写规范同上:类定义和使用
	3、单例类调用一律使用singletonClass:GetInstance():function/.var访问
	4、除了局部变量,不要使用成员变量或者全局变量缓存单例类引用,如:inst = singletonClass:GetInstance(),inst:function/.var,因为单例类销毁后inst还会存在引用
	5、单例类的Instace只用来查询该单例类是否已经被创建,如:if singletonClass.Instance ~= nil then singletonClass:Delete() end

四:数据类定义和使用
	1、数据类:对普通类增加访问限制,具体为:不能对不存在的域进行读写。目的:减少因为笔误而造成的不可察Bug
	2、定义格式使用:DataClass("dataClassName", dataTable)
	3、dataTable是一张普通表,定义了该数据成员的域,必须初始化,不能有nil值
	4、定义以后不能新增数据域,访问不存在的域会提示错误,New新的数据实例同New新的类实例

五:常量类定义和使用
	1、常量类:对普通类增加访问限制,具体为:不能对不存在的域进行读写,数据域只读,不可写。目的:减少因为笔误而造成的不可察Bug
	2、定义格式使用:ConstClass("constClassName", constTable),一般用于配置表等数据,一旦生成只能查表,不能写表
	3、定义以后查询不存在的域、写不存在的域、写存在的域都会有错误提示

六:UI窗口代码规范
	1、严格遵守MVC架构:Model层数据、View层窗口组件操作、Ctrl层数据操作
	2、View层直接依赖Ctrl层,间接依赖Model层(只读);Ctrl层依赖Model层;Model层不依赖Ctrl和View层
	3、Ctrl层没有状态,可以操作游戏逻辑和Model层数据;View层除了读取配置表,不能直接操作任何游戏逻辑
	4、逻辑的运行不能依赖窗口的Ctrl层,如果需要这样的控制代码,写到游戏逻辑模块中
	5、窗口Model层不存游戏数据,它的生命周期是和窗口绑定在一起的,只能缓存用户操作,比如:当前选择了那个服务器做登陆服务器
	6、窗口Model层是针对窗口的数据,是游戏数据中心的一个抽取,比如数据中心UserData可能包括用户名、背包等等数据,但是用于界面可能只是从用户名提取部分数据展示

七:UI组件代码规范
	1、原则上尽量对UI组件执行封装:一是可以简化逻辑层脚本使用方式,二是可以利用缓存尽量减少lua与cs交换,提升性能
	2、所有UI组件最好先封装,后使用,以尽量使用Lua侧组件管理系统来简化写View层脚本的工作量,各个使用到的组件现在还不是很完善,后续...
	3、当设计通用组件时,不能直接依赖window.view,需要数据刷新最好提供函数回调
	4、UI组件代码所有函数的执行规律同Unity脚本,UI组件代码不要使用ctor、__delete函数,由OnInit、OnClose代替
	5、最好不要自己去New组件,使用AddComponent替代,否则必须自己管理生命周期---在OnDestory中调用组件的Delete方法

八:工具类代码规范
	1、目前所有和UI界面相关的公共函数添加到 Utility

九:性能
	1、性能瓶颈出现在两点:lua作为脚本语言本身的速度问题、lua与cs的频繁交互造成高频率堆栈操作和Marshall操作
	2、原则1:单次调用,内部执行性能要求高的函数,比如寻路计算,考虑放CS侧,或者用C/CPP写---要求:函数执行时间要高于lua与cs调用交互时间,否则得不偿失
	3、原则2:尽量避免与cs的交互,交互越少越好,如tolua作者对Vector3在lua侧的实现,就是为了避免Vector3操作调用cs接口,其它实现的数据结构类似
	4、不要使用cs侧协程
	5、更新频率低的函数(如UI界面倒计时)使用定时器,尽量不要用Updater
	6、虽然Lua采用分步GC,不需要太关注GC造成游戏Lag的问题,但是分配、回收频率很高的table,还是要做缓存