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
7925d1cd
Commit
7925d1cd
authored
Apr 17, 2022
by
Melledy
Browse files
Initial commit
parents
Changes
354
Show whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/GenshinConstants.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter
;
import
java.util.Arrays
;
import
emu.grasscutter.game.props.OpenState
;
import
emu.grasscutter.utils.Position
;
import
emu.grasscutter.utils.Utils
;
public
class
GenshinConstants
{
public
static
String
VERSION
=
"2.6.0"
;
public
static
final
int
MAX_TEAMS
=
4
;
public
static
final
int
MAX_AVATARS_IN_TEAM
=
4
;
public
static
final
int
LIMIT_WEAPON
=
2000
;
public
static
final
int
LIMIT_RELIC
=
2000
;
public
static
final
int
LIMIT_MATERIAL
=
2000
;
public
static
final
int
LIMIT_FURNITURE
=
2000
;
public
static
final
int
LIMIT_ALL
=
30000
;
public
static
final
int
MAIN_CHARACTER_MALE
=
10000005
;
public
static
final
int
MAIN_CHARACTER_FEMALE
=
10000007
;
public
static
final
Position
START_POSITION
=
new
Position
(
2747
,
194
,
-
1719
);
public
static
final
int
MAX_FRIENDS
=
45
;
public
static
final
int
MAX_FRIEND_REQUESTS
=
50
;
public
static
final
int
SERVER_CONSOLE_UID
=
99
;
// uid of the fake player used for commands
// Default entity ability hashes
public
static
final
String
[]
DEFAULT_ABILITY_STRINGS
=
{
"Avatar_DefaultAbility_VisionReplaceDieInvincible"
,
"Avatar_DefaultAbility_AvartarInShaderChange"
,
"Avatar_SprintBS_Invincible"
,
"Avatar_Freeze_Duration_Reducer"
,
"Avatar_Attack_ReviveEnergy"
,
"Avatar_Component_Initializer"
,
"Avatar_FallAnthem_Achievement_Listener"
};
public
static
final
int
[]
DEFAULT_ABILITY_HASHES
=
Arrays
.
stream
(
DEFAULT_ABILITY_STRINGS
).
mapToInt
(
Utils:
:
abilityHash
).
toArray
();
public
static
final
int
DEFAULT_ABILITY_NAME
=
Utils
.
abilityHash
(
"Default"
);
}
src/main/java/emu/grasscutter/Grasscutter.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter
;
import
java.io.BufferedReader
;
import
java.io.File
;
import
java.io.FileReader
;
import
java.io.FileWriter
;
import
java.io.InputStreamReader
;
import
java.net.InetSocketAddress
;
import
java.util.Arrays
;
import
org.slf4j.LoggerFactory
;
import
com.google.gson.Gson
;
import
com.google.gson.GsonBuilder
;
import
ch.qos.logback.classic.Logger
;
import
emu.grasscutter.commands.ServerCommands
;
import
emu.grasscutter.data.ResourceLoader
;
import
emu.grasscutter.database.DatabaseManager
;
import
emu.grasscutter.server.dispatch.DispatchServer
;
import
emu.grasscutter.server.game.GameServer
;
import
emu.grasscutter.tools.Tools
;
import
emu.grasscutter.utils.Crypto
;
public
class
Grasscutter
{
private
static
Logger
log
=
(
Logger
)
LoggerFactory
.
getLogger
(
Grasscutter
.
class
);
private
static
Config
config
;
private
static
Gson
gson
=
new
GsonBuilder
().
setPrettyPrinting
().
create
();
private
static
File
configFile
=
new
File
(
"./config.json"
);
public
static
RunMode
MODE
=
RunMode
.
BOTH
;
private
static
DispatchServer
dispatchServer
;
private
static
GameServer
gameServer
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
Grasscutter
.
loadConfig
();
Crypto
.
loadKeys
();
for
(
String
arg
:
args
)
{
switch
(
arg
.
toLowerCase
())
{
case
"-auth"
:
MODE
=
RunMode
.
AUTH
;
break
;
case
"-game"
:
MODE
=
RunMode
.
GAME
;
break
;
case
"-handbook"
:
Tools
.
createGmHandbook
();
return
;
}
}
// Startup
Grasscutter
.
getLogger
().
info
(
"Grasscutter Emu"
);
// Load resource files
ResourceLoader
.
loadAll
();
// Database
DatabaseManager
.
initialize
();
// Run servers
dispatchServer
=
new
DispatchServer
();
dispatchServer
.
start
();
gameServer
=
new
GameServer
(
new
InetSocketAddress
(
getConfig
().
GameServerIp
,
getConfig
().
GameServerPort
));
gameServer
.
start
();
startConsole
();
}
public
static
Config
getConfig
()
{
return
config
;
}
public
static
Logger
getLogger
()
{
return
log
;
}
public
static
Gson
getGsonFactory
()
{
return
gson
;
}
public
static
DispatchServer
getDispatchServer
()
{
return
dispatchServer
;
}
public
static
GameServer
getGameServer
()
{
return
gameServer
;
}
public
static
void
loadConfig
()
{
try
(
FileReader
file
=
new
FileReader
(
configFile
))
{
config
=
gson
.
fromJson
(
file
,
Config
.
class
);
}
catch
(
Exception
e
)
{
Grasscutter
.
config
=
new
Config
();
}
saveConfig
();
}
public
static
void
saveConfig
()
{
try
(
FileWriter
file
=
new
FileWriter
(
configFile
))
{
file
.
write
(
gson
.
toJson
(
config
));
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Config save error"
);
}
}
public
static
void
startConsole
()
{
String
input
;
try
(
BufferedReader
br
=
new
BufferedReader
(
new
InputStreamReader
(
System
.
in
)))
{
while
((
input
=
br
.
readLine
())
!=
null
)
{
ServerCommands
.
handle
(
input
);
}
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Console error:"
,
e
);
}
}
public
enum
RunMode
{
BOTH
,
AUTH
,
GAME
}
}
src/main/java/emu/grasscutter/commands/Command.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.commands
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
Command
{
public
String
[]
aliases
()
default
""
;
public
int
gmLevel
()
default
1
;
public
String
helpText
()
default
""
;
}
src/main/java/emu/grasscutter/commands/PlayerCommands.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.commands
;
import
java.lang.reflect.Modifier
;
import
java.util.HashMap
;
import
java.util.LinkedList
;
import
java.util.List
;
import
emu.grasscutter.data.GenshinData
;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.data.def.MonsterData
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.avatar.GenshinAvatar
;
import
emu.grasscutter.game.entity.EntityAvatar
;
import
emu.grasscutter.game.entity.EntityItem
;
import
emu.grasscutter.game.entity.EntityMonster
;
import
emu.grasscutter.game.entity.GenshinEntity
;
import
emu.grasscutter.game.inventory.GenshinItem
;
import
emu.grasscutter.game.inventory.ItemType
;
import
emu.grasscutter.game.props.ActionReason
;
import
emu.grasscutter.game.props.FightProperty
;
import
emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify
;
import
emu.grasscutter.server.packet.send.PacketItemAddHintNotify
;
import
emu.grasscutter.utils.Position
;
public
class
PlayerCommands
{
private
static
HashMap
<
String
,
PlayerCommand
>
list
=
new
HashMap
<
String
,
PlayerCommand
>();
static
{
try
{
// Look for classes
for
(
Class
<?>
cls
:
PlayerCommands
.
class
.
getDeclaredClasses
())
{
// Get non abstract classes
if
(!
Modifier
.
isAbstract
(
cls
.
getModifiers
()))
{
Command
commandAnnotation
=
cls
.
getAnnotation
(
Command
.
class
);
PlayerCommand
command
=
(
PlayerCommand
)
cls
.
newInstance
();
if
(
commandAnnotation
!=
null
)
{
command
.
setLevel
(
commandAnnotation
.
gmLevel
());
for
(
String
alias
:
commandAnnotation
.
aliases
())
{
if
(
alias
.
length
()
==
0
)
{
continue
;
}
String
commandName
=
"!"
+
alias
;
list
.
put
(
commandName
,
command
);
commandName
=
"/"
+
alias
;
list
.
put
(
commandName
,
command
);
}
}
String
commandName
=
"!"
+
cls
.
getSimpleName
().
toLowerCase
();
list
.
put
(
commandName
,
command
);
commandName
=
"/"
+
cls
.
getSimpleName
().
toLowerCase
();
list
.
put
(
commandName
,
command
);
}
}
}
catch
(
Exception
e
)
{
}
}
public
static
void
handle
(
GenshinPlayer
player
,
String
msg
)
{
String
[]
split
=
msg
.
split
(
" "
);
// End if invalid
if
(
split
.
length
==
0
)
{
return
;
}
//
String
first
=
split
[
0
].
toLowerCase
();
PlayerCommand
c
=
PlayerCommands
.
list
.
get
(
first
);
if
(
c
!=
null
)
{
// Level check
if
(
player
.
getGmLevel
()
<
c
.
getLevel
())
{
return
;
}
// Execute
int
len
=
Math
.
min
(
first
.
length
()
+
1
,
msg
.
length
());
c
.
execute
(
player
,
msg
.
substring
(
len
));
}
}
public
static
abstract
class
PlayerCommand
{
// GM level required to use this command
private
int
level
;
protected
int
getLevel
()
{
return
this
.
level
;
}
protected
void
setLevel
(
int
minLevel
)
{
this
.
level
=
minLevel
;
}
// Main
public
abstract
void
execute
(
GenshinPlayer
player
,
String
raw
);
}
// ================ Commands ================
@Command
(
aliases
=
{
"g"
,
"item"
,
"additem"
},
helpText
=
"/give [item id] [count] - Gives {count} amount of {item id}"
)
public
static
class
Give
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
String
[]
split
=
raw
.
split
(
" "
);
int
itemId
=
0
,
count
=
1
;
try
{
itemId
=
Integer
.
parseInt
(
split
[
0
]);
}
catch
(
Exception
e
)
{
itemId
=
0
;
}
try
{
count
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
1
]),
Integer
.
MAX_VALUE
),
1
);
}
catch
(
Exception
e
)
{
count
=
1
;
}
// Give
ItemData
itemData
=
GenshinData
.
getItemDataMap
().
get
(
itemId
);
GenshinItem
item
;
if
(
itemData
==
null
)
{
player
.
dropMessage
(
"Error: Item data not found"
);
return
;
}
if
(
itemData
.
isEquip
())
{
List
<
GenshinItem
>
items
=
new
LinkedList
<>();
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
item
=
new
GenshinItem
(
itemData
);
items
.
add
(
item
);
}
player
.
getInventory
().
addItems
(
items
);
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
items
,
ActionReason
.
SubfieldDrop
));
}
else
{
item
=
new
GenshinItem
(
itemData
,
count
);
player
.
getInventory
().
addItem
(
item
);
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
item
,
ActionReason
.
SubfieldDrop
));
}
}
}
@Command
(
aliases
=
{
"d"
},
helpText
=
"/drop [item id] [count] - Drops {count} amount of {item id}"
)
public
static
class
Drop
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
String
[]
split
=
raw
.
split
(
" "
);
int
itemId
=
0
,
count
=
1
;
try
{
itemId
=
Integer
.
parseInt
(
split
[
0
]);
}
catch
(
Exception
e
)
{
itemId
=
0
;
}
try
{
count
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
1
]),
Integer
.
MAX_VALUE
),
1
);
}
catch
(
Exception
e
)
{
count
=
1
;
}
// Give
ItemData
itemData
=
GenshinData
.
getItemDataMap
().
get
(
itemId
);
if
(
itemData
==
null
)
{
player
.
dropMessage
(
"Error: Item data not found"
);
return
;
}
if
(
itemData
.
isEquip
())
{
float
range
=
(
5
f
+
(.
1
f
*
count
));
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
Position
pos
=
player
.
getPos
().
clone
().
addX
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
)).
addY
(
3
f
).
addZ
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
));
EntityItem
entity
=
new
EntityItem
(
player
.
getWorld
(),
player
,
itemData
,
pos
,
1
);
player
.
getWorld
().
addEntity
(
entity
);
}
}
else
{
EntityItem
entity
=
new
EntityItem
(
player
.
getWorld
(),
player
,
itemData
,
player
.
getPos
().
clone
().
addY
(
3
f
),
count
);
player
.
getWorld
().
addEntity
(
entity
);
}
}
}
@Command
(
helpText
=
"/spawn [monster id] [count] - Creates {count} amount of {item id}"
)
public
static
class
Spawn
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
String
[]
split
=
raw
.
split
(
" "
);
int
monsterId
=
0
,
count
=
1
,
level
=
1
;
try
{
monsterId
=
Integer
.
parseInt
(
split
[
0
]);
}
catch
(
Exception
e
)
{
monsterId
=
0
;
}
try
{
level
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
1
]),
200
),
1
);
}
catch
(
Exception
e
)
{
level
=
1
;
}
try
{
count
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
2
]),
1000
),
1
);
}
catch
(
Exception
e
)
{
count
=
1
;
}
// Give
MonsterData
monsterData
=
GenshinData
.
getMonsterDataMap
().
get
(
monsterId
);
if
(
monsterData
==
null
)
{
player
.
dropMessage
(
"Error: Monster data not found"
);
return
;
}
float
range
=
(
5
f
+
(.
1
f
*
count
));
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
Position
pos
=
player
.
getPos
().
clone
().
addX
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
)).
addY
(
3
f
).
addZ
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
));
EntityMonster
entity
=
new
EntityMonster
(
player
.
getWorld
(),
monsterData
,
pos
,
level
);
player
.
getWorld
().
addEntity
(
entity
);
}
}
}
@Command
(
helpText
=
"/killall"
)
public
static
class
KillAll
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
List
<
GenshinEntity
>
toRemove
=
new
LinkedList
<>();
for
(
GenshinEntity
entity
:
player
.
getWorld
().
getEntities
().
values
())
{
if
(
entity
instanceof
EntityMonster
)
{
toRemove
.
add
(
entity
);
}
}
toRemove
.
forEach
(
e
->
player
.
getWorld
().
killEntity
(
e
,
0
));
}
}
@Command
(
helpText
=
"/resetconst - Resets all constellations for the currently active character"
)
public
static
class
ResetConst
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
EntityAvatar
entity
=
player
.
getTeamManager
().
getCurrentAvatarEntity
();
if
(
entity
==
null
)
{
return
;
}
GenshinAvatar
avatar
=
entity
.
getAvatar
();
avatar
.
getTalentIdList
().
clear
();
avatar
.
setCoreProudSkillLevel
(
0
);
avatar
.
recalcStats
();
avatar
.
save
();
player
.
dropMessage
(
"Constellations for "
+
entity
.
getAvatar
().
getAvatarData
().
getName
()
+
" have been reset. Please relogin to see changes."
);
}
}
@Command
(
helpText
=
"/godmode - Prevents you from taking damage"
)
public
static
class
Godmode
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
player
.
setGodmode
(!
player
.
hasGodmode
());
player
.
dropMessage
(
"Godmode is now "
+
(
player
.
hasGodmode
()
?
"ON"
:
"OFF"
));
}
}
@Command
(
helpText
=
"/sethp [hp]"
)
public
static
class
Sethp
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
String
[]
split
=
raw
.
split
(
" "
);
int
hp
=
0
;
try
{
hp
=
Math
.
max
(
Integer
.
parseInt
(
split
[
0
]),
1
);
}
catch
(
Exception
e
)
{
hp
=
1
;
}
EntityAvatar
entity
=
player
.
getTeamManager
().
getCurrentAvatarEntity
();
if
(
entity
==
null
)
{
return
;
}
entity
.
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
hp
);
entity
.
getWorld
().
broadcastPacket
(
new
PacketEntityFightPropUpdateNotify
(
entity
,
FightProperty
.
FIGHT_PROP_CUR_HP
));
}
}
@Command
(
aliases
=
{
"clearart"
},
helpText
=
"/clearartifacts"
)
public
static
class
ClearArtifacts
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
List
<
GenshinItem
>
toRemove
=
new
LinkedList
<>();
for
(
GenshinItem
item
:
player
.
getInventory
().
getItems
().
values
())
{
if
(
item
.
getItemType
()
==
ItemType
.
ITEM_RELIQUARY
&&
item
.
getLevel
()
==
1
&&
item
.
getExp
()
==
0
&&
!
item
.
isLocked
()
&&
!
item
.
isEquipped
())
{
toRemove
.
add
(
item
);
}
}
player
.
getInventory
().
removeItems
(
toRemove
);
}
}
}
src/main/java/emu/grasscutter/commands/ServerCommands.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.commands
;
import
java.lang.reflect.Modifier
;
import
java.util.HashMap
;
import
java.util.LinkedList
;
import
java.util.List
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.GenshinData
;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.inventory.GenshinItem
;
import
emu.grasscutter.utils.Crypto
;
import
emu.grasscutter.utils.Utils
;
public
class
ServerCommands
{
private
static
HashMap
<
String
,
ServerCommand
>
list
=
new
HashMap
<>();
static
{
try
{
// Look for classes
for
(
Class
<?>
cls
:
ServerCommands
.
class
.
getDeclaredClasses
())
{
// Get non abstract classes
if
(!
Modifier
.
isAbstract
(
cls
.
getModifiers
()))
{
String
commandName
=
cls
.
getSimpleName
().
toLowerCase
();
list
.
put
(
commandName
,
(
ServerCommand
)
cls
.
newInstance
());
}
}
}
catch
(
Exception
e
)
{
}
}
public
static
void
handle
(
String
msg
)
{
String
[]
split
=
msg
.
split
(
" "
);
// End if invalid
if
(
split
.
length
==
0
)
{
return
;
}
//
String
first
=
split
[
0
].
toLowerCase
();
ServerCommand
c
=
ServerCommands
.
list
.
get
(
first
);
if
(
c
!=
null
)
{
// Execute
int
len
=
Math
.
min
(
first
.
length
()
+
1
,
msg
.
length
());
c
.
execute
(
msg
.
substring
(
len
));
}
}
public
static
abstract
class
ServerCommand
{
public
abstract
void
execute
(
String
raw
);
}
// ================ Commands ================
public
static
class
Reload
extends
ServerCommand
{
@Override
public
void
execute
(
String
raw
)
{
Grasscutter
.
getLogger
().
info
(
"Reloading config."
);
Grasscutter
.
loadConfig
();
Grasscutter
.
getDispatchServer
().
loadQueries
();
Grasscutter
.
getLogger
().
info
(
"Reload complete."
);
}
}
public
static
class
Account
extends
ServerCommand
{
@Override
public
void
execute
(
String
raw
)
{
String
[]
split
=
raw
.
split
(
" "
);
if
(
split
.
length
<
2
)
{
Grasscutter
.
getLogger
().
error
(
"Invalid amount of args"
);
return
;
}
String
command
=
split
[
0
].
toLowerCase
();
String
username
=
split
[
1
];
switch
(
command
)
{
case
"create"
:
if
(
split
.
length
<
2
)
{
Grasscutter
.
getLogger
().
error
(
"Invalid amount of args"
);
return
;
}
int
reservedId
=
0
;
try
{
reservedId
=
Integer
.
parseInt
(
split
[
2
]);
}
catch
(
Exception
e
)
{
reservedId
=
0
;
}
emu
.
grasscutter
.
game
.
Account
account
=
DatabaseHelper
.
createAccountWithId
(
username
,
reservedId
);
if
(
account
!=
null
)
{
Grasscutter
.
getLogger
().
info
(
"Account created"
+
(
reservedId
>
0
?
" with an id of "
+
reservedId
:
""
));
}
else
{
Grasscutter
.
getLogger
().
error
(
"Account already exists"
);
}
break
;
case
"delete"
:
boolean
success
=
DatabaseHelper
.
deleteAccount
(
username
);
if
(
success
)
{
Grasscutter
.
getLogger
().
info
(
"Account deleted"
);
}
break
;
/*
case "setpw":
case "setpass":
case "setpassword":
if (split.length < 3) {
Grasscutter.getLogger().error("Invalid amount of args");
return;
}
account = DatabaseHelper.getAccountByName(username);
if (account == null) {
Grasscutter.getLogger().error("No account found!");
return;
}
token = split[2];
token = PasswordHelper.hashPassword(token);
account.setPassword(token);
DatabaseHelper.saveAccount(account);
Grasscutter.getLogger().info("Password set");
break;
*/
}
}
}
}
src/main/java/emu/grasscutter/data/GenshinData.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.data
;
import
java.lang.reflect.Field
;
import
java.util.HashMap
;
import
java.util.Map
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.utils.Utils
;
import
emu.grasscutter.data.custom.AbilityEmbryoEntry
;
import
emu.grasscutter.data.custom.OpenConfigEntry
;
import
emu.grasscutter.data.def.*
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
public
class
GenshinData
{
// BinOutputs
private
static
final
Int2ObjectMap
<
String
>
abilityHashes
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Map
<
String
,
AbilityEmbryoEntry
>
abilityEmbryos
=
new
HashMap
<>();
private
static
final
Map
<
String
,
OpenConfigEntry
>
openConfigEntries
=
new
HashMap
<>();
// ExcelConfigs
private
static
final
Int2ObjectMap
<
PlayerLevelData
>
playerLevelDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarData
>
avatarDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarLevelData
>
avatarLevelDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarSkillDepotData
>
avatarSkillDepotDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarSkillData
>
avatarSkillDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarCurveData
>
avatarCurveDataMap
=
new
Int2ObjectLinkedOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarPromoteData
>
avatarPromoteDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarTalentData
>
avatarTalentDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
ProudSkillData
>
proudSkillDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
ItemData
>
itemDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
ReliquaryLevelData
>
reliquaryLevelDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
ReliquaryAffixData
>
reliquaryAffixDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
ReliquaryMainPropData
>
reliquaryMainPropDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
ReliquarySetData
>
reliquarySetDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
WeaponLevelData
>
weaponLevelDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
WeaponPromoteData
>
weaponPromoteDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
WeaponCurveData
>
weaponCurveDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
EquipAffixData
>
equipAffixDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
MonsterData
>
monsterDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
NpcData
>
npcDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
GadgetData
>
gadgetDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
MonsterCurveData
>
monsterCurveDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
MonsterDescribeData
>
monsterDescribeDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarFlycloakData
>
avatarFlycloakDataMap
=
new
Int2ObjectLinkedOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarCostumeData
>
avatarCostumeDataMap
=
new
Int2ObjectLinkedOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarCostumeData
>
avatarCostumeDataItemIdMap
=
new
Int2ObjectLinkedOpenHashMap
<>();
public
static
Int2ObjectMap
<?>
getMapByResourceDef
(
Class
<?>
resourceDefinition
)
{
Int2ObjectMap
<?>
map
=
null
;
try
{
Field
field
=
GenshinData
.
class
.
getDeclaredField
(
Utils
.
lowerCaseFirstChar
(
resourceDefinition
.
getSimpleName
())
+
"Map"
);
field
.
setAccessible
(
true
);
map
=
(
Int2ObjectMap
<?>)
field
.
get
(
null
);
field
.
setAccessible
(
false
);
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Error fetching resource map for "
+
resourceDefinition
.
getSimpleName
(),
e
);
}
return
map
;
}
public
static
Int2ObjectMap
<
String
>
getAbilityHashes
()
{
return
abilityHashes
;
}
public
static
Map
<
String
,
AbilityEmbryoEntry
>
getAbilityEmbryoInfo
()
{
return
abilityEmbryos
;
}
public
static
Map
<
String
,
OpenConfigEntry
>
getOpenConfigEntries
()
{
return
openConfigEntries
;
}
public
static
Int2ObjectMap
<
AvatarData
>
getAvatarDataMap
()
{
return
avatarDataMap
;
}
public
static
Int2ObjectMap
<
ItemData
>
getItemDataMap
()
{
return
itemDataMap
;
}
public
static
Int2ObjectMap
<
AvatarSkillDepotData
>
getAvatarSkillDepotDataMap
()
{
return
avatarSkillDepotDataMap
;
}
public
static
Int2ObjectMap
<
AvatarSkillData
>
getAvatarSkillDataMap
()
{
return
avatarSkillDataMap
;
}
public
static
Int2ObjectMap
<
PlayerLevelData
>
getPlayerLevelDataMap
()
{
return
playerLevelDataMap
;
}
public
static
Int2ObjectMap
<
AvatarLevelData
>
getAvatarLevelDataMap
()
{
return
avatarLevelDataMap
;
}
public
static
Int2ObjectMap
<
WeaponLevelData
>
getWeaponLevelDataMap
()
{
return
weaponLevelDataMap
;
}
public
static
Int2ObjectMap
<
ReliquaryAffixData
>
getReliquaryAffixDataMap
()
{
return
reliquaryAffixDataMap
;
}
public
static
Int2ObjectMap
<
ReliquaryMainPropData
>
getReliquaryMainPropDataMap
()
{
return
reliquaryMainPropDataMap
;
}
public
static
Int2ObjectMap
<
WeaponPromoteData
>
getWeaponPromoteDataMap
()
{
return
weaponPromoteDataMap
;
}
public
static
Int2ObjectMap
<
WeaponCurveData
>
getWeaponCurveDataMap
()
{
return
weaponCurveDataMap
;
}
public
static
Int2ObjectMap
<
AvatarCurveData
>
getAvatarCurveDataMap
()
{
return
avatarCurveDataMap
;
}
public
static
int
getRelicExpRequired
(
int
rankLevel
,
int
level
)
{
ReliquaryLevelData
levelData
=
reliquaryLevelDataMap
.
get
((
rankLevel
<<
8
)
+
level
);
return
levelData
!=
null
?
levelData
.
getExp
()
:
0
;
}
public
static
ReliquaryLevelData
getRelicLevelData
(
int
rankLevel
,
int
level
)
{
return
reliquaryLevelDataMap
.
get
((
rankLevel
<<
8
)
+
level
);
}
public
static
WeaponPromoteData
getWeaponPromoteData
(
int
promoteId
,
int
promoteLevel
)
{
return
weaponPromoteDataMap
.
get
((
promoteId
<<
8
)
+
promoteLevel
);
}
public
static
int
getWeaponExpRequired
(
int
rankLevel
,
int
level
)
{
WeaponLevelData
levelData
=
weaponLevelDataMap
.
get
(
level
);
if
(
levelData
==
null
)
{
return
0
;
}
try
{
return
levelData
.
getRequiredExps
()[
rankLevel
-
1
];
}
catch
(
Exception
e
)
{
return
0
;
}
}
public
static
AvatarPromoteData
getAvatarPromoteData
(
int
promoteId
,
int
promoteLevel
)
{
return
avatarPromoteDataMap
.
get
((
promoteId
<<
8
)
+
promoteLevel
);
}
public
static
int
getAvatarLevelExpRequired
(
int
level
)
{
AvatarLevelData
levelData
=
avatarLevelDataMap
.
get
(
level
);
return
levelData
!=
null
?
levelData
.
getExp
()
:
0
;
}
public
static
Int2ObjectMap
<
ProudSkillData
>
getProudSkillDataMap
()
{
return
proudSkillDataMap
;
}
public
static
Int2ObjectMap
<
MonsterData
>
getMonsterDataMap
()
{
return
monsterDataMap
;
}
public
static
Int2ObjectMap
<
NpcData
>
getNpcDataMap
()
{
return
npcDataMap
;
}
public
static
Int2ObjectMap
<
GadgetData
>
getGadgetDataMap
()
{
return
gadgetDataMap
;
}
public
static
Int2ObjectMap
<
ReliquarySetData
>
getReliquarySetDataMap
()
{
return
reliquarySetDataMap
;
}
public
static
Int2ObjectMap
<
EquipAffixData
>
getEquipAffixDataMap
()
{
return
equipAffixDataMap
;
}
public
static
Int2ObjectMap
<
MonsterCurveData
>
getMonsterCurveDataMap
()
{
return
monsterCurveDataMap
;
}
public
static
Int2ObjectMap
<
MonsterDescribeData
>
getMonsterDescribeDataMap
()
{
return
monsterDescribeDataMap
;
}
public
static
Int2ObjectMap
<
AvatarTalentData
>
getAvatarTalentDataMap
()
{
return
avatarTalentDataMap
;
}
public
static
Int2ObjectMap
<
AvatarFlycloakData
>
getAvatarFlycloakDataMap
()
{
return
avatarFlycloakDataMap
;
}
public
static
Int2ObjectMap
<
AvatarCostumeData
>
getAvatarCostumeDataMap
()
{
return
avatarCostumeDataMap
;
}
public
static
Int2ObjectMap
<
AvatarCostumeData
>
getAvatarCostumeDataItemIdMap
()
{
return
avatarCostumeDataItemIdMap
;
}
}
src/main/java/emu/grasscutter/data/GenshinDepot.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.data
;
import
java.util.ArrayList
;
import
java.util.List
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.def.ReliquaryAffixData
;
import
emu.grasscutter.data.def.ReliquaryMainPropData
;
import
emu.grasscutter.utils.WeightedList
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
public
class
GenshinDepot
{
private
static
Int2ObjectMap
<
WeightedList
<
ReliquaryMainPropData
>>
relicMainPropDepot
=
new
Int2ObjectOpenHashMap
<>();
private
static
Int2ObjectMap
<
List
<
ReliquaryAffixData
>>
relicAffixDepot
=
new
Int2ObjectOpenHashMap
<>();
public
static
void
load
()
{
for
(
ReliquaryMainPropData
data
:
GenshinData
.
getReliquaryMainPropDataMap
().
values
())
{
if
(
data
.
getWeight
()
<=
0
||
data
.
getPropDepotId
()
<=
0
)
{
continue
;
}
WeightedList
<
ReliquaryMainPropData
>
list
=
relicMainPropDepot
.
computeIfAbsent
(
data
.
getPropDepotId
(),
k
->
new
WeightedList
<>());
list
.
add
(
data
.
getWeight
(),
data
);
}
for
(
ReliquaryAffixData
data
:
GenshinData
.
getReliquaryAffixDataMap
().
values
())
{
if
(
data
.
getWeight
()
<=
0
||
data
.
getDepotId
()
<=
0
)
{
continue
;
}
List
<
ReliquaryAffixData
>
list
=
relicAffixDepot
.
computeIfAbsent
(
data
.
getDepotId
(),
k
->
new
ArrayList
<>());
list
.
add
(
data
);
}
// Let the server owner know if theyre missing weights
if
(
relicMainPropDepot
.
size
()
==
0
||
relicAffixDepot
.
size
()
==
0
)
{
Grasscutter
.
getLogger
().
error
(
"Relic properties are missing weights! Please check your ReliquaryMainPropExcelConfigData or ReliquaryAffixExcelConfigData files in your ExcelBinOutput folder."
);
}
}
public
static
ReliquaryMainPropData
getRandomRelicMainProp
(
int
depot
)
{
WeightedList
<
ReliquaryMainPropData
>
depotList
=
relicMainPropDepot
.
get
(
depot
);
if
(
depotList
==
null
)
{
return
null
;
}
return
depotList
.
next
();
}
public
static
List
<
ReliquaryAffixData
>
getRandomRelicAffixList
(
int
depot
)
{
return
relicAffixDepot
.
get
(
depot
);
}
}
src/main/java/emu/grasscutter/data/GenshinResource.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.data
;
public
abstract
class
GenshinResource
{
public
int
getId
()
{
return
0
;
}
public
void
onLoad
()
{
}
}
src/main/java/emu/grasscutter/data/ResourceLoader.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.data
;
import
java.io.File
;
import
java.io.FileReader
;
import
java.nio.file.Files
;
import
java.nio.file.Paths
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.TreeMap
;
import
java.util.Map.Entry
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
java.util.stream.Stream
;
import
org.reflections.Reflections
;
import
com.google.gson.reflect.TypeToken
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.custom.AbilityEmbryoEntry
;
import
emu.grasscutter.data.custom.OpenConfigEntry
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
public
class
ResourceLoader
{
public
static
List
<
Class
<?>>
getResourceDefClasses
()
{
Reflections
reflections
=
new
Reflections
(
ResourceLoader
.
class
.
getPackage
().
getName
());
Set
<?>
classes
=
reflections
.
getSubTypesOf
(
GenshinResource
.
class
);
List
<
Class
<?>>
classList
=
new
ArrayList
<>(
classes
.
size
());
classes
.
forEach
(
o
->
{
Class
<?>
c
=
(
Class
<?>)
o
;
if
(
c
.
getAnnotation
(
ResourceType
.
class
)
!=
null
)
{
classList
.
add
(
c
);
}
});
classList
.
sort
((
a
,
b
)
->
{
return
b
.
getAnnotation
(
ResourceType
.
class
).
loadPriority
().
value
()
-
a
.
getAnnotation
(
ResourceType
.
class
).
loadPriority
().
value
();
});
return
classList
;
}
public
static
void
loadAll
()
{
// Create resource folder if it doesnt exist
File
resFolder
=
new
File
(
Grasscutter
.
getConfig
().
RESOURCE_FOLDER
);
if
(!
resFolder
.
exists
())
{
resFolder
.
mkdir
();
}
// Load ability lists
loadAbilityEmbryos
();
loadOpenConfig
();
// Load resources
loadResources
();
// Process into depots
GenshinDepot
.
load
();
// Custom - TODO move this somewhere else
try
{
GenshinData
.
getAvatarSkillDepotDataMap
().
get
(
504
).
setAbilities
(
new
AbilityEmbryoEntry
(
""
,
new
String
[]
{
"Avatar_PlayerBoy_ExtraAttack_Wind"
,
"Avatar_Player_UziExplode_Mix"
,
"Avatar_Player_UziExplode"
,
"Avatar_Player_UziExplode_Strike_01"
,
"Avatar_Player_UziExplode_Strike_02"
,
"Avatar_Player_WindBreathe"
,
"Avatar_Player_WindBreathe_CameraController"
}
));
GenshinData
.
getAvatarSkillDepotDataMap
().
get
(
704
).
setAbilities
(
new
AbilityEmbryoEntry
(
""
,
new
String
[]
{
"Avatar_PlayerGirl_ExtraAttack_Wind"
,
"Avatar_Player_UziExplode_Mix"
,
"Avatar_Player_UziExplode"
,
"Avatar_Player_UziExplode_Strike_01"
,
"Avatar_Player_UziExplode_Strike_02"
,
"Avatar_Player_WindBreathe"
,
"Avatar_Player_WindBreathe_CameraController"
}
));
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Error loading abilities"
,
e
);
}
}
public
static
void
loadResources
()
{
for
(
Class
<?>
resourceDefinition
:
getResourceDefClasses
())
{
ResourceType
type
=
resourceDefinition
.
getAnnotation
(
ResourceType
.
class
);
if
(
type
==
null
)
{
continue
;
}
@SuppressWarnings
(
"rawtypes"
)
Int2ObjectMap
map
=
GenshinData
.
getMapByResourceDef
(
resourceDefinition
);
if
(
map
==
null
)
{
continue
;
}
try
{
loadFromResource
(
resourceDefinition
,
type
,
map
);
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Error loading resource file: "
+
type
.
name
(),
e
);
}
}
}
@SuppressWarnings
(
"rawtypes"
)
protected
static
void
loadFromResource
(
Class
<?>
c
,
ResourceType
type
,
Int2ObjectMap
map
)
throws
Exception
{
for
(
String
name
:
type
.
name
())
{
loadFromResource
(
c
,
name
,
map
);
}
Grasscutter
.
getLogger
().
info
(
"Loaded "
+
map
.
size
()
+
" "
+
c
.
getSimpleName
()
+
"s."
);
}
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
protected
static
void
loadFromResource
(
Class
<?>
c
,
String
fileName
,
Int2ObjectMap
map
)
throws
Exception
{
try
(
FileReader
fileReader
=
new
FileReader
(
Grasscutter
.
getConfig
().
RESOURCE_FOLDER
+
"ExcelBinOutput/"
+
fileName
))
{
List
list
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
TypeToken
.
getParameterized
(
Collection
.
class
,
c
).
getType
());
for
(
Object
o
:
list
)
{
GenshinResource
res
=
(
GenshinResource
)
o
;
res
.
onLoad
();
map
.
put
(
res
.
getId
(),
res
);
}
}
}
private
static
void
loadAbilityEmbryos
()
{
// Read from cached file if exists
File
embryoCache
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"AbilityEmbryos.json"
);
List
<
AbilityEmbryoEntry
>
embryoList
=
null
;
if
(
embryoCache
.
exists
())
{
// Load from cache
try
(
FileReader
fileReader
=
new
FileReader
(
embryoCache
))
{
embryoList
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
TypeToken
.
getParameterized
(
Collection
.
class
,
AbilityEmbryoEntry
.
class
).
getType
());
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
else
{
// Load from BinOutput
Pattern
pattern
=
Pattern
.
compile
(
"(?<=ConfigAvatar_)(.*?)(?=.json)"
);
embryoList
=
new
LinkedList
<>();
File
folder
=
new
File
(
Grasscutter
.
getConfig
().
RESOURCE_FOLDER
+
"BinOutput\\Avatar\\"
);
for
(
File
file
:
folder
.
listFiles
())
{
AvatarConfig
config
=
null
;
String
avatarName
=
null
;
Matcher
matcher
=
pattern
.
matcher
(
file
.
getName
());
if
(
matcher
.
find
())
{
avatarName
=
matcher
.
group
(
0
);
}
else
{
continue
;
}
try
(
FileReader
fileReader
=
new
FileReader
(
file
))
{
config
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
AvatarConfig
.
class
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
continue
;
}
if
(
config
.
abilities
==
null
)
{
continue
;
}
int
s
=
config
.
abilities
.
size
();
AbilityEmbryoEntry
al
=
new
AbilityEmbryoEntry
(
avatarName
,
config
.
abilities
.
stream
().
map
(
Object:
:
toString
).
toArray
(
size
->
new
String
[
s
]));
embryoList
.
add
(
al
);
}
}
if
(
embryoList
==
null
||
embryoList
.
isEmpty
())
{
Grasscutter
.
getLogger
().
error
(
"No embryos loaded!"
);
return
;
}
for
(
AbilityEmbryoEntry
entry
:
embryoList
)
{
GenshinData
.
getAbilityEmbryoInfo
().
put
(
entry
.
getName
(),
entry
);
}
}
private
static
void
loadOpenConfig
()
{
// Read from cached file if exists
File
openConfigCache
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"OpenConfig.json"
);
List
<
OpenConfigEntry
>
list
=
null
;
if
(
openConfigCache
.
exists
())
{
try
(
FileReader
fileReader
=
new
FileReader
(
openConfigCache
))
{
list
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
TypeToken
.
getParameterized
(
Collection
.
class
,
OpenConfigEntry
.
class
).
getType
());
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
else
{
Map
<
String
,
OpenConfigEntry
>
map
=
new
TreeMap
<>();
java
.
lang
.
reflect
.
Type
type
=
new
TypeToken
<
Map
<
String
,
OpenConfigData
[]>>()
{}.
getType
();
String
[]
folderNames
=
{
"BinOutput\\Talent\\EquipTalents\\"
,
"BinOutput\\Talent\\AvatarTalents\\"
};
for
(
String
name
:
folderNames
)
{
File
folder
=
new
File
(
Grasscutter
.
getConfig
().
RESOURCE_FOLDER
+
name
);
for
(
File
file
:
folder
.
listFiles
())
{
if
(!
file
.
getName
().
endsWith
(
".json"
))
{
continue
;
}
Map
<
String
,
OpenConfigData
[]>
config
=
null
;
try
(
FileReader
fileReader
=
new
FileReader
(
file
))
{
config
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
type
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
continue
;
}
for
(
Entry
<
String
,
OpenConfigData
[]>
e
:
config
.
entrySet
())
{
List
<
String
>
abilityList
=
new
ArrayList
<>();
int
extraTalentIndex
=
0
;
for
(
OpenConfigData
entry
:
e
.
getValue
())
{
if
(
entry
.
$type
.
contains
(
"AddAbility"
))
{
abilityList
.
add
(
entry
.
abilityName
);
}
else
if
(
entry
.
talentIndex
>
0
)
{
extraTalentIndex
=
entry
.
talentIndex
;
}
}
OpenConfigEntry
entry
=
new
OpenConfigEntry
(
e
.
getKey
(),
abilityList
,
extraTalentIndex
);
map
.
put
(
entry
.
getName
(),
entry
);
}
}
}
list
=
new
ArrayList
<>(
map
.
values
());
}
if
(
list
==
null
||
list
.
isEmpty
())
{
Grasscutter
.
getLogger
().
error
(
"No openconfig entries loaded!"
);
return
;
}
for
(
OpenConfigEntry
entry
:
list
)
{
GenshinData
.
getOpenConfigEntries
().
put
(
entry
.
getName
(),
entry
);
}
}
// BinOutput configs
private
static
class
AvatarConfig
{
public
ArrayList
<
AvatarConfigAbility
>
abilities
;
private
static
class
AvatarConfigAbility
{
public
String
abilityName
;
public
String
toString
()
{
return
abilityName
;
}
}
}
private
static
class
OpenConfig
{
public
OpenConfigData
[]
data
;
}
private
static
class
OpenConfigData
{
public
String
$type
;
public
String
abilityName
;
public
int
talentIndex
;
}
}
src/main/java/emu/grasscutter/data/ResourceType.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.data
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
ResourceType
{
/** Names of the file that this Resource loads from */
String
[]
name
();
/** Load priority - dictates which order to load this resource, with "highest" being loaded first */
LoadPriority
loadPriority
()
default
LoadPriority
.
NORMAL
;
public
enum
LoadPriority
{
HIGHEST
(
4
),
HIGH
(
3
),
NORMAL
(
2
),
LOW
(
1
),
LOWEST
(
0
);
private
final
int
value
;
LoadPriority
(
int
value
)
{
this
.
value
=
value
;
}
public
int
value
()
{
return
value
;
}
}
}
src/main/java/emu/grasscutter/data/common/CurveInfo.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.data.common
;
public
class
CurveInfo
{
private
String
Type
;
private
String
Arith
;
private
float
Value
;
public
String
getType
()
{
return
Type
;
}
public
String
getArith
()
{
return
Arith
;
}
public
float
getValue
()
{
return
Value
;
}
}
src/main/java/emu/grasscutter/data/common/FightPropData.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.data.common
;
import
emu.grasscutter.game.props.FightProperty
;
public
class
FightPropData
{
private
String
PropType
;
private
FightProperty
prop
;
private
float
Value
;
public
String
getPropType
()
{
return
PropType
;
}
public
float
getValue
()
{
return
Value
;
}
public
FightProperty
getProp
()
{
return
prop
;
}
public
void
onLoad
()
{
this
.
prop
=
FightProperty
.
getPropByName
(
PropType
);
}
}
\ No newline at end of file
src/main/java/emu/grasscutter/data/common/ItemParamData.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.data.common
;
public
class
ItemParamData
{
private
int
Id
;
private
int
Count
;
public
int
getId
()
{
return
Id
;
}
public
int
getCount
()
{
return
Count
;
}
}
src/main/java/emu/grasscutter/data/common/PropGrowCurve.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.data.common
;
public
class
PropGrowCurve
{
private
String
Type
;
private
String
GrowCurve
;
public
String
getType
(){
return
this
.
Type
;
}
public
String
getGrowCurve
(){
return
this
.
GrowCurve
;
}
}
src/main/java/emu/grasscutter/data/custom/AbilityEmbryoEntry.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.data.custom
;
public
class
AbilityEmbryoEntry
{
private
String
name
;
private
String
[]
abilities
;
public
AbilityEmbryoEntry
()
{
}
public
AbilityEmbryoEntry
(
String
avatarName
,
String
[]
array
)
{
this
.
name
=
avatarName
;
this
.
abilities
=
array
;
}
public
String
getName
()
{
return
name
;
}
public
String
[]
getAbilities
()
{
return
abilities
;
}
}
src/main/java/emu/grasscutter/data/custom/OpenConfigEntry.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.data.custom
;
import
java.util.List
;
public
class
OpenConfigEntry
{
private
String
name
;
private
String
[]
addAbilities
;
private
int
extraTalentIndex
;
public
OpenConfigEntry
(
String
name
,
List
<
String
>
abilityList
,
int
extraTalentIndex
)
{
this
.
name
=
name
;
this
.
extraTalentIndex
=
extraTalentIndex
;
if
(
abilityList
.
size
()
>
0
)
{
this
.
addAbilities
=
abilityList
.
toArray
(
new
String
[
0
]);
}
}
public
String
getName
()
{
return
name
;
}
public
String
[]
getAddAbilities
()
{
return
addAbilities
;
}
public
int
getExtraTalentIndex
()
{
return
extraTalentIndex
;
}
}
src/main/java/emu/grasscutter/data/def/AvatarCostumeData.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.data.def
;
import
emu.grasscutter.data.GenshinData
;
import
emu.grasscutter.data.GenshinResource
;
import
emu.grasscutter.data.ResourceType
;
@ResourceType
(
name
=
"AvatarCostumeExcelConfigData.json"
)
public
class
AvatarCostumeData
extends
GenshinResource
{
private
int
CostumeId
;
private
int
ItemId
;
private
int
AvatarId
;
@Override
public
int
getId
()
{
return
this
.
CostumeId
;
}
public
int
getItemId
()
{
return
this
.
ItemId
;
}
public
int
getAvatarId
()
{
return
AvatarId
;
}
@Override
public
void
onLoad
()
{
GenshinData
.
getAvatarCostumeDataItemIdMap
().
put
(
this
.
getItemId
(),
this
);
}
}
src/main/java/emu/grasscutter/data/def/AvatarCurveData.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.data.def
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.stream.Stream
;
import
emu.grasscutter.data.GenshinResource
;
import
emu.grasscutter.data.ResourceType
;
import
emu.grasscutter.data.common.CurveInfo
;
@ResourceType
(
name
=
"AvatarCurveExcelConfigData.json"
)
public
class
AvatarCurveData
extends
GenshinResource
{
private
int
Level
;
private
CurveInfo
[]
CurveInfos
;
private
Map
<
String
,
Float
>
curveInfos
;
@Override
public
int
getId
()
{
return
this
.
Level
;
}
public
int
getLevel
()
{
return
Level
;
}
public
Map
<
String
,
Float
>
getCurveInfos
()
{
return
curveInfos
;
}
@Override
public
void
onLoad
()
{
this
.
curveInfos
=
new
HashMap
<>();
Stream
.
of
(
this
.
CurveInfos
).
forEach
(
info
->
this
.
curveInfos
.
put
(
info
.
getType
(),
info
.
getValue
()));
}
}
src/main/java/emu/grasscutter/data/def/AvatarData.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.data.def
;
import
java.util.List
;
import
emu.grasscutter.data.GenshinData
;
import
emu.grasscutter.data.GenshinResource
;
import
emu.grasscutter.data.ResourceType
;
import
emu.grasscutter.data.ResourceType.LoadPriority
;
import
emu.grasscutter.data.common.PropGrowCurve
;
import
emu.grasscutter.data.custom.AbilityEmbryoEntry
;
import
emu.grasscutter.game.props.FightProperty
;
import
emu.grasscutter.utils.Utils
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.IntArrayList
;
import
it.unimi.dsi.fastutil.ints.IntList
;
@ResourceType
(
name
=
"AvatarExcelConfigData.json"
,
loadPriority
=
LoadPriority
.
LOW
)
public
class
AvatarData
extends
GenshinResource
{
private
String
name
;
private
String
IconName
;
private
String
BodyType
;
private
String
QualityType
;
private
int
ChargeEfficiency
;
private
int
InitialWeapon
;
private
String
WeaponType
;
private
String
ImageName
;
private
int
AvatarPromoteId
;
private
String
CutsceneShow
;
private
int
SkillDepotId
;
private
int
StaminaRecoverSpeed
;
private
List
<
String
>
CandSkillDepotIds
;
private
long
DescTextMapHash
;
private
String
AvatarIdentityType
;
private
List
<
Integer
>
AvatarPromoteRewardLevelList
;
private
List
<
Integer
>
AvatarPromoteRewardIdList
;
private
int
FeatureTagGroupID
;
private
long
NameTextMapHash
;
private
long
GachaImageNameHashSuffix
;
private
long
InfoDescTextMapHash
;
private
float
HpBase
;
private
float
AttackBase
;
private
float
DefenseBase
;
private
float
Critical
;
private
float
CriticalHurt
;
private
List
<
PropGrowCurve
>
PropGrowCurves
;
private
int
Id
;
private
Int2ObjectMap
<
String
>
growthCurveMap
;
private
float
[]
hpGrowthCurve
;
private
float
[]
attackGrowthCurve
;
private
float
[]
defenseGrowthCurve
;
private
AvatarSkillDepotData
skillDepot
;
private
IntList
abilities
;
@Override
public
int
getId
(){
return
this
.
Id
;
}
public
String
getName
()
{
return
name
;
}
public
String
getBodyType
(){
return
this
.
BodyType
;
}
public
String
getQualityType
(){
return
this
.
QualityType
;
}
public
int
getChargeEfficiency
(){
return
this
.
ChargeEfficiency
;
}
public
int
getInitialWeapon
(){
return
this
.
InitialWeapon
;
}
public
String
getWeaponType
(){
return
this
.
WeaponType
;
}
public
String
getImageName
(){
return
this
.
ImageName
;
}
public
int
getAvatarPromoteId
(){
return
this
.
AvatarPromoteId
;
}
public
long
getGachaImageNameHashSuffix
(){
return
this
.
GachaImageNameHashSuffix
;
}
public
String
getCutsceneShow
(){
return
this
.
CutsceneShow
;
}
public
int
getSkillDepotId
(){
return
this
.
SkillDepotId
;
}
public
int
getStaminaRecoverSpeed
(){
return
this
.
StaminaRecoverSpeed
;
}
public
List
<
String
>
getCandSkillDepotIds
(){
return
this
.
CandSkillDepotIds
;
}
public
long
getDescTextMapHash
(){
return
this
.
DescTextMapHash
;
}
public
String
getAvatarIdentityType
(){
return
this
.
AvatarIdentityType
;
}
public
List
<
Integer
>
getAvatarPromoteRewardLevelList
(){
return
this
.
AvatarPromoteRewardLevelList
;
}
public
List
<
Integer
>
getAvatarPromoteRewardIdList
(){
return
this
.
AvatarPromoteRewardIdList
;
}
public
int
getFeatureTagGroupID
(){
return
this
.
FeatureTagGroupID
;
}
public
long
getInfoDescTextMapHash
(){
return
this
.
InfoDescTextMapHash
;
}
public
float
getBaseHp
(
int
level
){
try
{
return
this
.
HpBase
*
this
.
hpGrowthCurve
[
level
-
1
];
}
catch
(
Exception
e
)
{
return
this
.
HpBase
;
}
}
public
float
getBaseAttack
(
int
level
){
try
{
return
this
.
AttackBase
*
this
.
attackGrowthCurve
[
level
-
1
];
}
catch
(
Exception
e
)
{
return
this
.
AttackBase
;
}
}
public
float
getBaseDefense
(
int
level
){
try
{
return
this
.
DefenseBase
*
this
.
defenseGrowthCurve
[
level
-
1
];
}
catch
(
Exception
e
)
{
return
this
.
DefenseBase
;
}
}
public
float
getBaseCritical
(){
return
this
.
Critical
;
}
public
float
getBaseCriticalHurt
(){
return
this
.
CriticalHurt
;
}
public
float
getGrowthCurveById
(
int
level
,
FightProperty
prop
)
{
String
growCurve
=
this
.
growthCurveMap
.
get
(
prop
.
getId
());
if
(
growCurve
==
null
)
{
return
1
f
;
}
AvatarCurveData
curveData
=
GenshinData
.
getAvatarCurveDataMap
().
get
(
level
);
if
(
curveData
==
null
)
{
return
1
f
;
}
return
curveData
.
getCurveInfos
().
getOrDefault
(
growCurve
,
1
f
);
}
public
long
getNameTextMapHash
(){
return
this
.
NameTextMapHash
;
}
public
AvatarSkillDepotData
getSkillDepot
()
{
return
skillDepot
;
}
public
IntList
getAbilities
()
{
return
abilities
;
}
@Override
public
void
onLoad
()
{
this
.
skillDepot
=
GenshinData
.
getAvatarSkillDepotDataMap
().
get
(
this
.
SkillDepotId
);
int
size
=
GenshinData
.
getAvatarCurveDataMap
().
size
();
this
.
hpGrowthCurve
=
new
float
[
size
];
this
.
attackGrowthCurve
=
new
float
[
size
];
this
.
defenseGrowthCurve
=
new
float
[
size
];
for
(
AvatarCurveData
curveData
:
GenshinData
.
getAvatarCurveDataMap
().
values
())
{
int
level
=
curveData
.
getLevel
()
-
1
;
for
(
PropGrowCurve
growCurve
:
this
.
PropGrowCurves
)
{
FightProperty
prop
=
FightProperty
.
getPropByName
(
growCurve
.
getType
());
switch
(
prop
)
{
case
FIGHT_PROP_BASE_HP:
this
.
hpGrowthCurve
[
level
]
=
curveData
.
getCurveInfos
().
get
(
growCurve
.
getGrowCurve
());
break
;
case
FIGHT_PROP_BASE_ATTACK:
this
.
attackGrowthCurve
[
level
]
=
curveData
.
getCurveInfos
().
get
(
growCurve
.
getGrowCurve
());
break
;
case
FIGHT_PROP_BASE_DEFENSE:
this
.
defenseGrowthCurve
[
level
]
=
curveData
.
getCurveInfos
().
get
(
growCurve
.
getGrowCurve
());
break
;
default
:
break
;
}
}
}
/*
for (PropGrowCurve growCurve : this.PropGrowCurves) {
FightProperty prop = FightProperty.getPropByName(growCurve.getType());
this.growthCurveMap.put(prop.getId(), growCurve.getGrowCurve());
}
*/
// Cache abilities
String
[]
split
=
this
.
IconName
.
split
(
"_"
);
if
(
split
.
length
>
0
)
{
this
.
name
=
split
[
split
.
length
-
1
];
AbilityEmbryoEntry
info
=
GenshinData
.
getAbilityEmbryoInfo
().
get
(
this
.
name
);
if
(
info
!=
null
)
{
this
.
abilities
=
new
IntArrayList
(
info
.
getAbilities
().
length
);
for
(
String
ability
:
info
.
getAbilities
())
{
this
.
abilities
.
add
(
Utils
.
abilityHash
(
ability
));
}
}
}
}
}
src/main/java/emu/grasscutter/data/def/AvatarFlycloakData.java
0 → 100644
View file @
7925d1cd
package
emu.grasscutter.data.def
;
import
emu.grasscutter.data.GenshinResource
;
import
emu.grasscutter.data.ResourceType
;
@ResourceType
(
name
=
"AvatarFlycloakExcelConfigData.json"
)
public
class
AvatarFlycloakData
extends
GenshinResource
{
private
int
FlycloakId
;
private
long
NameTextMapHash
;
@Override
public
int
getId
()
{
return
this
.
FlycloakId
;
}
public
long
getNameTextMapHash
()
{
return
NameTextMapHash
;
}
@Override
public
void
onLoad
()
{
}
}
Prev
1
2
3
4
5
6
…
18
Next
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