Merge branch 'main' into profile-pins

This commit is contained in:
jvyden 2021-11-02 19:10:01 -04:00
commit 39bf8cfb35
No known key found for this signature in database
GPG key ID: 18BCF2BE0262B278
13 changed files with 629 additions and 13 deletions

View file

@ -1,4 +1,4 @@
on: [ push ]
on: [ push, pull_request ]
name: Continuous Integration
# Inspired by osu! lazer's CI

View file

@ -49,7 +49,7 @@ namespace LBPUnion.ProjectLighthouse.Tests
{
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/eula", loginResult.AuthTicket);
HttpResponseMessage response = await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/announce", loginResult.AuthTicket);
string responseContent = await response.Content.ReadAsStringAsync();
Assert.True(response.IsSuccessStatusCode);

View file

@ -76,6 +76,11 @@
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Affero/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCAS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCES/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCET/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCJB/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCJS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Braaains/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=brun/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ezoiar/@EntryIndexedValue">True</s:Boolean>
@ -85,8 +90,15 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=LBPU/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=lolcatftw/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mmpick/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mmpicks/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPEA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPHG/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCAS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCJS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCKS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Swingy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=thumbsup/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=UCAS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=unfavourite/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Unpublish/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=yourthumb/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View file

@ -45,7 +45,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
"[{\"StatusCode\":200},{\"Players\":[{\"PlayerId\":\"literally1984\",\"matching_res\":0},{\"PlayerId\":\"jvyden\",\"matching_res\":1}],\"Slots\":[[5,0]],\"RoomState\":\"E_ROOM_IN_POD\",\"HostMood\":\"E_MOOD_EVERYONE\",\"LevelCompletionEstimate\":0,\"PassedNoJoinPoint\":0,\"MoveConnected\":false,\"Location\":[\"127.0.0.1\"],\"BuildVersion\":289,\"Language\":1,\"FirstSeenTimestamp\":1427331263756,\"LastSeenTimestamp\":1635112546000,\"GameId\":1,\"NatType\":2,\"Friends\":[],\"Blocked\":[],\"RecentlyLeft\":[],\"FailedJoin\":[]}]"
);
if (bodyString[0] != '[') return this.BadRequest();
if (bodyString.Length == 0 || bodyString[0] != '[') return this.BadRequest();
IMatchData? matchData;
try

View file

@ -55,5 +55,20 @@ namespace LBPUnion.ProjectLighthouse.Controllers
return this.Ok(LbpSerializer.TaggedStringElement("slots", response, "hint_start", pageStart + Math.Min(pageSize, 30)));
}
[HttpGet("slots/mmpicks")]
public IActionResult TeamPickedSlots([FromQuery] int pageStart, [FromQuery] int pageSize)
{
IQueryable<Slot> slots = this.database.Slots
.Where(s => s.TeamPick)
.Include(s => s.Creator)
.Include(s => s.Location)
.OrderByDescending(s => s.LastUpdated)
.Skip(pageStart - 1)
.Take(Math.Min(pageSize, 30));
string response = Enumerable.Aggregate(slots, string.Empty, (current, slot) => current + slot.Serialize());
return this.Ok(LbpSerializer.TaggedStringElement("slots", response, "hint_start", pageStart + Math.Min(pageSize, 30)));
}
}
}

View file

@ -37,9 +37,17 @@ namespace LBPUnion.ProjectLighthouse.Helpers
public static LbpFileType DetermineFileType(byte[] data)
{
if (data.Length == 0) return LbpFileType.Unknown; // Can't be anything if theres no data.
using MemoryStream ms = new(data);
using BinaryReader reader = new(ms);
// Determine if file is a FARC (File Archive).
// Needs to be done before anything else that determines the type by the header
// because this determines the type by the footer.
string footer = Encoding.ASCII.GetString(BinaryHelper.ReadLastBytes(reader, 4));
if (footer == "FARC") return LbpFileType.FileArchive;
byte[] header = reader.ReadBytes(3);
return Encoding.ASCII.GetString(header) switch
@ -57,11 +65,7 @@ namespace LBPUnion.ProjectLighthouse.Helpers
private static LbpFileType determineFileTypePartTwoWeirdName(BinaryReader reader)
{
reader.BaseStream.Position = 0;
// Determine if file is FARC
string footer = Encoding.ASCII.GetString(BinaryHelper.ReadLastBytes(reader, 4));
if (footer == "FARC") return LbpFileType.FileArchive;
// Determine if file is JPEG
byte[] header = reader.ReadBytes(9);

View file

@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using LBPUnion.ProjectLighthouse.Types;
namespace LBPUnion.ProjectLighthouse.Helpers
{
public class GameVersionHelper
{
// https://www.serialstation.com/games/b89b4eb4-4e4c-4e54-b72b-f7f9dbfac125
public readonly string[] LittleBigPlanet1TitleIds =
{
"BCES00141",
"BCAS20091",
"BCUS98208",
"BCAS20078",
"BCJS70009",
"BCES00611",
"BCUS98148",
"BCAS20058",
"BCJS30018",
"UCAS40262",
"BCET70011",
"BCUS98199",
"BCJB95003",
"NPUA70045",
"NPEA00241",
"NPEA00147",
"NPHG00033",
"NPHG00035",
};
// https://serialstation.com/games/35e69aba-1872-4fd7-9d39-11ce75924040
public readonly string[] LittleBigPlanet2TitleIds =
{
"BCUS98249",
"BCES01086",
"BCAS20113",
"BCJS70024",
"BCAS20201",
"BCUS98245",
"BCES01345",
"BCJS30058",
"BCUS98372",
"BCES00850",
"BCES01346",
"BCUS90260",
"BCET70023",
"NPUA80662",
};
// https://www.serialstation.com/games/b62d53d9-fdff-4463-8134-64b81e1cbd50
// includes PS4 games
public readonly string[] LittleBigPlanet3TitleIds =
{
"CUSA00063",
"CUSA00693",
"CUSA00473",
"CUSA00810",
"CUSA00473",
"CUSA01072",
"CUSA00738",
"PCJS50003",
"BCES02068",
"BCAS20322",
"BCJS30095",
"BCES01663",
"CUSA00063",
"BCUS98362",
"PCKS90007",
"PCAS00012",
"CUSA00601",
"CUSA00810",
"CUSA00762",
"PCAS20007",
"CUSA00473",
"CUSA01077",
"CUSA01304",
};
public GameVersion FromTitleId(string titleId)
{
if (this.LittleBigPlanet1TitleIds.Contains(titleId)) return GameVersion.LittleBigPlanet1;
if (this.LittleBigPlanet2TitleIds.Contains(titleId)) return GameVersion.LittleBigPlanet2;
if (this.LittleBigPlanet3TitleIds.Contains(titleId)) return GameVersion.LittleBigPlanet3;
return GameVersion.Unknown;
}
}
}

View file

@ -0,0 +1,460 @@
// <auto-generated />
using LBPUnion.ProjectLighthouse;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace ProjectLighthouse.Migrations
{
[DbContext(typeof(Database))]
[Migration("20211102215859_RenameTeamPick")]
partial class RenameTeamPick
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 64)
.HasAnnotation("ProductVersion", "5.0.11");
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.Property<int>("HeartedProfileId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("HeartedUserId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedProfileId");
b.HasIndex("HeartedUserId");
b.HasIndex("UserId");
b.ToTable("HeartedProfiles");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.Property<int>("HeartedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("HeartedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.Property<int>("QueuedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("QueuedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("QueuedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.Property<int>("SlotId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AuthorLabels")
.HasColumnType("longtext");
b.Property<string>("BackgroundHash")
.HasColumnType("longtext");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<long>("FirstUploaded")
.HasColumnType("bigint");
b.Property<string>("IconHash")
.HasColumnType("longtext");
b.Property<bool>("InitiallyLocked")
.HasColumnType("tinyint(1)");
b.Property<long>("LastUpdated")
.HasColumnType("bigint");
b.Property<bool>("Lbp1Only")
.HasColumnType("tinyint(1)");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<int>("MaximumPlayers")
.HasColumnType("int");
b.Property<int>("MinimumPlayers")
.HasColumnType("int");
b.Property<bool>("MoveRequired")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.HasColumnType("longtext");
b.Property<string>("ResourceCollection")
.HasColumnType("longtext");
b.Property<string>("RootLevel")
.HasColumnType("longtext");
b.Property<int>("Shareable")
.HasColumnType("int");
b.Property<bool>("SubLevel")
.HasColumnType("tinyint(1)");
b.Property<bool>("TeamPick")
.HasColumnType("tinyint(1)");
b.HasKey("SlotId");
b.HasIndex("CreatorId");
b.HasIndex("LocationId");
b.ToTable("Slots");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.Property<int>("CommentId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Message")
.HasColumnType("longtext");
b.Property<int>("PosterUserId")
.HasColumnType("int");
b.Property<int>("TargetUserId")
.HasColumnType("int");
b.Property<int>("ThumbsDown")
.HasColumnType("int");
b.Property<int>("ThumbsUp")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("CommentId");
b.HasIndex("PosterUserId");
b.HasIndex("TargetUserId");
b.ToTable("Comments");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("UserId");
b.ToTable("LastMatches");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("X")
.HasColumnType("int");
b.Property<int>("Y")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Locations");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.Property<int>("ScoreId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("PlayerIdCollection")
.HasColumnType("longtext");
b.Property<int>("Points")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("ScoreId");
b.HasIndex("SlotId");
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<string>("UserToken")
.HasColumnType("longtext");
b.HasKey("TokenId");
b.ToTable("Tokens");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Biography")
.HasColumnType("longtext");
b.Property<string>("BooHash")
.HasColumnType("longtext");
b.Property<int>("CommentCount")
.HasColumnType("int");
b.Property<bool>("CommentsEnabled")
.HasColumnType("tinyint(1)");
b.Property<int>("FavouriteSlotCount")
.HasColumnType("int");
b.Property<int>("FavouriteUserCount")
.HasColumnType("int");
b.Property<int>("Game")
.HasColumnType("int");
b.Property<int>("HeartCount")
.HasColumnType("int");
b.Property<string>("IconHash")
.HasColumnType("longtext");
b.Property<int>("Lists")
.HasColumnType("int");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<int>("LolCatFtwCount")
.HasColumnType("int");
b.Property<int>("PhotosByMeCount")
.HasColumnType("int");
b.Property<int>("PhotosWithMeCount")
.HasColumnType("int");
b.Property<string>("Pins")
.HasColumnType("longtext");
b.Property<string>("PlanetHash")
.HasColumnType("longtext");
b.Property<int>("ReviewCount")
.HasColumnType("int");
b.Property<int>("StaffChallengeBronzeCount")
.HasColumnType("int");
b.Property<int>("StaffChallengeGoldCount")
.HasColumnType("int");
b.Property<int>("StaffChallengeSilverCount")
.HasColumnType("int");
b.Property<string>("Username")
.HasColumnType("longtext");
b.Property<string>("YayHash")
.HasColumnType("longtext");
b.HasKey("UserId");
b.HasIndex("LocationId");
b.ToTable("Users");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser")
.WithMany()
.HasForeignKey("HeartedUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("HeartedUser");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
b.Navigation("Location");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster")
.WithMany()
.HasForeignKey("PosterUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target")
.WithMany()
.HasForeignKey("TargetUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Poster");
b.Navigation("Target");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Location");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace ProjectLighthouse.Migrations
{
public partial class RenameTeamPick : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "MMPick",
table: "Slots",
newName: "TeamPick");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "TeamPick",
table: "Slots",
newName: "MMPick");
}
}
}

View file

@ -115,9 +115,6 @@ namespace ProjectLighthouse.Migrations
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<bool>("MMPick")
.HasColumnType("tinyint(1)");
b.Property<int>("MaximumPlayers")
.HasColumnType("int");
@ -142,6 +139,9 @@ namespace ProjectLighthouse.Migrations
b.Property<bool>("SubLevel")
.HasColumnType("tinyint(1)");
b.Property<bool>("TeamPick")
.HasColumnType("tinyint(1)");
b.HasKey("SlotId");
b.HasIndex("CreatorId");

View file

@ -16,6 +16,8 @@ namespace LBPUnion.ProjectLighthouse.Serialization
public static string StringElement(KeyValuePair<string, object> pair) => $"<{pair.Key}>{pair.Value}</{pair.Key}>";
public static string StringElement(string key, bool value) => $"<{key}>{value.ToString().ToLower()}</{key}>";
public static string StringElement(string key, object value) => $"<{key}>{value}</{key}>";
public static string TaggedStringElement

View file

@ -0,0 +1,10 @@
namespace LBPUnion.ProjectLighthouse.Types
{
public enum GameVersion
{
LittleBigPlanet1,
LittleBigPlanet2,
LittleBigPlanet3,
Unknown,
}
}

View file

@ -93,7 +93,7 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels
public long LastUpdated { get; set; }
[XmlIgnore]
public bool MMPick { get; set; }
public bool TeamPick { get; set; }
public string SerializeResources()
{
@ -121,7 +121,7 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels
LbpSerializer.StringElement("moveRequired", this.MoveRequired) +
LbpSerializer.StringElement("firstPublished", this.FirstUploaded) +
LbpSerializer.StringElement("lastUpdated", this.LastUpdated) +
LbpSerializer.StringElement("mmpick", this.MMPick);
LbpSerializer.StringElement("mmpick", this.TeamPick);
return LbpSerializer.TaggedStringElement("slot", slotData, "type", "user");
}