refactor(common): 重构 Conn 实体并优化地图进入逻辑
- 优化 Conn 实体的 SendPack 方法,提高代码复用性 - 添加 goja 模块到 go.work 文件 - 重构地图进入逻辑,增加玩家广播和刷怪功能 - 调整 OutInfo 结构中的 Vip 和 Viped 字段类型 - 简化 MonsterRefresh 结构体定义
This commit is contained in:
342
common/utils/goja/builtin_map.go
Normal file
342
common/utils/goja/builtin_map.go
Normal file
@@ -0,0 +1,342 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var mapExportType = reflect.TypeOf([][2]interface{}{})
|
||||
|
||||
type mapObject struct {
|
||||
baseObject
|
||||
m *orderedMap
|
||||
}
|
||||
|
||||
type mapIterObject struct {
|
||||
baseObject
|
||||
iter *orderedMapIter
|
||||
kind iterationKind
|
||||
}
|
||||
|
||||
func (o *mapIterObject) next() Value {
|
||||
if o.iter == nil {
|
||||
return o.val.runtime.createIterResultObject(_undefined, true)
|
||||
}
|
||||
|
||||
entry := o.iter.next()
|
||||
if entry == nil {
|
||||
o.iter = nil
|
||||
return o.val.runtime.createIterResultObject(_undefined, true)
|
||||
}
|
||||
|
||||
var result Value
|
||||
switch o.kind {
|
||||
case iterationKindKey:
|
||||
result = entry.key
|
||||
case iterationKindValue:
|
||||
result = entry.value
|
||||
default:
|
||||
result = o.val.runtime.newArrayValues([]Value{entry.key, entry.value})
|
||||
}
|
||||
|
||||
return o.val.runtime.createIterResultObject(result, false)
|
||||
}
|
||||
|
||||
func (mo *mapObject) init() {
|
||||
mo.baseObject.init()
|
||||
mo.m = newOrderedMap(mo.val.runtime.getHash())
|
||||
}
|
||||
|
||||
func (mo *mapObject) exportType() reflect.Type {
|
||||
return mapExportType
|
||||
}
|
||||
|
||||
func (mo *mapObject) export(ctx *objectExportCtx) interface{} {
|
||||
m := make([][2]interface{}, mo.m.size)
|
||||
ctx.put(mo.val, m)
|
||||
|
||||
iter := mo.m.newIter()
|
||||
for i := 0; i < len(m); i++ {
|
||||
entry := iter.next()
|
||||
if entry == nil {
|
||||
break
|
||||
}
|
||||
m[i][0] = exportValue(entry.key, ctx)
|
||||
m[i][1] = exportValue(entry.value, ctx)
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (mo *mapObject) exportToMap(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
|
||||
dst.Set(reflect.MakeMap(typ))
|
||||
ctx.putTyped(mo.val, typ, dst.Interface())
|
||||
keyTyp := typ.Key()
|
||||
elemTyp := typ.Elem()
|
||||
iter := mo.m.newIter()
|
||||
r := mo.val.runtime
|
||||
for {
|
||||
entry := iter.next()
|
||||
if entry == nil {
|
||||
break
|
||||
}
|
||||
keyVal := reflect.New(keyTyp).Elem()
|
||||
err := r.toReflectValue(entry.key, keyVal, ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
elemVal := reflect.New(elemTyp).Elem()
|
||||
err = r.toReflectValue(entry.value, elemVal, ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dst.SetMapIndex(keyVal, elemVal)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_clear(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
mo, ok := thisObj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Map.prototype.clear called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
|
||||
mo.m.clear()
|
||||
|
||||
return _undefined
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_delete(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
mo, ok := thisObj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Map.prototype.delete called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
|
||||
return r.toBoolean(mo.m.remove(call.Argument(0)))
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_get(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
mo, ok := thisObj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Map.prototype.get called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
|
||||
return nilSafe(mo.m.get(call.Argument(0)))
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_has(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
mo, ok := thisObj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Map.prototype.has called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
if mo.m.has(call.Argument(0)) {
|
||||
return valueTrue
|
||||
}
|
||||
return valueFalse
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_set(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
mo, ok := thisObj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Map.prototype.set called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
mo.m.set(call.Argument(0), call.Argument(1))
|
||||
return call.This
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_entries(call FunctionCall) Value {
|
||||
return r.createMapIterator(call.This, iterationKindKeyValue)
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_forEach(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
mo, ok := thisObj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Map.prototype.forEach called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
callbackFn, ok := r.toObject(call.Argument(0)).self.assertCallable()
|
||||
if !ok {
|
||||
panic(r.NewTypeError("object is not a function %s"))
|
||||
}
|
||||
t := call.Argument(1)
|
||||
iter := mo.m.newIter()
|
||||
for {
|
||||
entry := iter.next()
|
||||
if entry == nil {
|
||||
break
|
||||
}
|
||||
callbackFn(FunctionCall{This: t, Arguments: []Value{entry.value, entry.key, thisObj}})
|
||||
}
|
||||
|
||||
return _undefined
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_keys(call FunctionCall) Value {
|
||||
return r.createMapIterator(call.This, iterationKindKey)
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_values(call FunctionCall) Value {
|
||||
return r.createMapIterator(call.This, iterationKindValue)
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_getSize(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
mo, ok := thisObj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method get Map.prototype.size called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
return intToValue(int64(mo.m.size))
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_newMap(args []Value, newTarget *Object) *Object {
|
||||
if newTarget == nil {
|
||||
panic(r.needNew("Map"))
|
||||
}
|
||||
proto := r.getPrototypeFromCtor(newTarget, r.global.Map, r.global.MapPrototype)
|
||||
o := &Object{runtime: r}
|
||||
|
||||
mo := &mapObject{}
|
||||
mo.class = classObject
|
||||
mo.val = o
|
||||
mo.extensible = true
|
||||
o.self = mo
|
||||
mo.prototype = proto
|
||||
mo.init()
|
||||
if len(args) > 0 {
|
||||
if arg := args[0]; arg != nil && arg != _undefined && arg != _null {
|
||||
adder := mo.getStr("set", nil)
|
||||
adderFn := toMethod(adder)
|
||||
if adderFn == nil {
|
||||
panic(r.NewTypeError("Map.set in missing"))
|
||||
}
|
||||
iter := r.getIterator(arg, nil)
|
||||
i0 := valueInt(0)
|
||||
i1 := valueInt(1)
|
||||
if adder == r.global.mapAdder {
|
||||
iter.iterate(func(item Value) {
|
||||
itemObj := r.toObject(item)
|
||||
k := nilSafe(itemObj.self.getIdx(i0, nil))
|
||||
v := nilSafe(itemObj.self.getIdx(i1, nil))
|
||||
mo.m.set(k, v)
|
||||
})
|
||||
} else {
|
||||
iter.iterate(func(item Value) {
|
||||
itemObj := r.toObject(item)
|
||||
k := itemObj.self.getIdx(i0, nil)
|
||||
v := itemObj.self.getIdx(i1, nil)
|
||||
adderFn(FunctionCall{This: o, Arguments: []Value{k, v}})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createMapIterator(mapValue Value, kind iterationKind) Value {
|
||||
obj := r.toObject(mapValue)
|
||||
mapObj, ok := obj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Object is not a Map"))
|
||||
}
|
||||
|
||||
o := &Object{runtime: r}
|
||||
|
||||
mi := &mapIterObject{
|
||||
iter: mapObj.m.newIter(),
|
||||
kind: kind,
|
||||
}
|
||||
mi.class = classObject
|
||||
mi.val = o
|
||||
mi.extensible = true
|
||||
o.self = mi
|
||||
mi.prototype = r.getMapIteratorPrototype()
|
||||
mi.init()
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) mapIterProto_next(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
if iter, ok := thisObj.self.(*mapIterObject); ok {
|
||||
return iter.next()
|
||||
}
|
||||
panic(r.NewTypeError("Method Map Iterator.prototype.next called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
|
||||
func (r *Runtime) createMapProto(val *Object) objectImpl {
|
||||
o := newBaseObjectObj(val, r.global.ObjectPrototype, classObject)
|
||||
|
||||
o._putProp("constructor", r.getMap(), true, false, true)
|
||||
o._putProp("clear", r.newNativeFunc(r.mapProto_clear, "clear", 0), true, false, true)
|
||||
r.global.mapAdder = r.newNativeFunc(r.mapProto_set, "set", 2)
|
||||
o._putProp("set", r.global.mapAdder, true, false, true)
|
||||
o._putProp("delete", r.newNativeFunc(r.mapProto_delete, "delete", 1), true, false, true)
|
||||
o._putProp("forEach", r.newNativeFunc(r.mapProto_forEach, "forEach", 1), true, false, true)
|
||||
o._putProp("has", r.newNativeFunc(r.mapProto_has, "has", 1), true, false, true)
|
||||
o._putProp("get", r.newNativeFunc(r.mapProto_get, "get", 1), true, false, true)
|
||||
o.setOwnStr("size", &valueProperty{
|
||||
getterFunc: r.newNativeFunc(r.mapProto_getSize, "get size", 0),
|
||||
accessor: true,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
}, true)
|
||||
o._putProp("keys", r.newNativeFunc(r.mapProto_keys, "keys", 0), true, false, true)
|
||||
o._putProp("values", r.newNativeFunc(r.mapProto_values, "values", 0), true, false, true)
|
||||
|
||||
entriesFunc := r.newNativeFunc(r.mapProto_entries, "entries", 0)
|
||||
o._putProp("entries", entriesFunc, true, false, true)
|
||||
o._putSym(SymIterator, valueProp(entriesFunc, true, false, true))
|
||||
o._putSym(SymToStringTag, valueProp(asciiString(classMap), false, false, true))
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createMap(val *Object) objectImpl {
|
||||
o := r.newNativeConstructOnly(val, r.builtin_newMap, r.getMapPrototype(), "Map", 0)
|
||||
r.putSpeciesReturnThis(o)
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createMapIterProto(val *Object) objectImpl {
|
||||
o := newBaseObjectObj(val, r.getIteratorPrototype(), classObject)
|
||||
|
||||
o._putProp("next", r.newNativeFunc(r.mapIterProto_next, "next", 0), true, false, true)
|
||||
o._putSym(SymToStringTag, valueProp(asciiString(classMapIterator), false, false, true))
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) getMapIteratorPrototype() *Object {
|
||||
var o *Object
|
||||
if o = r.global.MapIteratorPrototype; o == nil {
|
||||
o = &Object{runtime: r}
|
||||
r.global.MapIteratorPrototype = o
|
||||
o.self = r.createMapIterProto(o)
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) getMapPrototype() *Object {
|
||||
ret := r.global.MapPrototype
|
||||
if ret == nil {
|
||||
ret = &Object{runtime: r}
|
||||
r.global.MapPrototype = ret
|
||||
ret.self = r.createMapProto(ret)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (r *Runtime) getMap() *Object {
|
||||
ret := r.global.Map
|
||||
if ret == nil {
|
||||
ret = &Object{runtime: r}
|
||||
r.global.Map = ret
|
||||
ret.self = r.createMap(ret)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
Reference in New Issue
Block a user