refactor(common): 重构 Conn 实体并优化地图进入逻辑
- 优化 Conn 实体的 SendPack 方法,提高代码复用性 - 添加 goja 模块到 go.work 文件 - 重构地图进入逻辑,增加玩家广播和刷怪功能 - 调整 OutInfo 结构中的 Vip 和 Viped 字段类型 - 简化 MonsterRefresh 结构体定义
This commit is contained in:
343
common/utils/goja/object_goslice.go
Normal file
343
common/utils/goja/object_goslice.go
Normal file
@@ -0,0 +1,343 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/bits"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
type objectGoSlice struct {
|
||||
baseObject
|
||||
data *[]interface{}
|
||||
lengthProp valueProperty
|
||||
origIsPtr bool
|
||||
}
|
||||
|
||||
func (r *Runtime) newObjectGoSlice(data *[]interface{}, isPtr bool) *objectGoSlice {
|
||||
obj := &Object{runtime: r}
|
||||
a := &objectGoSlice{
|
||||
baseObject: baseObject{
|
||||
val: obj,
|
||||
},
|
||||
data: data,
|
||||
origIsPtr: isPtr,
|
||||
}
|
||||
obj.self = a
|
||||
a.init()
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) init() {
|
||||
o.baseObject.init()
|
||||
o.class = classArray
|
||||
o.prototype = o.val.runtime.getArrayPrototype()
|
||||
o.lengthProp.writable = true
|
||||
o.extensible = true
|
||||
o.baseObject._put("length", &o.lengthProp)
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) updateLen() {
|
||||
o.lengthProp.value = intToValue(int64(len(*o.data)))
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) _getIdx(idx int) Value {
|
||||
return o.val.runtime.ToValue((*o.data)[idx])
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) getStr(name unistring.String, receiver Value) Value {
|
||||
var ownProp Value
|
||||
if idx := strToGoIdx(name); idx >= 0 && idx < len(*o.data) {
|
||||
ownProp = o._getIdx(idx)
|
||||
} else if name == "length" {
|
||||
o.updateLen()
|
||||
ownProp = &o.lengthProp
|
||||
}
|
||||
|
||||
return o.getStrWithOwnProp(ownProp, name, receiver)
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) getIdx(idx valueInt, receiver Value) Value {
|
||||
if idx := int64(idx); idx >= 0 && idx < int64(len(*o.data)) {
|
||||
return o._getIdx(int(idx))
|
||||
}
|
||||
if o.prototype != nil {
|
||||
if receiver == nil {
|
||||
return o.prototype.self.getIdx(idx, o.val)
|
||||
}
|
||||
return o.prototype.self.getIdx(idx, receiver)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) getOwnPropStr(name unistring.String) Value {
|
||||
if idx := strToGoIdx(name); idx >= 0 {
|
||||
if idx < len(*o.data) {
|
||||
return &valueProperty{
|
||||
value: o._getIdx(idx),
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if name == "length" {
|
||||
o.updateLen()
|
||||
return &o.lengthProp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) getOwnPropIdx(idx valueInt) Value {
|
||||
if idx := int64(idx); idx >= 0 && idx < int64(len(*o.data)) {
|
||||
return &valueProperty{
|
||||
value: o._getIdx(int(idx)),
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) grow(size int) {
|
||||
oldcap := cap(*o.data)
|
||||
if oldcap < size {
|
||||
n := make([]interface{}, size, growCap(size, len(*o.data), oldcap))
|
||||
copy(n, *o.data)
|
||||
*o.data = n
|
||||
} else {
|
||||
tail := (*o.data)[len(*o.data):size]
|
||||
for k := range tail {
|
||||
tail[k] = nil
|
||||
}
|
||||
*o.data = (*o.data)[:size]
|
||||
}
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) shrink(size int) {
|
||||
tail := (*o.data)[size:]
|
||||
for k := range tail {
|
||||
tail[k] = nil
|
||||
}
|
||||
*o.data = (*o.data)[:size]
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) putIdx(idx int, v Value, throw bool) {
|
||||
if idx >= len(*o.data) {
|
||||
o.grow(idx + 1)
|
||||
}
|
||||
(*o.data)[idx] = v.Export()
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) putLength(v uint32, throw bool) bool {
|
||||
if bits.UintSize == 32 && v > math.MaxInt32 {
|
||||
panic(rangeError("Integer value overflows 32-bit int"))
|
||||
}
|
||||
newLen := int(v)
|
||||
curLen := len(*o.data)
|
||||
if newLen > curLen {
|
||||
o.grow(newLen)
|
||||
} else if newLen < curLen {
|
||||
o.shrink(newLen)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) setOwnIdx(idx valueInt, val Value, throw bool) bool {
|
||||
if i := toIntStrict(int64(idx)); i >= 0 {
|
||||
if i >= len(*o.data) {
|
||||
if res, ok := o._setForeignIdx(idx, nil, val, o.val, throw); ok {
|
||||
return res
|
||||
}
|
||||
}
|
||||
o.putIdx(i, val, throw)
|
||||
} else {
|
||||
name := idx.string()
|
||||
if res, ok := o._setForeignStr(name, nil, val, o.val, throw); !ok {
|
||||
o.val.runtime.typeErrorResult(throw, "Can't set property '%s' on Go slice", name)
|
||||
return false
|
||||
} else {
|
||||
return res
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) setOwnStr(name unistring.String, val Value, throw bool) bool {
|
||||
if idx := strToGoIdx(name); idx >= 0 {
|
||||
if idx >= len(*o.data) {
|
||||
if res, ok := o._setForeignStr(name, nil, val, o.val, throw); ok {
|
||||
return res
|
||||
}
|
||||
}
|
||||
o.putIdx(idx, val, throw)
|
||||
} else {
|
||||
if name == "length" {
|
||||
return o.putLength(o.val.runtime.toLengthUint32(val), throw)
|
||||
}
|
||||
if res, ok := o._setForeignStr(name, nil, val, o.val, throw); !ok {
|
||||
o.val.runtime.typeErrorResult(throw, "Can't set property '%s' on Go slice", name)
|
||||
return false
|
||||
} else {
|
||||
return res
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) setForeignIdx(idx valueInt, val, receiver Value, throw bool) (bool, bool) {
|
||||
return o._setForeignIdx(idx, trueValIfPresent(o.hasOwnPropertyIdx(idx)), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
|
||||
return o._setForeignStr(name, trueValIfPresent(o.hasOwnPropertyStr(name)), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) hasOwnPropertyIdx(idx valueInt) bool {
|
||||
if idx := int64(idx); idx >= 0 {
|
||||
return idx < int64(len(*o.data))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) hasOwnPropertyStr(name unistring.String) bool {
|
||||
if idx := strToIdx64(name); idx >= 0 {
|
||||
return idx < int64(len(*o.data))
|
||||
}
|
||||
return name == "length"
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool {
|
||||
if i := toIntStrict(int64(idx)); i >= 0 {
|
||||
if !o.val.runtime.checkHostObjectPropertyDescr(idx.string(), descr, throw) {
|
||||
return false
|
||||
}
|
||||
val := descr.Value
|
||||
if val == nil {
|
||||
val = _undefined
|
||||
}
|
||||
o.putIdx(i, val, throw)
|
||||
return true
|
||||
}
|
||||
o.val.runtime.typeErrorResult(throw, "Cannot define property '%d' on a Go slice", idx)
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
|
||||
if idx := strToGoIdx(name); idx >= 0 {
|
||||
if !o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) {
|
||||
return false
|
||||
}
|
||||
val := descr.Value
|
||||
if val == nil {
|
||||
val = _undefined
|
||||
}
|
||||
o.putIdx(idx, val, throw)
|
||||
return true
|
||||
}
|
||||
if name == "length" {
|
||||
return o.val.runtime.defineArrayLength(&o.lengthProp, descr, o.putLength, throw)
|
||||
}
|
||||
o.val.runtime.typeErrorResult(throw, "Cannot define property '%s' on a Go slice", name)
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) _deleteIdx(idx int64) {
|
||||
if idx < int64(len(*o.data)) {
|
||||
(*o.data)[idx] = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) deleteStr(name unistring.String, throw bool) bool {
|
||||
if idx := strToIdx64(name); idx >= 0 {
|
||||
o._deleteIdx(idx)
|
||||
return true
|
||||
}
|
||||
return o.baseObject.deleteStr(name, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) deleteIdx(i valueInt, throw bool) bool {
|
||||
idx := int64(i)
|
||||
if idx >= 0 {
|
||||
o._deleteIdx(idx)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type goslicePropIter struct {
|
||||
o *objectGoSlice
|
||||
idx, limit int
|
||||
}
|
||||
|
||||
func (i *goslicePropIter) next() (propIterItem, iterNextFunc) {
|
||||
if i.idx < i.limit && i.idx < len(*i.o.data) {
|
||||
name := strconv.Itoa(i.idx)
|
||||
i.idx++
|
||||
return propIterItem{name: newStringValue(name), enumerable: _ENUM_TRUE}, i.next
|
||||
}
|
||||
|
||||
return propIterItem{}, nil
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) iterateStringKeys() iterNextFunc {
|
||||
return (&goslicePropIter{
|
||||
o: o,
|
||||
limit: len(*o.data),
|
||||
}).next
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) stringKeys(_ bool, accum []Value) []Value {
|
||||
for i := range *o.data {
|
||||
accum = append(accum, asciiString(strconv.Itoa(i)))
|
||||
}
|
||||
|
||||
return accum
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) export(*objectExportCtx) interface{} {
|
||||
if o.origIsPtr {
|
||||
return o.data
|
||||
}
|
||||
return *o.data
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) exportType() reflect.Type {
|
||||
if o.origIsPtr {
|
||||
return reflectTypeArrayPtr
|
||||
}
|
||||
return reflectTypeArray
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) equal(other objectImpl) bool {
|
||||
if other, ok := other.(*objectGoSlice); ok {
|
||||
return o.data == other.data
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) esValue() Value {
|
||||
return o.val
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) reflectValue() reflect.Value {
|
||||
return reflect.ValueOf(o.data).Elem()
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) setReflectValue(value reflect.Value) {
|
||||
o.data = value.Addr().Interface().(*[]interface{})
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) sortLen() int {
|
||||
return len(*o.data)
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) sortGet(i int) Value {
|
||||
return o.getIdx(valueInt(i), nil)
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) swap(i int, j int) {
|
||||
(*o.data)[i], (*o.data)[j] = (*o.data)[j], (*o.data)[i]
|
||||
}
|
||||
Reference in New Issue
Block a user