mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-16 17:05:03 +01:00
Merge branch 'main' into feature/event-tent
This commit is contained in:
15
AUTHORS.md
15
AUTHORS.md
@@ -1,14 +1,15 @@
|
|||||||
# List of AUTHORS who contributed over time to the Erupe project
|
# List of authors who contributed to Erupe
|
||||||
|
|
||||||
## Point of current development
|
## Point of current development
|
||||||
The project is currently developed under https://github.com/ZeruLight/Erupe
|
The project is currently developed under https://github.com/ZeruLight/Erupe
|
||||||
|
|
||||||
## History of development
|
## History of development
|
||||||
Development of this project dates back to 2019, and was developed under various umbrellas over time:
|
Development of this project dates back to 2019, and was developed under various umbrellas over time:
|
||||||
* Cappuccino (Fist/Ando/Ellie42) (The Erupe Developers), 2019-2020 (https://github.com/Ellie42/Erupe / https://github.com/ricochhet/Erupe-Legacy) (Still active closed source)
|
* Cappuccino (Fist/Ando/Ellie42) ("The Erupe Developers"), 2019-2020 (https://github.com/Ellie42/Erupe / https://github.com/ricochhet/Erupe-Legacy) (Still active closed source)
|
||||||
* Einherjar Team, ????-2022 Feb (There is no git history for this period, this team's work was taken and used as a foundation for future repositories)
|
* Einherjar Team, ????-2022 Feb (There is no git history for this period, this team's work was taken and used as a foundation for future repositories)
|
||||||
* Community Edition, 2022 (https://github.com/xl3lackout/Erupe)
|
* Community Edition, 2022 (https://github.com/xl3lackout/Erupe)
|
||||||
* Zerulight, 2022-2023 (https://github.com/ZeruLight/Erupe)
|
* sekaiwish Fork, 2022 (https://github.com/sekaiwish/Erupe)
|
||||||
|
* ZeruLight, 2022-2023 (https://github.com/ZeruLight/Erupe)
|
||||||
|
|
||||||
## Authorship of the code
|
## Authorship of the code
|
||||||
Authorship is assigned for each commit within the git history, which is stored in these git repos:
|
Authorship is assigned for each commit within the git history, which is stored in these git repos:
|
||||||
@@ -17,13 +18,13 @@ Authorship is assigned for each commit within the git history, which is stored i
|
|||||||
* https://github.com/ricochhet/Erupe-Legacy
|
* https://github.com/ricochhet/Erupe-Legacy
|
||||||
* https://github.com/xl3lackout/Erupe
|
* https://github.com/xl3lackout/Erupe
|
||||||
|
|
||||||
Note there is a divergence between Ellie42s branch and xl3lackout where history has been lost.
|
Note the divergence between Ellie42's branch and xl3lackout's where history has been lost.
|
||||||
|
|
||||||
Unfortunately, we have no detailed information on the history of the Erupe pre-2022
|
Unfortunately, we have no detailed information on the history of Erupe before 2022.
|
||||||
if somebody can provide information, please contact us, so that we can make this history available.
|
If somebody can provide information, please contact us, so that we can make this history available.
|
||||||
|
|
||||||
## Exceptions with third-party libraries
|
## Exceptions with third-party libraries
|
||||||
The third-party libraries have their own way of addressing authorship and the authorship of commits importing/updating
|
The third-party libraries have their own way of addressing authorship and the authorship of commits importing/updating
|
||||||
a third-party library reflects who did the importing instead of who wrote the code within the commit.
|
a third-party library reflects who did the importing instead of who wrote the code within the commit.
|
||||||
|
|
||||||
The Authors of third-party libraries are not explicitly mentioned, and usually is possible to obtain from the files belonging to the third-party libraries.
|
The authors of third-party libraries are not explicitly mentioned, and usually is possible to obtain from the files belonging to the third-party libraries.
|
||||||
12
README.md
12
README.md
@@ -1,6 +1,6 @@
|
|||||||
# Erupe
|
# Erupe
|
||||||
|
|
||||||
## Client Compatiblity
|
## Client Compatibility
|
||||||
### Platforms
|
### Platforms
|
||||||
- PC
|
- PC
|
||||||
- PlayStation 3
|
- PlayStation 3
|
||||||
@@ -34,15 +34,15 @@ If you want to modify or compile Erupe yourself, please read on.
|
|||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
Please see the readme in [docker/README.md](./docker/README.md). At the moment this is only really good for quick installs and checking out development not for production.
|
Please see [docker/README.md](./docker/README.md). This is intended for quick installs and development, not for production.
|
||||||
|
|
||||||
## Schemas
|
## Schemas
|
||||||
|
|
||||||
We source control the following schemas:
|
We source control the following schemas:
|
||||||
- Initialisation Schemas: These initialise the application database to a clean install from a specific version.
|
- Initialization Schema: This initializes the application database to a specific version (9.1.0).
|
||||||
- Update Schemas: These are update files they should be ran in order of version to get to the latest schema.
|
- Update Schemas: These are update files that should be ran on top of the initialization schema.
|
||||||
- Patch Schemas: These are for development and should be ran from the lastest available update schema or initial schema. These eventually get condensed into `Update Schemas` and then deleted when updated to a new version.
|
- Patch Schemas: These are for development and should be run after running all initialization and update schema. These get condensed into `Update Schemas` and deleted when updated to a new release.
|
||||||
- Bundled Schemas: These are demo reference files to allow servers to be able to roll their own shops, distributions gachas and scenarios set ups.
|
- Bundled Schemas: These are demo reference files to give servers standard set-ups.
|
||||||
|
|
||||||
Note: Patch schemas are subject to change! You should only be using them if you are following along with development.
|
Note: Patch schemas are subject to change! You should only be using them if you are following along with development.
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ func (m *MsgMhfUpdateGuacot) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Clien
|
|||||||
m.AckHandle = bf.ReadUint32()
|
m.AckHandle = bf.ReadUint32()
|
||||||
m.EntryCount = bf.ReadUint16()
|
m.EntryCount = bf.ReadUint16()
|
||||||
bf.ReadUint16() // Zeroed
|
bf.ReadUint16() // Zeroed
|
||||||
var temp Goocoo
|
|
||||||
for i := 0; i < int(m.EntryCount); i++ {
|
for i := 0; i < int(m.EntryCount); i++ {
|
||||||
|
var temp Goocoo
|
||||||
temp.Index = bf.ReadUint32()
|
temp.Index = bf.ReadUint32()
|
||||||
for j := 0; j < 22; j++ {
|
for j := 0; j < 22; j++ {
|
||||||
temp.Data1 = append(temp.Data1, bf.ReadInt16())
|
temp.Data1 = append(temp.Data1, bf.ReadInt16())
|
||||||
|
|||||||
6
schemas/patch-schema/22-clan-changing-room.sql
Normal file
6
schemas/patch-schema/22-clan-changing-room.sql
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
ALTER TABLE guilds ADD COLUMN IF NOT EXISTS room_rp INT DEFAULT 0;
|
||||||
|
ALTER TABLE guilds ADD COLUMN IF NOT EXISTS room_expiry TIMESTAMP WITHOUT TIME ZONE;
|
||||||
|
|
||||||
|
END;
|
||||||
@@ -51,6 +51,8 @@ type Guild struct {
|
|||||||
MemberCount uint16 `db:"member_count"`
|
MemberCount uint16 `db:"member_count"`
|
||||||
RankRP uint32 `db:"rank_rp"`
|
RankRP uint32 `db:"rank_rp"`
|
||||||
EventRP uint32 `db:"event_rp"`
|
EventRP uint32 `db:"event_rp"`
|
||||||
|
RoomRP uint16 `db:"room_rp"`
|
||||||
|
RoomExpiry time.Time `db:"room_expiry"`
|
||||||
Comment string `db:"comment"`
|
Comment string `db:"comment"`
|
||||||
PugiName1 string `db:"pugi_name_1"`
|
PugiName1 string `db:"pugi_name_1"`
|
||||||
PugiName2 string `db:"pugi_name_2"`
|
PugiName2 string `db:"pugi_name_2"`
|
||||||
@@ -153,6 +155,8 @@ SELECT
|
|||||||
g.name,
|
g.name,
|
||||||
rank_rp,
|
rank_rp,
|
||||||
event_rp,
|
event_rp,
|
||||||
|
room_rp,
|
||||||
|
COALESCE(room_expiry, '1970-01-01') AS room_expiry,
|
||||||
main_motto,
|
main_motto,
|
||||||
sub_motto,
|
sub_motto,
|
||||||
created_at,
|
created_at,
|
||||||
@@ -706,7 +710,7 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
}
|
}
|
||||||
bf.WriteUint32(uint32(response))
|
bf.WriteUint32(uint32(response))
|
||||||
case mhfpacket.OperateGuildDonateRank:
|
case mhfpacket.OperateGuildDonateRank:
|
||||||
bf.WriteBytes(handleDonateRP(s, uint16(pkt.Data1.ReadUint32()), guild, false))
|
bf.WriteBytes(handleDonateRP(s, uint16(pkt.Data1.ReadUint32()), guild, 0))
|
||||||
case mhfpacket.OperateGuildSetApplicationDeny:
|
case mhfpacket.OperateGuildSetApplicationDeny:
|
||||||
s.server.db.Exec("UPDATE guilds SET recruiting=false WHERE id=$1", guild.ID)
|
s.server.db.Exec("UPDATE guilds SET recruiting=false WHERE id=$1", guild.ID)
|
||||||
case mhfpacket.OperateGuildSetApplicationAllow:
|
case mhfpacket.OperateGuildSetApplicationAllow:
|
||||||
@@ -747,10 +751,11 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
// TODO: This doesn't implement blocking, if someone unlocked the same outfit at the same time
|
// TODO: This doesn't implement blocking, if someone unlocked the same outfit at the same time
|
||||||
s.server.db.Exec(`UPDATE guilds SET pugi_outfits=pugi_outfits+$1 WHERE id=$2`, int(math.Pow(float64(pkt.Data1.ReadUint32()), 2)), guild.ID)
|
s.server.db.Exec(`UPDATE guilds SET pugi_outfits=pugi_outfits+$1 WHERE id=$2`, int(math.Pow(float64(pkt.Data1.ReadUint32()), 2)), guild.ID)
|
||||||
case mhfpacket.OperateGuildDonateRoom:
|
case mhfpacket.OperateGuildDonateRoom:
|
||||||
// TODO: Where does this go?
|
quantity := uint16(pkt.Data1.ReadUint32())
|
||||||
|
bf.WriteBytes(handleDonateRP(s, quantity, guild, 2))
|
||||||
case mhfpacket.OperateGuildDonateEvent:
|
case mhfpacket.OperateGuildDonateEvent:
|
||||||
quantity := uint16(pkt.Data1.ReadUint32())
|
quantity := uint16(pkt.Data1.ReadUint32())
|
||||||
bf.WriteBytes(handleDonateRP(s, quantity, guild, true))
|
bf.WriteBytes(handleDonateRP(s, quantity, guild, 1))
|
||||||
// TODO: Move this value onto rp_yesterday and reset to 0... daily?
|
// TODO: Move this value onto rp_yesterday and reset to 0... daily?
|
||||||
s.server.db.Exec(`UPDATE guild_characters SET rp_today=rp_today+$1 WHERE character_id=$2`, quantity, s.charID)
|
s.server.db.Exec(`UPDATE guild_characters SET rp_today=rp_today+$1 WHERE character_id=$2`, quantity, s.charID)
|
||||||
case mhfpacket.OperateGuildEventExchange:
|
case mhfpacket.OperateGuildEventExchange:
|
||||||
@@ -794,20 +799,37 @@ func handleChangePugi(s *Session, outfit uint8, guild *Guild, num int) {
|
|||||||
guild.Save(s)
|
guild.Save(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleDonateRP(s *Session, amount uint16, guild *Guild, isEvent bool) []byte {
|
func handleDonateRP(s *Session, amount uint16, guild *Guild, _type int) []byte {
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
bf.WriteUint32(0)
|
bf.WriteUint32(0)
|
||||||
saveData, err := GetCharacterSaveData(s, s.charID)
|
saveData, err := GetCharacterSaveData(s, s.charID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return bf.Data()
|
return bf.Data()
|
||||||
}
|
}
|
||||||
|
var resetRoom bool
|
||||||
|
if _type == 2 {
|
||||||
|
var currentRP uint16
|
||||||
|
s.server.db.QueryRow(`SELECT room_rp FROM guilds WHERE id = $1`, guild.ID).Scan(¤tRP)
|
||||||
|
if currentRP+amount >= 30 {
|
||||||
|
amount = 30 - currentRP
|
||||||
|
resetRoom = true
|
||||||
|
}
|
||||||
|
}
|
||||||
saveData.RP -= amount
|
saveData.RP -= amount
|
||||||
saveData.Save(s)
|
saveData.Save(s)
|
||||||
updateSQL := "UPDATE guilds SET rank_rp = rank_rp + $1 WHERE id = $2"
|
switch _type {
|
||||||
if isEvent {
|
case 0:
|
||||||
updateSQL = "UPDATE guilds SET event_rp = event_rp + $1 WHERE id = $2"
|
s.server.db.Exec(`UPDATE guilds SET rank_rp = rank_rp + $1 WHERE id = $2`, amount, guild.ID)
|
||||||
|
case 1:
|
||||||
|
s.server.db.Exec(`UPDATE guilds SET event_rp = event_rp + $1 WHERE id = $2`, amount, guild.ID)
|
||||||
|
case 2:
|
||||||
|
if resetRoom {
|
||||||
|
s.server.db.Exec(`UPDATE guilds SET room_rp = 0 WHERE id = $1`, guild.ID)
|
||||||
|
s.server.db.Exec(`UPDATE guilds SET room_expiry = $1 WHERE id = $2`, TimeAdjusted().Add(time.Hour*24*7), guild.ID)
|
||||||
|
} else {
|
||||||
|
s.server.db.Exec(`UPDATE guilds SET room_rp = room_rp + $1 WHERE id = $2`, amount, guild.ID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
s.server.db.Exec(updateSQL, amount, guild.ID)
|
|
||||||
bf.Seek(0, 0)
|
bf.Seek(0, 0)
|
||||||
bf.WriteUint32(uint32(saveData.RP))
|
bf.WriteUint32(uint32(saveData.RP))
|
||||||
return bf.Data()
|
return bf.Data()
|
||||||
@@ -1001,8 +1023,8 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
bf.WriteUint8(limit)
|
bf.WriteUint8(limit)
|
||||||
|
|
||||||
bf.WriteUint32(55000)
|
bf.WriteUint32(55000)
|
||||||
bf.WriteUint32(0)
|
bf.WriteUint32(uint32(guild.RoomExpiry.Unix()))
|
||||||
bf.WriteUint16(0) // Changing Room RP
|
bf.WriteUint16(guild.RoomRP)
|
||||||
bf.WriteUint16(0) // Ignored
|
bf.WriteUint16(0) // Ignored
|
||||||
|
|
||||||
if guild.AllianceID > 0 {
|
if guild.AllianceID > 0 {
|
||||||
|
|||||||
@@ -148,9 +148,21 @@ func removeSessionFromStage(s *Session) {
|
|||||||
destructEmptySemaphores(s)
|
destructEmptySemaphores(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isStageFull(s *Session, StageID string) bool {
|
||||||
|
if stage, exists := s.server.stages[StageID]; exists {
|
||||||
|
return len(stage.reservedClientSlots)+len(stage.clients) >= int(stage.maxPlayers)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysEnterStage)
|
pkt := p.(*mhfpacket.MsgSysEnterStage)
|
||||||
|
|
||||||
|
if isStageFull(s, pkt.StageID) {
|
||||||
|
doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Push our current stage ID to the movement stack before entering another one.
|
// Push our current stage ID to the movement stack before entering another one.
|
||||||
if s.stage != nil {
|
if s.stage != nil {
|
||||||
s.stage.Lock()
|
s.stage.Lock()
|
||||||
@@ -175,6 +187,12 @@ func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
backStage = "sl1Ns200p0a0u0"
|
backStage = "sl1Ns200p0a0u0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isStageFull(s, backStage) {
|
||||||
|
s.stageMoveStack.Push(backStage)
|
||||||
|
doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if _, exists := s.stage.reservedClientSlots[s.charID]; exists {
|
if _, exists := s.stage.reservedClientSlots[s.charID]; exists {
|
||||||
delete(s.stage.reservedClientSlots, s.charID)
|
delete(s.stage.reservedClientSlots, s.charID)
|
||||||
}
|
}
|
||||||
@@ -188,6 +206,12 @@ func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgSysMoveStage(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysMoveStage(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysMoveStage)
|
pkt := p.(*mhfpacket.MsgSysMoveStage)
|
||||||
|
|
||||||
|
if isStageFull(s, pkt.StageID) {
|
||||||
|
doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
doStageTransfer(s, pkt.AckHandle, pkt.StageID)
|
doStageTransfer(s, pkt.AckHandle, pkt.StageID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ func NewStage(ID string) *Stage {
|
|||||||
objects: make(map[uint32]*Object),
|
objects: make(map[uint32]*Object),
|
||||||
objectIndex: 0,
|
objectIndex: 0,
|
||||||
rawBinaryData: make(map[stageBinaryKey][]byte),
|
rawBinaryData: make(map[stageBinaryKey][]byte),
|
||||||
maxPlayers: 4,
|
maxPlayers: 127,
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,26 +38,25 @@ func (s *Session) makeSignResponse(uid uint32) []byte {
|
|||||||
return bf.Data()
|
return bf.Data()
|
||||||
}
|
}
|
||||||
|
|
||||||
bf.WriteUint8(uint8(SIGN_SUCCESS)) // resp_code
|
if s.client == PS3 && (s.server.erupeConfig.PatchServerFile == "" || s.server.erupeConfig.PatchServerManifest == "") {
|
||||||
if (s.server.erupeConfig.PatchServerManifest != "" && s.server.erupeConfig.PatchServerFile != "") || s.client == PS3 {
|
bf.WriteUint8(uint8(SIGN_EABORT))
|
||||||
bf.WriteUint8(2)
|
return bf.Data()
|
||||||
} else {
|
|
||||||
bf.WriteUint8(0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bf.WriteUint8(uint8(SIGN_SUCCESS))
|
||||||
|
bf.WriteUint8(2) // patch server count
|
||||||
bf.WriteUint8(1) // entrance server count
|
bf.WriteUint8(1) // entrance server count
|
||||||
bf.WriteUint8(uint8(len(chars)))
|
bf.WriteUint8(uint8(len(chars)))
|
||||||
bf.WriteUint32(tokenID)
|
bf.WriteUint32(tokenID)
|
||||||
bf.WriteBytes([]byte(sessToken))
|
bf.WriteBytes([]byte(sessToken))
|
||||||
bf.WriteUint32(uint32(channelserver.TimeAdjusted().Unix()))
|
bf.WriteUint32(uint32(channelserver.TimeAdjusted().Unix()))
|
||||||
if s.client == PS3 {
|
if s.client == PS3 {
|
||||||
ps.Uint8(bf, fmt.Sprintf(`ps3-%s.zerulight.cc`, s.server.erupeConfig.Language), false)
|
ps.Uint8(bf, fmt.Sprintf("%s/ps3", s.server.erupeConfig.PatchServerManifest), false)
|
||||||
ps.Uint8(bf, fmt.Sprintf(`ps3-%s.zerulight.cc`, s.server.erupeConfig.Language), false)
|
ps.Uint8(bf, fmt.Sprintf("%s/ps3", s.server.erupeConfig.PatchServerFile), false)
|
||||||
} else {
|
} else {
|
||||||
if s.server.erupeConfig.PatchServerManifest != "" && s.server.erupeConfig.PatchServerFile != "" {
|
|
||||||
ps.Uint8(bf, s.server.erupeConfig.PatchServerManifest, false)
|
ps.Uint8(bf, s.server.erupeConfig.PatchServerManifest, false)
|
||||||
ps.Uint8(bf, s.server.erupeConfig.PatchServerFile, false)
|
ps.Uint8(bf, s.server.erupeConfig.PatchServerFile, false)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if strings.Split(s.rawConn.RemoteAddr().String(), ":")[0] == "127.0.0.1" {
|
if strings.Split(s.rawConn.RemoteAddr().String(), ":")[0] == "127.0.0.1" {
|
||||||
ps.Uint8(bf, fmt.Sprintf("127.0.0.1:%d", s.server.erupeConfig.Entrance.Port), false)
|
ps.Uint8(bf, fmt.Sprintf("127.0.0.1:%d", s.server.erupeConfig.Entrance.Port), false)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user