Merge branch 'main' into feature/event-tent

This commit is contained in:
stratic-dev
2024-03-11 20:16:20 +00:00
9 changed files with 90 additions and 38 deletions

View File

@@ -1,29 +1,30 @@
# List of AUTHORS who contributed over time to the Erupe project
# List of authors who contributed to Erupe
## Point of current development
The project is currently developed under https://github.com/ZeruLight/Erupe
## History of development
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)
* 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 is assigned for each commit within the git history, which is stored in these git repos:
* https://github.com/ZeruLight/Erupe
* https://github.com/Ellie42/Erupe
* https://github.com/Ellie42/Erupe
* https://github.com/ricochhet/Erupe-Legacy
* https://github.com/xl3lackout/Erupe
Note there is a divergence between Ellie42s branch and xl3lackout where history has been lost.
Unfortunately, we have no detailed information on the history of the Erupe pre-2022
if somebody can provide information, please contact us, so that we can make this history available.
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 Erupe before 2022.
If somebody can provide information, please contact us, so that we can make this history available.
## Exceptions with third-party libraries
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.
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.

View File

@@ -1,6 +1,6 @@
# Erupe
## Client Compatiblity
## Client Compatibility
### Platforms
- PC
- PlayStation 3
@@ -34,15 +34,15 @@ If you want to modify or compile Erupe yourself, please read on.
## 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
We source control the following schemas:
- Initialisation Schemas: These initialise the application database to a clean install from a specific version.
- Update Schemas: These are update files they should be ran in order of version to get to the latest 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.
- Bundled Schemas: These are demo reference files to allow servers to be able to roll their own shops, distributions gachas and scenarios set ups.
- Initialization Schema: This initializes the application database to a specific version (9.1.0).
- 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 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 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.

View File

@@ -31,8 +31,8 @@ func (m *MsgMhfUpdateGuacot) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Clien
m.AckHandle = bf.ReadUint32()
m.EntryCount = bf.ReadUint16()
bf.ReadUint16() // Zeroed
var temp Goocoo
for i := 0; i < int(m.EntryCount); i++ {
var temp Goocoo
temp.Index = bf.ReadUint32()
for j := 0; j < 22; j++ {
temp.Data1 = append(temp.Data1, bf.ReadInt16())

View 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;

View File

@@ -51,6 +51,8 @@ type Guild struct {
MemberCount uint16 `db:"member_count"`
RankRP uint32 `db:"rank_rp"`
EventRP uint32 `db:"event_rp"`
RoomRP uint16 `db:"room_rp"`
RoomExpiry time.Time `db:"room_expiry"`
Comment string `db:"comment"`
PugiName1 string `db:"pugi_name_1"`
PugiName2 string `db:"pugi_name_2"`
@@ -153,6 +155,8 @@ SELECT
g.name,
rank_rp,
event_rp,
room_rp,
COALESCE(room_expiry, '1970-01-01') AS room_expiry,
main_motto,
sub_motto,
created_at,
@@ -706,7 +710,7 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
}
bf.WriteUint32(uint32(response))
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:
s.server.db.Exec("UPDATE guilds SET recruiting=false WHERE id=$1", guild.ID)
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
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:
// TODO: Where does this go?
quantity := uint16(pkt.Data1.ReadUint32())
bf.WriteBytes(handleDonateRP(s, quantity, guild, 2))
case mhfpacket.OperateGuildDonateEvent:
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?
s.server.db.Exec(`UPDATE guild_characters SET rp_today=rp_today+$1 WHERE character_id=$2`, quantity, s.charID)
case mhfpacket.OperateGuildEventExchange:
@@ -794,20 +799,37 @@ func handleChangePugi(s *Session, outfit uint8, guild *Guild, num int) {
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.WriteUint32(0)
saveData, err := GetCharacterSaveData(s, s.charID)
if err != nil {
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(&currentRP)
if currentRP+amount >= 30 {
amount = 30 - currentRP
resetRoom = true
}
}
saveData.RP -= amount
saveData.Save(s)
updateSQL := "UPDATE guilds SET rank_rp = rank_rp + $1 WHERE id = $2"
if isEvent {
updateSQL = "UPDATE guilds SET event_rp = event_rp + $1 WHERE id = $2"
switch _type {
case 0:
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.WriteUint32(uint32(saveData.RP))
return bf.Data()
@@ -1001,8 +1023,8 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint8(limit)
bf.WriteUint32(55000)
bf.WriteUint32(0)
bf.WriteUint16(0) // Changing Room RP
bf.WriteUint32(uint32(guild.RoomExpiry.Unix()))
bf.WriteUint16(guild.RoomRP)
bf.WriteUint16(0) // Ignored
if guild.AllianceID > 0 {

View File

@@ -148,9 +148,21 @@ func removeSessionFromStage(s *Session) {
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) {
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.
if s.stage != nil {
s.stage.Lock()
@@ -175,6 +187,12 @@ func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) {
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 {
delete(s.stage.reservedClientSlots, s.charID)
}
@@ -188,6 +206,12 @@ func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) {
func handleMsgSysMoveStage(s *Session, p mhfpacket.MHFPacket) {
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)
}

View File

@@ -59,7 +59,7 @@ func NewStage(ID string) *Stage {
objects: make(map[uint32]*Object),
objectIndex: 0,
rawBinaryData: make(map[stageBinaryKey][]byte),
maxPlayers: 4,
maxPlayers: 127,
}
return s
}

View File

@@ -38,25 +38,24 @@ func (s *Session) makeSignResponse(uid uint32) []byte {
return bf.Data()
}
bf.WriteUint8(uint8(SIGN_SUCCESS)) // resp_code
if (s.server.erupeConfig.PatchServerManifest != "" && s.server.erupeConfig.PatchServerFile != "") || s.client == PS3 {
bf.WriteUint8(2)
} else {
bf.WriteUint8(0)
if s.client == PS3 && (s.server.erupeConfig.PatchServerFile == "" || s.server.erupeConfig.PatchServerManifest == "") {
bf.WriteUint8(uint8(SIGN_EABORT))
return bf.Data()
}
bf.WriteUint8(uint8(SIGN_SUCCESS))
bf.WriteUint8(2) // patch server count
bf.WriteUint8(1) // entrance server count
bf.WriteUint8(uint8(len(chars)))
bf.WriteUint32(tokenID)
bf.WriteBytes([]byte(sessToken))
bf.WriteUint32(uint32(channelserver.TimeAdjusted().Unix()))
if s.client == PS3 {
ps.Uint8(bf, fmt.Sprintf(`ps3-%s.zerulight.cc`, s.server.erupeConfig.Language), 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.PatchServerManifest), false)
ps.Uint8(bf, fmt.Sprintf("%s/ps3", s.server.erupeConfig.PatchServerFile), false)
} else {
if s.server.erupeConfig.PatchServerManifest != "" && s.server.erupeConfig.PatchServerFile != "" {
ps.Uint8(bf, s.server.erupeConfig.PatchServerManifest, false)
ps.Uint8(bf, s.server.erupeConfig.PatchServerFile, false)
}
ps.Uint8(bf, s.server.erupeConfig.PatchServerManifest, false)
ps.Uint8(bf, s.server.erupeConfig.PatchServerFile, false)
}
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)