diff --git a/bin/json/game_equipenchanting.json b/bin/json/game_equipenchanting.json
new file mode 100644
index 000000000..74da40f65
--- /dev/null
+++ b/bin/json/game_equipenchanting.json
@@ -0,0 +1,268 @@
+[
+ {
+ "item": "40001",
+ "suittype": 1,
+ "attrkey": "atk",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40002",
+ "suittype": 1,
+ "attrkey": "atk",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40003",
+ "suittype": 1,
+ "attrkey": "def",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40004",
+ "suittype": 1,
+ "attrkey": "hp",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40005",
+ "suittype": 1,
+ "attrkey": "atk",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40006",
+ "suittype": 1,
+ "attrkey": "atk",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40007",
+ "suittype": 1,
+ "attrkey": "def",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40008",
+ "suittype": 1,
+ "attrkey": "hp",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40009",
+ "suittype": 1,
+ "attrkey": "atk",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40010",
+ "suittype": 1,
+ "attrkey": "atk",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40011",
+ "suittype": 1,
+ "attrkey": "def",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40012",
+ "suittype": 1,
+ "attrkey": "hp",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40013",
+ "suittype": 1,
+ "attrkey": "atk",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40014",
+ "suittype": 1,
+ "attrkey": "atk",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40015",
+ "suittype": 1,
+ "attrkey": "def",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40016",
+ "suittype": 1,
+ "attrkey": "hp",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40017",
+ "suittype": 1,
+ "attrkey": "atk",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40018",
+ "suittype": 1,
+ "attrkey": "atk",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ },
+ {
+ "item": "40019",
+ "suittype": 1,
+ "attrkey": "def",
+ "attr_mini": 300,
+ "attr_max": 500,
+ "need": [
+ {
+ "a": "attr",
+ "t": "gold",
+ "n": 16851
+ }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/comm/imodule.go b/comm/imodule.go
index 4d760686a..62ee6ac67 100644
--- a/comm/imodule.go
+++ b/comm/imodule.go
@@ -161,6 +161,8 @@ type (
IChat interface {
//推送消息到世界频道
SendWorldChat(msg *pb.DBChat) (code pb.ErrorCode)
+ //推送聊天消息到工会
+ SendUnionChat(msg *pb.DBChat) (code pb.ErrorCode)
//推送消息到用户
SendUserChat(msg *pb.DBChat) (code pb.ErrorCode)
//广播系统消息
diff --git a/modules/chat/module.go b/modules/chat/module.go
index cb77c776d..059bb8893 100644
--- a/modules/chat/module.go
+++ b/modules/chat/module.go
@@ -163,6 +163,37 @@ func (this *Chat) SendWorldChat(msg *pb.DBChat) (code pb.ErrorCode) {
return
}
+//向工会发送聊天消息
+func (this *Chat) SendUnionChat(msg *pb.DBChat) (code pb.ErrorCode) {
+ var (
+ max_chat int32
+ err error
+ )
+ if max_chat, err = this.configure.GetChannelRecordMax(); err != nil {
+ code = pb.ErrorCode_ConfigNoFound
+ this.Errorln(err)
+ return
+ }
+ if this.IsCross() {
+ if err = this.modelChat.sendChatToUnion(msg, max_chat); err != nil {
+ this.Errorln(err)
+ return
+ }
+ } else {
+ if _, err = this.service.AcrossClusterRpcGo(
+ context.Background(),
+ msg.Stag,
+ comm.Service_Worker,
+ string(comm.Rpc_ModuleChatPushChat),
+ msg,
+ nil); err != nil {
+ this.Errorln(err)
+ code = pb.ErrorCode_RpcFuncExecutionError
+ }
+ }
+ return
+}
+
//向个人发送聊天消息
func (this *Chat) SendUserChat(msg *pb.DBChat) (code pb.ErrorCode) {
var (
diff --git a/modules/equipment/api_ench.go b/modules/equipment/api_ench.go
index 12208b631..3cb59e466 100644
--- a/modules/equipment/api_ench.go
+++ b/modules/equipment/api_ench.go
@@ -2,7 +2,10 @@ package equipment
import (
"go_dreamfactory/comm"
+ "go_dreamfactory/lego/sys/log"
"go_dreamfactory/pb"
+ cfg "go_dreamfactory/sys/configure/structs"
+ "math/rand"
"google.golang.org/protobuf/proto"
)
@@ -17,19 +20,40 @@ func (this *apiComp) EnchCheck(session comm.IUserSession, req *pb.EquipmentEnchR
//附魔
func (this *apiComp) Ench(session comm.IUserSession, req *pb.EquipmentEnchReq) (code pb.ErrorCode, data proto.Message) {
- // var (
- // equip *pb.DB_Equipment
- // err error
- // )
+ var (
+ equip *pb.DB_Equipment
+ conf *cfg.GameEquipEnchantingData
+ AttrValue int32
+ err error
+ )
if code = this.EnchCheck(session, req); code != pb.ErrorCode_Success {
return
}
- // if equip, err = this.module.modelEquipment.QueryUserEquipmentsById(session.GetUserId(), req.Eid); err != nil {
- // this.module.Errorf("Equip reader uid:%s equipment:%s err:%v", session.GetUserId(), req.Eid, err)
- // code = pb.ErrorCode_SystemError
- // return
- // }
-
- session.SendMsg(string(this.module.GetType()), "ench", &pb.EquipmentEnchResp{Issucc: true})
+ if conf, err = this.module.configure.getEquipenchanting(req.Itemid); err != nil {
+ code = pb.ErrorCode_ConfigNoFound
+ return
+ }
+ if equip, err = this.module.modelEquipment.QueryUserEquipmentsById(session.GetUserId(), req.Eid); err != nil {
+ this.module.Errorf("Equip reader uid:%s equipment:%s err:%v", session.GetUserId(), req.Eid, err)
+ code = pb.ErrorCode_SystemError
+ return
+ }
+ if equip.AdverbEntry[req.Index] == nil || equip.AdverbEntry[req.Index].AttrName != conf.Attrkey {
+ code = pb.ErrorCode_ReqParameterError
+ return
+ }
+ AttrValue = rand.Int31n(conf.AttrMax - conf.AttrMini)
+ if AttrValue > equip.AdverbEntry[req.Index].Value {
+ equip.AdverbEntry[req.Index].Value = AttrValue
+ }
+ if err = this.module.modelEquipment.ChangeList(session.GetUserId(), equip.Id, map[string]interface{}{
+ "adverbEntry": equip.AdverbEntry,
+ "isInitialState": false,
+ }); err != nil {
+ log.Errorf("Upgrade err:%v", err)
+ code = pb.ErrorCode_SystemError
+ return
+ }
+ session.SendMsg(string(this.module.GetType()), "ench", &pb.EquipmentEnchResp{Issucc: true, Equipment: equip})
return
}
diff --git a/modules/equipment/configure.go b/modules/equipment/configure.go
index f85735be8..b33472671 100644
--- a/modules/equipment/configure.go
+++ b/modules/equipment/configure.go
@@ -9,12 +9,13 @@ import (
)
const (
- game_equip = "game_equip.json" //装备信息表
- equip_attrlibrary = "game_equipattrlibrary.json" //装备属性配置表
- equip_intensify = "game_equipintensify.json" //装备等级消耗表
- equip_suit = "game_equipsuit.json" //装备套装表
- game_equipcompose = "game_equipcompose.json" //装备锻造
- game_equipattribute = "game_equipattribute.json" //装备技能列表
+ game_equip = "game_equip.json" //装备信息表
+ equip_attrlibrary = "game_equipattrlibrary.json" //装备属性配置表
+ equip_intensify = "game_equipintensify.json" //装备等级消耗表
+ equip_suit = "game_equipsuit.json" //装备套装表
+ game_equipcompose = "game_equipcompose.json" //装备锻造
+ game_equipattribute = "game_equipattribute.json" //装备技能列表
+ game_equipenchanting = "game_equipenchanting.json" //装备附魔
)
///背包配置管理组件
@@ -235,3 +236,22 @@ func (this *configureComp) getEquipAttribute(sid string) (result *cfg.GameEquipA
}
return
}
+
+//获取附魔数据
+func (this *configureComp) getEquipenchanting(id string) (result *cfg.GameEquipEnchantingData, err error) {
+ var (
+ v interface{}
+ ok bool
+ )
+ if v, err = this.GetConfigure(game_equipenchanting); err != nil {
+ this.module.Errorf("err:%v", err)
+ return
+ } else {
+ if result, ok = v.(*cfg.GameEquipEnchanting).GetDataMap()[id]; !ok {
+ err = fmt.Errorf("on found getEquipenchanting id:%s", id)
+ this.module.Errorf("err:%v", err)
+ return
+ }
+ }
+ return
+}
diff --git a/pb/equipment_msg.pb.go b/pb/equipment_msg.pb.go
index 2c05bdb9c..a6a303220 100644
--- a/pb/equipment_msg.pb.go
+++ b/pb/equipment_msg.pb.go
@@ -896,7 +896,9 @@ type EquipmentEnchReq struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- Eid string `protobuf:"bytes,1,opt,name=eid,proto3" json:"eid"`
+ Eid string `protobuf:"bytes,1,opt,name=eid,proto3" json:"eid"`
+ Itemid string `protobuf:"bytes,2,opt,name=itemid,proto3" json:"itemid"`
+ Index int32 `protobuf:"varint,3,opt,name=index,proto3" json:"index"`
}
func (x *EquipmentEnchReq) Reset() {
@@ -938,13 +940,28 @@ func (x *EquipmentEnchReq) GetEid() string {
return ""
}
+func (x *EquipmentEnchReq) GetItemid() string {
+ if x != nil {
+ return x.Itemid
+ }
+ return ""
+}
+
+func (x *EquipmentEnchReq) GetIndex() int32 {
+ if x != nil {
+ return x.Index
+ }
+ return 0
+}
+
//装备附魔 回应
type EquipmentEnchResp struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- Issucc bool `protobuf:"varint,1,opt,name=issucc,proto3" json:"issucc"`
+ Issucc bool `protobuf:"varint,1,opt,name=issucc,proto3" json:"issucc"`
+ Equipment *DB_Equipment `protobuf:"bytes,2,opt,name=Equipment,proto3" json:"Equipment"`
}
func (x *EquipmentEnchResp) Reset() {
@@ -986,6 +1003,13 @@ func (x *EquipmentEnchResp) GetIssucc() bool {
return false
}
+func (x *EquipmentEnchResp) GetEquipment() *DB_Equipment {
+ if x != nil {
+ return x.Equipment
+ }
+ return nil
+}
+
var File_equipment_equipment_msg_proto protoreflect.FileDescriptor
var file_equipment_equipment_msg_proto_rawDesc = []byte{
@@ -1061,14 +1085,19 @@ var file_equipment_equipment_msg_proto_rawDesc = []byte{
0x20, 0x03, 0x28, 0x05, 0x52, 0x04, 0x70, 0x69, 0x64, 0x73, 0x22, 0x32, 0x0a, 0x18, 0x45, 0x71,
0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x57, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69,
0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, 0x63, 0x63,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x63, 0x63, 0x22, 0x24,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x63, 0x63, 0x22, 0x52,
0x0a, 0x10, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x63, 0x68, 0x52,
0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x03, 0x65, 0x69, 0x64, 0x22, 0x2b, 0x0a, 0x11, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e,
- 0x74, 0x45, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x73,
- 0x75, 0x63, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x63,
- 0x63, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x33,
+ 0x03, 0x65, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x74, 0x65, 0x6d, 0x69, 0x64, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x74, 0x65, 0x6d, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05,
+ 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x69, 0x6e, 0x64,
+ 0x65, 0x78, 0x22, 0x58, 0x0a, 0x11, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x45,
+ 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, 0x63,
+ 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x63, 0x63, 0x12,
+ 0x2b, 0x0a, 0x09, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x44, 0x42, 0x5f, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e,
+ 0x74, 0x52, 0x09, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x06, 0x5a, 0x04,
+ 0x2e, 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -1113,11 +1142,12 @@ var file_equipment_equipment_msg_proto_depIdxs = []int32{
19, // 2: EquipmentEquipResp.Equipments:type_name -> DB_Equipment
19, // 3: EquipmentUpgradeResp.Equipment:type_name -> DB_Equipment
20, // 4: EquipmentWashResp.adverbEntry:type_name -> EquipmentAttributeEntry
- 5, // [5:5] is the sub-list for method output_type
- 5, // [5:5] is the sub-list for method input_type
- 5, // [5:5] is the sub-list for extension type_name
- 5, // [5:5] is the sub-list for extension extendee
- 0, // [0:5] is the sub-list for field type_name
+ 19, // 5: EquipmentEnchResp.Equipment:type_name -> DB_Equipment
+ 6, // [6:6] is the sub-list for method output_type
+ 6, // [6:6] is the sub-list for method input_type
+ 6, // [6:6] is the sub-list for extension type_name
+ 6, // [6:6] is the sub-list for extension extendee
+ 0, // [0:6] is the sub-list for field type_name
}
func init() { file_equipment_equipment_msg_proto_init() }
diff --git a/sys/configure/structs/Game.EquipEnchanting.go b/sys/configure/structs/Game.EquipEnchanting.go
new file mode 100644
index 000000000..95f9c7e3f
--- /dev/null
+++ b/sys/configure/structs/Game.EquipEnchanting.go
@@ -0,0 +1,42 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+package cfg
+
+type GameEquipEnchanting struct {
+ _dataMap map[string]*GameEquipEnchantingData
+ _dataList []*GameEquipEnchantingData
+}
+
+func NewGameEquipEnchanting(_buf []map[string]interface{}) (*GameEquipEnchanting, error) {
+ _dataList := make([]*GameEquipEnchantingData, 0, len(_buf))
+ dataMap := make(map[string]*GameEquipEnchantingData)
+ for _, _ele_ := range _buf {
+ if _v, err2 := DeserializeGameEquipEnchantingData(_ele_); err2 != nil {
+ return nil, err2
+ } else {
+ _dataList = append(_dataList, _v)
+ dataMap[_v.Item] = _v
+ }
+ }
+ return &GameEquipEnchanting{_dataList:_dataList, _dataMap:dataMap}, nil
+}
+
+func (table *GameEquipEnchanting) GetDataMap() map[string]*GameEquipEnchantingData {
+ return table._dataMap
+}
+
+func (table *GameEquipEnchanting) GetDataList() []*GameEquipEnchantingData {
+ return table._dataList
+}
+
+func (table *GameEquipEnchanting) Get(key string) *GameEquipEnchantingData {
+ return table._dataMap[key]
+}
+
+
diff --git a/sys/configure/structs/Game.EquipEnchantingData.go b/sys/configure/structs/Game.EquipEnchantingData.go
new file mode 100644
index 000000000..09c0e098b
--- /dev/null
+++ b/sys/configure/structs/Game.EquipEnchantingData.go
@@ -0,0 +1,58 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+package cfg
+
+import "errors"
+
+type GameEquipEnchantingData struct {
+ Item string
+ Suittype int32
+ Attrkey string
+ AttrMini int32
+ AttrMax int32
+ Need []*Gameatn
+}
+
+const TypeId_GameEquipEnchantingData = 1681946759
+
+func (*GameEquipEnchantingData) GetTypeId() int32 {
+ return 1681946759
+}
+
+func (_v *GameEquipEnchantingData)Deserialize(_buf map[string]interface{}) (err error) {
+ { var _ok_ bool; if _v.Item, _ok_ = _buf["item"].(string); !_ok_ { err = errors.New("item error"); return } }
+ { var _ok_ bool; var _tempNum_ float64; if _tempNum_, _ok_ = _buf["suittype"].(float64); !_ok_ { err = errors.New("suittype error"); return }; _v.Suittype = int32(_tempNum_) }
+ { var _ok_ bool; if _v.Attrkey, _ok_ = _buf["attrkey"].(string); !_ok_ { err = errors.New("attrkey error"); return } }
+ { var _ok_ bool; var _tempNum_ float64; if _tempNum_, _ok_ = _buf["attr_mini"].(float64); !_ok_ { err = errors.New("attr_mini error"); return }; _v.AttrMini = int32(_tempNum_) }
+ { var _ok_ bool; var _tempNum_ float64; if _tempNum_, _ok_ = _buf["attr_max"].(float64); !_ok_ { err = errors.New("attr_max error"); return }; _v.AttrMax = int32(_tempNum_) }
+ {
+ var _arr_ []interface{}
+ var _ok_ bool
+ if _arr_, _ok_ = _buf["need"].([]interface{}); !_ok_ { err = errors.New("need error"); return }
+
+ _v.Need = make([]*Gameatn, 0, len(_arr_))
+
+ for _, _e_ := range _arr_ {
+ var _list_v_ *Gameatn
+ { var _ok_ bool; var _x_ map[string]interface{}; if _x_, _ok_ = _e_.(map[string]interface{}); !_ok_ { err = errors.New("_list_v_ error"); return }; if _list_v_, err = DeserializeGameatn(_x_); err != nil { return } }
+ _v.Need = append(_v.Need, _list_v_)
+ }
+ }
+
+ return
+}
+
+func DeserializeGameEquipEnchantingData(_buf map[string]interface{}) (*GameEquipEnchantingData, error) {
+ v := &GameEquipEnchantingData{}
+ if err := v.Deserialize(_buf); err == nil {
+ return v, nil
+ } else {
+ return nil, err
+ }
+}