Help on Making a Daily, Self-Updating Shop?

Yeah, that’s what I was trying to get at in my previous reply - updating a data store if the seed in it doesn’t match the seed for the current day. Basically, what you said.

Let’s say that the seed for the previous day is 2020519, and then 5:00 PST hits. The seed becomes 2020520, and the servers try to update. So, if one server updates the data store, the other ones running at the same time wouldn’t have to, right, because of the conditional?

The only reason why I’m kinda confused about this is because I’m thinking that all of the servers running would see the old key because all of them are checking at the same time (so nothing would be updated yet), and then all of them would try to update it. Unless, there’s some sort of latency so only one server is able to update it, so the other ones wouldn’t have to because the data store is already updated.

I’ll be back, I have to go now

This just gave me an idea that was so simple! Basically, what I can do is regenerate the shop items separately, using a time increment of let’s say like 1 hour (just to not exhaust the data store), and then just have the shop update to whatever’s in the data store when a new day hits.

And yeah, the limitation to this is that I’d always need a server running. But, if I just lowered the time increment, then by the time the shop updates again the values should already be something different. So, I’ll go with this as the solution for now. Thanks!

Edit: This is still the solution, I just thought of a smarter way to do this.
I can just connect the item generation/update function to PlayerAdded, with a cooldown, so that as long as 1 person joins/stays in the game longer than the cooldown, the shop will rotate by itself.

Yes, there could be an issue if a bunch of servers access one key at the same time. That’s why I don’t recommend it. Theoretically, a bunch of servers would try to update the value using UpdateAsync, and they would then see that the value has already been updated and would stop. But in reality, something may break because of the limitations.

see “game limits”

So then do you have any ideas on how to send out a value only once (from any server) and then have all the other servers update without changing the value?

I was thinking of making ID’s for each server and using them in some way, but I’m stumped and can’t flesh out any ideas.

(preferably without using external services, unless it’s a universal time)

How it would work is at 2am (or some other time there won’t be a lot of servers online), the servers would all check for that new data in the data store. One server would see that the data is old and would update it. Read up on UpdateAsync if you need to. This idea could still break, though. Also, perhaps you can use some kind of server instance ID to make only one server change the data store value. I’m not familiar with those functions.

Again, I don’t think the data store thing is a good idea unless you do it manually. Having each server instance check the current time (using os.time or os.date) and update the store on its own it much easier. And again, that random seed would be the same across all servers.

I agree with your opinion on my solution, it’s pretty risky. I’m gonna try to change my item generating format to a PRNG, and then find a way to implement weight into it. Then, from there it should be really easy.

1 Like

I’m not sure what PRNG is, but it must be pseudorandom for this to work. A true random number generator will have different results across servers (or it should, at least).

For using weight, if I understand what you mean, you can just use different ranges and call math.random multiple times as needed.

a = math.random(1, 10)
if a == 1
   --put common item on shop
end

b = math.random(1, 100)
if a == 1
   --put rare item on shop
end
1 Like

PRNG = Pseudorandom number generator

1 Like

I can’t believe I hadn’t thought of this. How would I manipulate math.random (or some other math function) to output the same number for every server?

1 Like

When 5pm occurs, use math.randomseed and pass in the current year and day of year as one number (maybe multiply by 100, I don’t know if it matters but it can’t hurt), and then put new items in the shop.

1 Like

I’ve made a similar system to what you are trying to do. Example code below. Definitely use the Random.new() object. I’d also make sure that your “syncedtime” module is using os.time()


local commonItems = {"Red Balloon", "Yellow Balloon", "Green Balloon", "Blue Balloon"}
local rareItems = {"Gold Balloon", "Rainbow Balloon"}

function getAvailableItems(day)
local rng = Random.new(day)
-- Use rng variable as much as you want inside this function, it should be completely deterministic as long as you use the same day parameter.
local shopItems = {}
for i=1, 3 do
if rng:NextNumber() < .1 then
local item = rareItems[rng:NextInteger(1,#rareItems)]
table.insert(shopItems, item)
else
local item = commonItems[rng:NextInteger(1,#commonItems)]
table.insert(shopItems, item)
end
end
return shopItems
end


local currentDay = nil
local currentShopItems = {}
local OFFSET = 0

while true do
local day = math.floor((os.time() + OFFSET) / (60*60*24))
if day ~= currentDay then
currentDay = day
currentShopItems = getAvailableItems(day)
print('Updated shop items')
end
wait(1)
end

I’m very sorry about the lack of indentation. I wrote this code by hand, and am not sure how to indent since tab doesn’t work here.

EDIT: Forgot to add a wait(1) to the while loop. Oof!

11 Likes

Thank so you much!! This is literally exactly what I’m trying to do. I’ll fuse my code and your code and test for results. All I’d have to do to add more rarities, I’m assuming, is to add more tables and more else-if’s inside of the conditional, right?

Okay so I just took a good look at this:

  • I could add more tables for more rarities
  • Change the end number in the for loop for how many items I want to be picked
  • Add more else-ifs and change the threshold (the < .1) to correspond with the rarity I want
4 Likes

Yeah, to be honest, you can use any sort of item picking you want. You can even have it return multiple tables, and use rng variable in different ways. Just be sure to use the rng variable for your determining source inside that function, and only inside that function.

2 Likes

Thank you so much man, I’ve been stumped on this for a few days now and I couldn’t find a way around it

3 Likes