Store: Buy Weapons and Shields, and selling
This commit is contained in:
parent
5ef3243c41
commit
07246dcdb2
@ -10,8 +10,11 @@ type PlayerEntry = {
|
|||||||
Player : Player
|
Player : Player
|
||||||
}
|
}
|
||||||
|
|
||||||
let mongo = MongoClient("mongodb://localhost:27017")
|
//let connString = "mongodb://localhost:27017"
|
||||||
let db = mongo.GetDatabase("degenz-game")
|
let connString = "mongodb+srv://joe:mtmu3XXe3crUfXdO@stage.2hyxh.mongodb.net/degenz?retryWrites=true&w=majority"
|
||||||
|
|
||||||
|
let mongo = MongoClient(connString)
|
||||||
|
let db = mongo.GetDatabase("degenz")
|
||||||
let players = db.GetCollection<PlayerEntry>("players")
|
let players = db.GetCollection<PlayerEntry>("players")
|
||||||
|
|
||||||
let tryFindPlayer (id : uint64) : Async<Player option> =
|
let tryFindPlayer (id : uint64) : Async<Player option> =
|
||||||
@ -38,13 +41,6 @@ let removePlayer (memberId : uint64) =
|
|||||||
|> Async.Ignore
|
|> Async.Ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
let updateAttacks (playerId : uint64) (attacks : Attack array) =
|
|
||||||
async {
|
|
||||||
let filter = Builders<PlayerEntry>.Filter.Eq((fun e -> e.Player.DiscordId), playerId)
|
|
||||||
let update = Builders<PlayerEntry>.Update.Set((fun e -> e.Player.Attacks), attacks)
|
|
||||||
return! players.UpdateOneAsync(filter, update) |> Async.AwaitTask |> Async.Ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
let updatePlayer player =
|
let updatePlayer player =
|
||||||
async {
|
async {
|
||||||
let filter = Builders<PlayerEntry>.Filter.Eq((fun e -> e.Player.DiscordId), player.DiscordId)
|
let filter = Builders<PlayerEntry>.Filter.Eq((fun e -> e.Player.DiscordId), player.DiscordId)
|
||||||
|
@ -24,7 +24,7 @@ let attack (ctx : InteractionContext) (target : DiscordUser) =
|
|||||||
let updatedAttacks =
|
let updatedAttacks =
|
||||||
attacker.Attacks
|
attacker.Attacks
|
||||||
|> removeExpiredActions (TimeSpan.FromMinutes(15)) (fun (atk : Attack) -> atk.Timestamp)
|
|> removeExpiredActions (TimeSpan.FromMinutes(15)) (fun (atk : Attack) -> atk.Timestamp)
|
||||||
do! DbService.updateAttacks attacker.DiscordId updatedAttacks
|
do! DbService.updatePlayer <| { attacker with Attacks = updatedAttacks }
|
||||||
if updatedAttacks.Length < 2 then
|
if updatedAttacks.Length < 2 then
|
||||||
let builder = DiscordInteractionResponseBuilder()
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
builder.AddEmbed (constructEmbed "Pick the hack you wish to use.") |> ignore
|
builder.AddEmbed (constructEmbed "Pick the hack you wish to use.") |> ignore
|
||||||
|
@ -15,7 +15,7 @@ type HackerGame() =
|
|||||||
member this.AttackCommand (ctx : InteractionContext, [<Option("target", "The player you want to hack")>] target : DiscordUser) =
|
member this.AttackCommand (ctx : InteractionContext, [<Option("target", "The player you want to hack")>] target : DiscordUser) =
|
||||||
Commands.attack ctx target
|
Commands.attack ctx target
|
||||||
|
|
||||||
[<SlashCommand("defend", "Create a passive defense that will last a certain amount of time")>]
|
[<SlashCommand("defend", "Create a passive defense that will last 24 hours")>]
|
||||||
member this.DefendCommand (ctx : InteractionContext) = Commands.defend ctx
|
member this.DefendCommand (ctx : InteractionContext) = Commands.defend ctx
|
||||||
|
|
||||||
let config = DiscordConfiguration()
|
let config = DiscordConfiguration()
|
@ -15,7 +15,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Commands.fs" />
|
<Compile Include="Commands.fs" />
|
||||||
<Compile Include="Program.fs" />
|
<Compile Include="HackerBattle.fs" />
|
||||||
<Content Include="paket.references" />
|
<Content Include="paket.references" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<RootNamespace>PlayerRegistration</RootNamespace>
|
<RootNamespace>PlayerRegistration</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Program.fs" />
|
<Compile Include="PlayerInteractions.fs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include=".dockerignore" />
|
<Content Include=".dockerignore" />
|
||||||
|
@ -6,8 +6,8 @@ open DSharpPlus.Entities
|
|||||||
open DSharpPlus.SlashCommands
|
open DSharpPlus.SlashCommands
|
||||||
|
|
||||||
type ItemType =
|
type ItemType =
|
||||||
| Weapon = 0
|
| Weapon
|
||||||
| Shield = 1
|
| Shield
|
||||||
|
|
||||||
type ActionClass =
|
type ActionClass =
|
||||||
| Network
|
| Network
|
||||||
@ -40,7 +40,6 @@ type Item = {
|
|||||||
let weaponInventory = [| Weapon.Virus ; Weapon.Ransom ; Weapon.DDos ; Weapon.Worm ; Weapon.Crack ; Weapon.Injection |]
|
let weaponInventory = [| Weapon.Virus ; Weapon.Ransom ; Weapon.DDos ; Weapon.Worm ; Weapon.Crack ; Weapon.Injection |]
|
||||||
let shieldInventory = [| Shield.Firewall ; Shield.PortScan ; Shield.Encryption ; Shield.Cypher ; Shield.Hardening ; Shield.Sanitation |]
|
let shieldInventory = [| Shield.Firewall ; Shield.PortScan ; Shield.Encryption ; Shield.Cypher ; Shield.Hardening ; Shield.Sanitation |]
|
||||||
|
|
||||||
|
|
||||||
let getClass =
|
let getClass =
|
||||||
function
|
function
|
||||||
| 0
|
| 0
|
||||||
@ -91,7 +90,7 @@ let createSimpleResponseAsync msg (ctx: InteractionContext) =
|
|||||||
}
|
}
|
||||||
|
|
||||||
let notYetAHackerMsg =
|
let notYetAHackerMsg =
|
||||||
createSimpleResponseAsync "You are not currently a hacker, first use the /redpill command to become one"
|
createSimpleResponseAsync "You are currently not a hacker, first use the /redpill command to become one"
|
||||||
|
|
||||||
let hackDescription = ""
|
let hackDescription = ""
|
||||||
|
|
||||||
|
112
Store/Program.fs
112
Store/Program.fs
@ -1,112 +0,0 @@
|
|||||||
open System
|
|
||||||
open System.Threading.Tasks
|
|
||||||
open DSharpPlus.Entities
|
|
||||||
open DSharpPlus
|
|
||||||
open DSharpPlus.EventArgs
|
|
||||||
open DSharpPlus.SlashCommands
|
|
||||||
open DegenzGame.Shared
|
|
||||||
open Emzi0767.Utilities
|
|
||||||
open Newtonsoft.Json
|
|
||||||
|
|
||||||
module Commands =
|
|
||||||
let constructItemButtons playerInfo (items : 'a array) =
|
|
||||||
items
|
|
||||||
|> Seq.map (fun item -> DiscordButtonComponent(ButtonStyle.Primary, $"{playerInfo}-{item}", $"{item}"))
|
|
||||||
|
|
||||||
let viewStore (ctx : InteractionContext) =
|
|
||||||
async {
|
|
||||||
let builder = DiscordInteractionResponseBuilder()
|
|
||||||
|
|
||||||
try
|
|
||||||
let file = System.IO.File.ReadAllText("Items.json")
|
|
||||||
JsonConvert.DeserializeObject<Item array>(file)
|
|
||||||
|> Array.groupBy (fun (i : Item) -> i.ItemType)
|
|
||||||
|> Array.iter (fun ( itemType , items ) ->
|
|
||||||
let itemList = items |> Array.map (fun i -> $"{i.Name} - {i.Cost} GBT") |> String.concat "\n"
|
|
||||||
builder.AddEmbed (constructEmbed $"{itemType}:\n{itemList}") |> ignore)
|
|
||||||
with _ -> builder.Content <- "System error preparing inventory for viewing"
|
|
||||||
|
|
||||||
builder.AsEphemeral true |> ignore
|
|
||||||
|
|
||||||
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|
|
||||||
|> Async.AwaitTask
|
|
||||||
} |> Async.StartAsTask
|
|
||||||
:> Task
|
|
||||||
|
|
||||||
let buyHack (ctx : InteractionContext) hackId =
|
|
||||||
async {
|
|
||||||
return ()
|
|
||||||
} |> Async.StartAsTask
|
|
||||||
:> Task
|
|
||||||
|
|
||||||
let buyShield (ctx : InteractionContext) shieldId =
|
|
||||||
async {
|
|
||||||
return ()
|
|
||||||
} |> Async.StartAsTask
|
|
||||||
:> Task
|
|
||||||
|
|
||||||
let sellItem (ctx : InteractionContext) =
|
|
||||||
async {
|
|
||||||
return ()
|
|
||||||
} |> Async.StartAsTask
|
|
||||||
:> Task
|
|
||||||
|
|
||||||
type EmptyGlobalCommandToAvoidFamousDuplicateSlashCommandsBug() = inherit ApplicationCommandModule ()
|
|
||||||
|
|
||||||
type Store() =
|
|
||||||
inherit ApplicationCommandModule ()
|
|
||||||
|
|
||||||
[<SlashCommand("store", "View items available for purchase")>]
|
|
||||||
member _.ViewStore (ctx : InteractionContext) = Commands.viewStore ctx
|
|
||||||
|
|
||||||
[<SlashCommand("buy-hack", "Purchase a hack attack you can use to earn GoodBoyTokenz")>]
|
|
||||||
member _.BuyHack (ctx : InteractionContext, [<Option("hack-id", "The ID of the hack you wish to purchase")>] hackId : Weapon) =
|
|
||||||
Commands.buyHack ctx hackId
|
|
||||||
|
|
||||||
[<SlashCommand("buy-shield", "Purchase a hack shield so you can protect your GoodBoyTokenz")>]
|
|
||||||
member this.BuyShield (ctx : InteractionContext, [<Option("shield-id", "The ID of the shield you wish to purchase")>] shieldId : Shield) =
|
|
||||||
Commands.buyShield ctx shieldId
|
|
||||||
|
|
||||||
[<SlashCommand("sell", "Sell an item in your inventory for GoodBoyTokenz")>]
|
|
||||||
member this.SellItem (ctx : InteractionContext) =
|
|
||||||
Commands.sellItem ctx
|
|
||||||
|
|
||||||
let handleButtonEvent (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) =
|
|
||||||
async {
|
|
||||||
let builder = DiscordInteractionResponseBuilder()
|
|
||||||
builder.IsEphemeral <- true
|
|
||||||
builder.Content <- $""
|
|
||||||
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|
|
||||||
|> Async.AwaitTask
|
|
||||||
} |> Async.StartAsTask
|
|
||||||
:> Task
|
|
||||||
|
|
||||||
let config = DiscordConfiguration()
|
|
||||||
config.Token <- "OTIyNDIyMDIyMTI1MDEwOTU1.YcBOcw.JxfW1CSIwEO7j6RbRFCnPZ-HoTk"
|
|
||||||
config.TokenType <- TokenType.Bot
|
|
||||||
config.Intents <- DiscordIntents.All
|
|
||||||
//config.MinimumLogLevel <- Microsoft.Extensions.Logging.LogLevel.Trace
|
|
||||||
|
|
||||||
let client = new DiscordClient(config)
|
|
||||||
|
|
||||||
client.add_ComponentInteractionCreated(AsyncEventHandler(handleButtonEvent))
|
|
||||||
|
|
||||||
let slash = client.UseSlashCommands()
|
|
||||||
|
|
||||||
// My server
|
|
||||||
slash.RegisterCommands<Store>(922419263275425832uL);
|
|
||||||
// Degenz
|
|
||||||
//slash.RegisterCommands<HackerGame>(922414052708327494uL);
|
|
||||||
|
|
||||||
client.ConnectAsync ()
|
|
||||||
|> Async.AwaitTask
|
|
||||||
|> Async.RunSynchronously
|
|
||||||
|
|
||||||
Task.Delay(-1)
|
|
||||||
|> Async.AwaitTask
|
|
||||||
|> Async.RunSynchronously
|
|
||||||
|
|
||||||
client.DisconnectAsync ()
|
|
||||||
|> Async.AwaitTask
|
|
||||||
|> Async.RunSynchronously
|
|
||||||
|
|
198
Store/Store.fs
Normal file
198
Store/Store.fs
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
open System
|
||||||
|
open System.Threading.Tasks
|
||||||
|
open DSharpPlus.Entities
|
||||||
|
open DSharpPlus
|
||||||
|
open DSharpPlus.EventArgs
|
||||||
|
open DSharpPlus.SlashCommands
|
||||||
|
open DegenzGame
|
||||||
|
open DegenzGame.Shared
|
||||||
|
open Emzi0767.Utilities
|
||||||
|
open Newtonsoft.Json
|
||||||
|
|
||||||
|
let store =
|
||||||
|
try
|
||||||
|
let file = System.IO.File.ReadAllText("Items.json")
|
||||||
|
JsonConvert.DeserializeObject<Item array>(file)
|
||||||
|
|> Array.groupBy (fun (i : Item) -> i.ItemType)
|
||||||
|
with _ -> [||]
|
||||||
|
|
||||||
|
let storeListing =
|
||||||
|
store
|
||||||
|
|> Array.map (fun ( itemType , items ) ->
|
||||||
|
let itemList = items |> Array.map (fun i -> $"{i.Name} - {i.Cost} GBT") |> String.concat "\n"
|
||||||
|
(constructEmbed $"{itemType}:\n{itemList}"))
|
||||||
|
|
||||||
|
module Commands =
|
||||||
|
let viewStore (ctx : InteractionContext) =
|
||||||
|
async {
|
||||||
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
|
|
||||||
|
builder.AddEmbeds(storeListing)
|
||||||
|
.AsEphemeral(true)
|
||||||
|
|> ignore
|
||||||
|
|
||||||
|
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|
||||||
|
|> Async.AwaitTask
|
||||||
|
} |> Async.StartAsTask
|
||||||
|
:> Task
|
||||||
|
|
||||||
|
let getItems itemType = store |> Array.find (fun ( t , _ ) -> t = itemType) |> snd
|
||||||
|
|
||||||
|
let buyHack (ctx : InteractionContext) hackId =
|
||||||
|
async {
|
||||||
|
let! playerResult = DbService.tryFindPlayer ctx.Member.Id
|
||||||
|
let weapons = getItems ItemType.Weapon
|
||||||
|
let weaponResult = weapons |> Array.tryFind (fun w -> w.Name = string hackId)
|
||||||
|
return!
|
||||||
|
match playerResult , weaponResult with
|
||||||
|
| Some player , Some item ->
|
||||||
|
async {
|
||||||
|
let newBalance = player.Bank - item.Cost
|
||||||
|
if newBalance >= 0.0f then
|
||||||
|
let playerHasItem = player.Weapons |> Array.exists (fun w -> item.Name = string w)
|
||||||
|
if not playerHasItem then
|
||||||
|
let weapon = weaponInventory |> Array.find (fun w -> item.Name = string w)
|
||||||
|
let p = { player with Bank = newBalance ; Weapons = Array.append [| weapon |] player.Weapons }
|
||||||
|
do! DbService.updatePlayer p
|
||||||
|
do! createSimpleResponseAsync $"Successfully purchased {item.Name}! You now have {newBalance} remaining" ctx
|
||||||
|
else
|
||||||
|
do! createSimpleResponseAsync $"You already own this item!" ctx
|
||||||
|
else
|
||||||
|
do! createSimpleResponseAsync $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT" ctx
|
||||||
|
}
|
||||||
|
| None , _ -> notYetAHackerMsg ctx
|
||||||
|
| _ -> createSimpleResponseAsync "Something is wrong" ctx
|
||||||
|
} |> Async.StartAsTask
|
||||||
|
:> Task
|
||||||
|
|
||||||
|
let buyShield (ctx : InteractionContext) shieldId =
|
||||||
|
async {
|
||||||
|
let! playerResult = DbService.tryFindPlayer ctx.Member.Id
|
||||||
|
let shieldResult =
|
||||||
|
getItems ItemType.Shield
|
||||||
|
|> Array.tryFind (fun w -> w.Name = string shieldId)
|
||||||
|
return!
|
||||||
|
match playerResult , shieldResult with
|
||||||
|
| Some player , Some item ->
|
||||||
|
async {
|
||||||
|
let newBalance = player.Bank - item.Cost
|
||||||
|
if newBalance >= 0.0f then
|
||||||
|
let playerHasItem = player.Shields |> Array.exists (fun w -> item.Name = string w)
|
||||||
|
if not playerHasItem then
|
||||||
|
let shield = shieldInventory |> Array.find (fun w -> item.Name = string w)
|
||||||
|
let p = { player with Bank = newBalance ; Shields = Array.append [| shield |] player.Shields }
|
||||||
|
do! DbService.updatePlayer p
|
||||||
|
do! createSimpleResponseAsync $"Successfully purchased {item.Name}! You now have {newBalance} remaining" ctx
|
||||||
|
else
|
||||||
|
do! createSimpleResponseAsync $"You already own this item!" ctx
|
||||||
|
else
|
||||||
|
do! createSimpleResponseAsync $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT" ctx
|
||||||
|
}
|
||||||
|
| None , _ -> notYetAHackerMsg ctx
|
||||||
|
| _ -> createSimpleResponseAsync "Something is wrong" ctx
|
||||||
|
} |> Async.StartAsTask
|
||||||
|
:> Task
|
||||||
|
|
||||||
|
let constructItemButtons playerInfo itemType (items : 'a array) =
|
||||||
|
items
|
||||||
|
|> Seq.map (fun item -> DiscordButtonComponent(ButtonStyle.Primary, $"{playerInfo}-{itemType}-{item}", $"{item}"))
|
||||||
|
|
||||||
|
let sellItem (ctx : InteractionContext) =
|
||||||
|
async {
|
||||||
|
let! playerResult = DbService.tryFindPlayer ctx.Member.Id
|
||||||
|
match playerResult with
|
||||||
|
| Some player ->
|
||||||
|
let hasInventoryToSell = Array.length player.Weapons + Array.length player.Shields > 0
|
||||||
|
if hasInventoryToSell then
|
||||||
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
|
builder.AddEmbed (constructEmbed "Pick the item you wish to sell.") |> ignore
|
||||||
|
|
||||||
|
Array.chunkBySize 3 player.Weapons
|
||||||
|
|> Array.iter
|
||||||
|
(fun wps ->
|
||||||
|
wps
|
||||||
|
|> Array.map (fun w ->
|
||||||
|
DiscordButtonComponent(ButtonStyle.Primary, $"{player.DiscordId}-Weapon-{w}", $"{w}"))
|
||||||
|
|> Seq.cast<DiscordComponent>
|
||||||
|
|> builder.AddComponents
|
||||||
|
|> ignore)
|
||||||
|
Array.chunkBySize 3 player.Shields
|
||||||
|
|> Array.iter
|
||||||
|
(fun shs ->
|
||||||
|
shs
|
||||||
|
|> Array.map (fun s ->
|
||||||
|
DiscordButtonComponent(ButtonStyle.Primary, $"{player.DiscordId}-Shield-{s}", $"{s}"))
|
||||||
|
|> Seq.cast<DiscordComponent>
|
||||||
|
|> builder.AddComponents
|
||||||
|
|> ignore)
|
||||||
|
|
||||||
|
builder.AsEphemeral true |> ignore
|
||||||
|
|
||||||
|
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|
||||||
|
|> Async.AwaitTask
|
||||||
|
else
|
||||||
|
do! createSimpleResponseAsync "You currently have no inventory to sell" ctx
|
||||||
|
| None -> do! notYetAHackerMsg ctx
|
||||||
|
return ()
|
||||||
|
} |> Async.StartAsTask
|
||||||
|
:> Task
|
||||||
|
|
||||||
|
let handleSellButtonEvents (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) =
|
||||||
|
async {
|
||||||
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
|
builder.IsEphemeral <- true
|
||||||
|
builder.Content <- $"{event.Id}"
|
||||||
|
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|
||||||
|
|> Async.AwaitTask
|
||||||
|
} |> Async.StartAsTask
|
||||||
|
:> Task
|
||||||
|
|
||||||
|
type EmptyGlobalCommandToAvoidFamousDuplicateSlashCommandsBug() = inherit ApplicationCommandModule ()
|
||||||
|
|
||||||
|
type Store() =
|
||||||
|
inherit ApplicationCommandModule ()
|
||||||
|
|
||||||
|
[<SlashCommand("store", "View items available for purchase")>]
|
||||||
|
member _.ViewStore (ctx : InteractionContext) = Commands.viewStore ctx
|
||||||
|
|
||||||
|
[<SlashCommand("buy-hack", "Purchase a hack attack you can use to earn GoodBoyTokenz")>]
|
||||||
|
member _.BuyHack (ctx : InteractionContext, [<Option("hack-id", "The ID of the hack you wish to purchase")>] hackId : Weapon) =
|
||||||
|
Commands.buyHack ctx hackId
|
||||||
|
|
||||||
|
[<SlashCommand("buy-shield", "Purchase a hack shield so you can protect your GoodBoyTokenz")>]
|
||||||
|
member this.BuyShield (ctx : InteractionContext, [<Option("shield-id", "The ID of the shield you wish to purchase")>] shieldId : Shield) =
|
||||||
|
Commands.buyShield ctx shieldId
|
||||||
|
|
||||||
|
[<SlashCommand("sell", "Sell an item in your inventory for GoodBoyTokenz")>]
|
||||||
|
member this.SellItem (ctx : InteractionContext) =
|
||||||
|
Commands.sellItem ctx
|
||||||
|
|
||||||
|
let config = DiscordConfiguration()
|
||||||
|
config.Token <- "OTIyNDIyMDIyMTI1MDEwOTU1.YcBOcw.JxfW1CSIwEO7j6RbRFCnPZ-HoTk"
|
||||||
|
config.TokenType <- TokenType.Bot
|
||||||
|
config.Intents <- DiscordIntents.All
|
||||||
|
//config.MinimumLogLevel <- Microsoft.Extensions.Logging.LogLevel.Trace
|
||||||
|
|
||||||
|
let client = new DiscordClient(config)
|
||||||
|
|
||||||
|
client.add_ComponentInteractionCreated(AsyncEventHandler(handleSellButtonEvents))
|
||||||
|
|
||||||
|
let slash = client.UseSlashCommands()
|
||||||
|
|
||||||
|
// My server
|
||||||
|
slash.RegisterCommands<Store>(922419263275425832uL);
|
||||||
|
// Degenz
|
||||||
|
//slash.RegisterCommands<HackerGame>(922414052708327494uL);
|
||||||
|
|
||||||
|
client.ConnectAsync ()
|
||||||
|
|> Async.AwaitTask
|
||||||
|
|> Async.RunSynchronously
|
||||||
|
|
||||||
|
Task.Delay(-1)
|
||||||
|
|> Async.AwaitTask
|
||||||
|
|> Async.RunSynchronously
|
||||||
|
|
||||||
|
client.DisconnectAsync ()
|
||||||
|
|> Async.AwaitTask
|
||||||
|
|> Async.RunSynchronously
|
||||||
|
|
@ -6,7 +6,7 @@
|
|||||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Program.fs" />
|
<Compile Include="Store.fs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include=".dockerignore" />
|
<Content Include=".dockerignore" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user