Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
ziqian zhang
Grasscutter
Commits
0559cc4e
Commit
0559cc4e
authored
Apr 29, 2022
by
Kengxxiao
Committed by
Melledy
Apr 28, 2022
Browse files
official shop support
parent
027bd28a
Changes
8
Show whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/Config.java
View file @
0559cc4e
...
@@ -72,6 +72,7 @@ public final class Config {
...
@@ -72,6 +72,7 @@ public final class Config {
public
boolean
WatchGacha
=
false
;
public
boolean
WatchGacha
=
false
;
public
int
[]
WelcomeEmotes
=
{
2007
,
1002
,
4010
};
public
int
[]
WelcomeEmotes
=
{
2007
,
1002
,
4010
};
public
String
WelcomeMotd
=
"Welcome to Grasscutter emu"
;
public
String
WelcomeMotd
=
"Welcome to Grasscutter emu"
;
public
boolean
EnableOfficialShop
=
true
;
public
GameRates
Game
=
new
GameRates
();
public
GameRates
Game
=
new
GameRates
();
...
...
src/main/java/emu/grasscutter/data/GameData.java
View file @
0559cc4e
...
@@ -62,8 +62,11 @@ public class GameData {
...
@@ -62,8 +62,11 @@ public class GameData {
private
static
final
Int2ObjectMap
<
RewardData
>
rewardDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
RewardData
>
rewardDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
WorldLevelData
>
worldLevelDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
WorldLevelData
>
worldLevelDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
ShopGoodsData
>
shopGoodsDataMap
=
new
Int2ObjectOpenHashMap
<>();
// Cache
// Cache
private
static
Map
<
Integer
,
List
<
Integer
>>
fetters
=
new
HashMap
<>();
private
static
Map
<
Integer
,
List
<
Integer
>>
fetters
=
new
HashMap
<>();
private
static
Map
<
Integer
,
List
<
ShopGoodsData
>>
shopGoods
=
new
HashMap
<>();
public
static
Int2ObjectMap
<?>
getMapByResourceDef
(
Class
<?>
resourceDefinition
)
{
public
static
Int2ObjectMap
<?>
getMapByResourceDef
(
Class
<?>
resourceDefinition
)
{
Int2ObjectMap
<?>
map
=
null
;
Int2ObjectMap
<?>
map
=
null
;
...
@@ -265,4 +268,16 @@ public class GameData {
...
@@ -265,4 +268,16 @@ public class GameData {
public
static
Int2ObjectMap
<
WorldLevelData
>
getWorldLevelDataMap
()
{
public
static
Int2ObjectMap
<
WorldLevelData
>
getWorldLevelDataMap
()
{
return
worldLevelDataMap
;
return
worldLevelDataMap
;
}
}
public
static
Map
<
Integer
,
List
<
ShopGoodsData
>>
getShopGoodsDataEntries
()
{
if
(
shopGoods
.
isEmpty
())
{
shopGoodsDataMap
.
forEach
((
k
,
v
)
->
{
if
(!
shopGoods
.
containsKey
(
v
.
getShopType
()))
shopGoods
.
put
(
v
.
getShopType
(),
new
ArrayList
<>());
shopGoods
.
get
(
v
.
getShopType
()).
add
(
v
);
});
}
return
shopGoods
;
}
}
}
src/main/java/emu/grasscutter/data/common/ItemParamData.java
View file @
0559cc4e
...
@@ -4,6 +4,12 @@ public class ItemParamData {
...
@@ -4,6 +4,12 @@ public class ItemParamData {
private
int
Id
;
private
int
Id
;
private
int
Count
;
private
int
Count
;
public
ItemParamData
()
{}
public
ItemParamData
(
int
id
,
int
count
)
{
this
.
Id
=
id
;
this
.
Count
=
count
;
}
public
int
getId
()
{
public
int
getId
()
{
return
Id
;
return
Id
;
}
}
...
...
src/main/java/emu/grasscutter/data/def/ShopGoodsData.java
0 → 100644
View file @
0559cc4e
package
emu.grasscutter.data.def
;
import
emu.grasscutter.data.GameResource
;
import
emu.grasscutter.data.ResourceType
;
import
emu.grasscutter.data.common.ItemParamData
;
import
java.util.List
;
@ResourceType
(
name
=
"ShopGoodsExcelConfigData.json"
)
public
class
ShopGoodsData
extends
GameResource
{
private
int
GoodsId
;
private
int
ShopType
;
private
int
ItemId
;
private
int
ItemCount
;
private
int
CostScoin
;
private
int
CostHcoin
;
private
int
CostMcoin
;
private
List
<
ItemParamData
>
CostItems
;
private
int
MinPlayerLevel
;
private
int
MaxPlayerLevel
;
private
int
BuyLimit
;
private
int
SubTabId
;
@Override
public
int
getId
()
{
return
getGoodsId
();
}
public
int
getGoodsId
()
{
return
GoodsId
;
}
public
int
getShopType
()
{
return
ShopType
;
}
public
int
getItemId
()
{
return
ItemId
;
}
public
int
getItemCount
()
{
return
ItemCount
;
}
public
int
getCostScoin
()
{
return
CostScoin
;
}
public
int
getCostHcoin
()
{
return
CostHcoin
;
}
public
int
getCostMcoin
()
{
return
CostMcoin
;
}
public
List
<
ItemParamData
>
getCostItems
()
{
return
CostItems
;
}
public
int
getMinPlayerLevel
()
{
return
MinPlayerLevel
;
}
public
int
getMaxPlayerLevel
()
{
return
MaxPlayerLevel
;
}
public
int
getBuyLimit
()
{
return
BuyLimit
;
}
public
int
getSubTabId
()
{
return
SubTabId
;
}
}
src/main/java/emu/grasscutter/game/shop/ShopInfo.java
View file @
0559cc4e
package
emu.grasscutter.game.shop
;
package
emu.grasscutter.game.shop
;
import
emu.grasscutter.data.common.ItemParamData
;
import
emu.grasscutter.data.common.ItemParamData
;
import
emu.grasscutter.data.def.ShopGoodsData
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
...
@@ -23,6 +24,20 @@ public class ShopInfo {
...
@@ -23,6 +24,20 @@ public class ShopInfo {
private
int
disableType
=
0
;
private
int
disableType
=
0
;
private
int
secondarySheetId
=
0
;
private
int
secondarySheetId
=
0
;
public
ShopInfo
(
ShopGoodsData
sgd
)
{
this
.
goodsId
=
sgd
.
getGoodsId
();
this
.
goodsItem
=
new
ItemParamData
(
sgd
.
getItemId
(),
sgd
.
getItemCount
());
this
.
scoin
=
sgd
.
getCostScoin
();
this
.
mcoin
=
sgd
.
getCostMcoin
();
this
.
hcoin
=
sgd
.
getCostHcoin
();
this
.
buyLimit
=
sgd
.
getBuyLimit
();
this
.
minLevel
=
sgd
.
getMinPlayerLevel
();
this
.
maxLevel
=
sgd
.
getMaxPlayerLevel
();
this
.
costItemList
=
sgd
.
getCostItems
().
stream
().
filter
(
x
->
x
.
getId
()
!=
0
).
map
(
x
->
new
ItemParamData
(
x
.
getId
(),
x
.
getCount
())).
toList
();
this
.
secondarySheetId
=
sgd
.
getSubTabId
();
}
public
int
getHcoin
()
{
public
int
getHcoin
()
{
return
hcoin
;
return
hcoin
;
}
}
...
...
src/main/java/emu/grasscutter/game/shop/ShopManager.java
View file @
0559cc4e
...
@@ -2,12 +2,19 @@ package emu.grasscutter.game.shop;
...
@@ -2,12 +2,19 @@ package emu.grasscutter.game.shop;
import
com.google.gson.reflect.TypeToken
;
import
com.google.gson.reflect.TypeToken
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.common.ItemParamData
;
import
emu.grasscutter.data.def.ShopGoodsData
;
import
emu.grasscutter.net.proto.ItemParamOuterClass
;
import
emu.grasscutter.net.proto.ShopGoodsOuterClass
;
import
emu.grasscutter.server.game.GameServer
;
import
emu.grasscutter.server.game.GameServer
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
import
java.io.FileReader
;
import
java.io.FileReader
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collection
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.List
;
public
class
ShopManager
{
public
class
ShopManager
{
...
@@ -31,12 +38,39 @@ public class ShopManager {
...
@@ -31,12 +38,39 @@ public class ShopManager {
List
<
ShopTable
>
banners
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
TypeToken
.
getParameterized
(
Collection
.
class
,
ShopTable
.
class
).
getType
());
List
<
ShopTable
>
banners
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
TypeToken
.
getParameterized
(
Collection
.
class
,
ShopTable
.
class
).
getType
());
if
(
banners
.
size
()
>
0
)
{
if
(
banners
.
size
()
>
0
)
{
for
(
ShopTable
shopTable
:
banners
)
{
for
(
ShopTable
shopTable
:
banners
)
{
for
(
ShopInfo
cost
:
shopTable
.
getItems
())
{
if
(
cost
.
getCostItemList
()
!=
null
)
{
Iterator
<
ItemParamData
>
iterator
=
cost
.
getCostItemList
().
iterator
();
while
(
iterator
.
hasNext
())
{
ItemParamData
ipd
=
iterator
.
next
();
if
(
ipd
.
getId
()
==
201
)
{
cost
.
setHcoin
(
cost
.
getHcoin
()
+
ipd
.
getCount
());
iterator
.
remove
();
}
if
(
ipd
.
getId
()
==
203
)
{
cost
.
setMcoin
(
cost
.
getMcoin
()
+
ipd
.
getCount
());
iterator
.
remove
();
}
}
}
}
getShopData
().
put
(
shopTable
.
getShopId
(),
shopTable
.
getItems
());
getShopData
().
put
(
shopTable
.
getShopId
(),
shopTable
.
getItems
());
}
}
Grasscutter
.
getLogger
().
info
(
"Shop data successfully loaded."
);
Grasscutter
.
getLogger
().
info
(
"Shop data successfully loaded."
);
}
else
{
}
else
{
Grasscutter
.
getLogger
().
error
(
"Unable to load shop data. Shop data size is 0."
);
Grasscutter
.
getLogger
().
error
(
"Unable to load shop data. Shop data size is 0."
);
}
}
if
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
EnableOfficialShop
)
{
GameData
.
getShopGoodsDataEntries
().
forEach
((
k
,
v
)
->
{
if
(!
getShopData
().
containsKey
(
k
.
intValue
()))
getShopData
().
put
(
k
.
intValue
(),
new
ArrayList
<>());
for
(
ShopGoodsData
sgd
:
v
)
{
var
shopInfo
=
new
ShopInfo
(
sgd
);
getShopData
().
get
(
k
.
intValue
()).
add
(
shopInfo
);
}
});
}
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
// TODO Auto-generated catch block
// TODO Auto-generated catch block
e
.
printStackTrace
();
e
.
printStackTrace
();
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java
View file @
0559cc4e
package
emu.grasscutter.server.packet.recv
;
package
emu.grasscutter.server.packet.recv
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.common.ItemParamData
;
import
emu.grasscutter.game.inventory.GameItem
;
import
emu.grasscutter.game.inventory.GameItem
;
import
emu.grasscutter.game.props.ActionReason
;
import
emu.grasscutter.game.props.ActionReason
;
import
emu.grasscutter.game.props.PlayerProperty
;
import
emu.grasscutter.game.props.PlayerProperty
;
import
emu.grasscutter.game.shop.ShopInfo
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
...
@@ -16,6 +18,7 @@ import emu.grasscutter.server.packet.send.PacketStoreItemChangeNotify;
...
@@ -16,6 +18,7 @@ import emu.grasscutter.server.packet.send.PacketStoreItemChangeNotify;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Optional
;
import
java.util.Optional
;
@Opcodes
(
PacketOpcodes
.
BuyGoodsReq
)
@Opcodes
(
PacketOpcodes
.
BuyGoodsReq
)
...
@@ -24,8 +27,18 @@ public class HandlerBuyGoodsReq extends PacketHandler {
...
@@ -24,8 +27,18 @@ public class HandlerBuyGoodsReq extends PacketHandler {
@Override
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
BuyGoodsReqOuterClass
.
BuyGoodsReq
buyGoodsReq
=
BuyGoodsReqOuterClass
.
BuyGoodsReq
.
parseFrom
(
payload
);
BuyGoodsReqOuterClass
.
BuyGoodsReq
buyGoodsReq
=
BuyGoodsReqOuterClass
.
BuyGoodsReq
.
parseFrom
(
payload
);
List
<
ShopInfo
>
configShop
=
session
.
getServer
().
getShopManager
().
getShopData
().
get
(
buyGoodsReq
.
getShopType
());
if
(
configShop
==
null
)
return
;
// Don't trust your users' input
List
<
Integer
>
targetShopGoodsId
=
buyGoodsReq
.
getGoodsListList
().
stream
().
map
(
ShopGoodsOuterClass
.
ShopGoods
::
getGoodsId
).
toList
();
for
(
int
goodsId
:
targetShopGoodsId
)
{
Optional
<
ShopInfo
>
sg2
=
configShop
.
stream
().
filter
(
x
->
x
.
getGoodsId
()
==
goodsId
).
findFirst
();
if
(
sg2
.
isEmpty
())
continue
;
ShopInfo
sg
=
sg2
.
get
();
for
(
ShopGoodsOuterClass
.
ShopGoods
sg
:
buyGoodsReq
.
getGoodsListList
())
{
if
(
sg
.
getScoin
()
>
0
&&
session
.
getPlayer
().
getMora
()
<
buyGoodsReq
.
getBoughtNum
()
*
sg
.
getScoin
())
{
if
(
sg
.
getScoin
()
>
0
&&
session
.
getPlayer
().
getMora
()
<
buyGoodsReq
.
getBoughtNum
()
*
sg
.
getScoin
())
{
return
;
return
;
}
}
...
@@ -37,12 +50,14 @@ public class HandlerBuyGoodsReq extends PacketHandler {
...
@@ -37,12 +50,14 @@ public class HandlerBuyGoodsReq extends PacketHandler {
}
}
HashMap
<
GameItem
,
Integer
>
itemsCache
=
new
HashMap
<>();
HashMap
<
GameItem
,
Integer
>
itemsCache
=
new
HashMap
<>();
for
(
ItemParamOuterClass
.
ItemParam
p
:
sg
.
getCostItemListList
())
{
if
(
sg
.
getCostItemList
()
!=
null
)
{
Optional
<
GameItem
>
invItem
=
session
.
getPlayer
().
getInventory
().
getItems
().
values
().
stream
().
filter
(
x
->
x
.
getItemId
()
==
p
.
getItemId
()).
findFirst
();
for
(
ItemParamData
p
:
sg
.
getCostItemList
())
{
Optional
<
GameItem
>
invItem
=
session
.
getPlayer
().
getInventory
().
getItems
().
values
().
stream
().
filter
(
x
->
x
.
getItemId
()
==
p
.
getId
()).
findFirst
();
if
(
invItem
.
isEmpty
()
||
invItem
.
get
().
getCount
()
<
p
.
getCount
())
if
(
invItem
.
isEmpty
()
||
invItem
.
get
().
getCount
()
<
p
.
getCount
())
return
;
return
;
itemsCache
.
put
(
invItem
.
get
(),
p
.
getCount
()
*
buyGoodsReq
.
getBoughtNum
());
itemsCache
.
put
(
invItem
.
get
(),
p
.
getCount
()
*
buyGoodsReq
.
getBoughtNum
());
}
}
}
session
.
getPlayer
().
setMora
(
session
.
getPlayer
().
getMora
()
-
buyGoodsReq
.
getBoughtNum
()
*
sg
.
getScoin
());
session
.
getPlayer
().
setMora
(
session
.
getPlayer
().
getMora
()
-
buyGoodsReq
.
getBoughtNum
()
*
sg
.
getScoin
());
session
.
getPlayer
().
setPrimogems
(
session
.
getPlayer
().
getPrimogems
()
-
buyGoodsReq
.
getBoughtNum
()
*
sg
.
getHcoin
());
session
.
getPlayer
().
setPrimogems
(
session
.
getPlayer
().
getPrimogems
()
-
buyGoodsReq
.
getBoughtNum
()
*
sg
.
getHcoin
());
...
@@ -56,10 +71,10 @@ public class HandlerBuyGoodsReq extends PacketHandler {
...
@@ -56,10 +71,10 @@ public class HandlerBuyGoodsReq extends PacketHandler {
}
}
session
.
getPlayer
().
addShopLimit
(
sg
.
getGoodsId
(),
buyGoodsReq
.
getBoughtNum
());
session
.
getPlayer
().
addShopLimit
(
sg
.
getGoodsId
(),
buyGoodsReq
.
getBoughtNum
());
GameItem
item
=
new
GameItem
(
GameData
.
getItemDataMap
().
get
(
sg
.
getGoodsItem
().
getI
temI
d
()));
GameItem
item
=
new
GameItem
(
GameData
.
getItemDataMap
().
get
(
sg
.
getGoodsItem
().
getId
()));
item
.
setCount
(
buyGoodsReq
.
getBoughtNum
()
*
sg
.
getGoodsItem
().
getCount
());
item
.
setCount
(
buyGoodsReq
.
getBoughtNum
()
*
sg
.
getGoodsItem
().
getCount
());
session
.
getPlayer
().
getInventory
().
addItem
(
item
,
ActionReason
.
Shop
,
true
);
// fix: not notify when got virtual item from shop
session
.
getPlayer
().
getInventory
().
addItem
(
item
,
ActionReason
.
Shop
,
true
);
// fix: not notify when got virtual item from shop
session
.
send
(
new
PacketBuyGoodsRsp
(
buyGoodsReq
.
getShopType
(),
session
.
getPlayer
().
getGoodsLimitNum
(
sg
.
getGoodsId
()),
sg
));
session
.
send
(
new
PacketBuyGoodsRsp
(
buyGoodsReq
.
getShopType
(),
session
.
getPlayer
().
getGoodsLimitNum
(
sg
.
getGoodsId
()),
buyGoodsReq
.
getGoodsListList
().
stream
().
filter
(
x
->
x
.
getGoodsId
()
==
goodsId
).
findFirst
().
get
()
));
}
}
session
.
getPlayer
().
save
();
session
.
getPlayer
().
save
();
...
...
src/main/java/emu/grasscutter/server/packet/send/PacketGetShopRsp.java
View file @
0559cc4e
package
emu.grasscutter.server.packet.send
;
package
emu.grasscutter.server.packet.send
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.def.ShopGoodsData
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.game.shop.ShopInfo
;
import
emu.grasscutter.game.shop.ShopInfo
;
import
emu.grasscutter.game.shop.ShopManager
;
import
emu.grasscutter.game.shop.ShopManager
;
...
@@ -43,13 +45,15 @@ public class PacketGetShopRsp extends BasePacket {
...
@@ -43,13 +45,15 @@ public class PacketGetShopRsp extends BasePacket {
.
setNextRefreshTime
(
info
.
getNextRefreshTime
())
.
setNextRefreshTime
(
info
.
getNextRefreshTime
())
.
setMinLevel
(
info
.
getMinLevel
())
.
setMinLevel
(
info
.
getMinLevel
())
.
setMaxLevel
(
info
.
getMaxLevel
())
.
setMaxLevel
(
info
.
getMaxLevel
())
.
addAllPreGoodsIdList
(
info
.
getPreGoodsIdList
())
.
setMcoin
(
info
.
getMcoin
())
.
setMcoin
(
info
.
getMcoin
())
.
setDisableType
(
info
.
getDisableType
())
.
setDisableType
(
info
.
getDisableType
())
.
setSecondarySheetId
(
info
.
getSecondarySheetId
());
.
setSecondarySheetId
(
info
.
getSecondarySheetId
());
if
(
info
.
getCostItemList
()
!=
null
)
{
if
(
info
.
getCostItemList
()
!=
null
)
{
goods
.
addAllCostItemList
(
info
.
getCostItemList
().
stream
().
map
(
x
->
ItemParamOuterClass
.
ItemParam
.
newBuilder
().
setItemId
(
x
.
getId
()).
setCount
(
x
.
getCount
()).
build
()).
collect
(
Collectors
.
toList
()));
goods
.
addAllCostItemList
(
info
.
getCostItemList
().
stream
().
map
(
x
->
ItemParamOuterClass
.
ItemParam
.
newBuilder
().
setItemId
(
x
.
getId
()).
setCount
(
x
.
getCount
()).
build
()).
collect
(
Collectors
.
toList
()));
}
}
if
(
info
.
getPreGoodsIdList
()
!=
null
)
{
goods
.
addAllPreGoodsIdList
(
info
.
getPreGoodsIdList
());
}
goodsList
.
add
(
goods
.
build
());
goodsList
.
add
(
goods
.
build
());
}
}
shop
.
addAllGoodsList
(
goodsList
);
shop
.
addAllGoodsList
(
goodsList
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment